nacos服务注册流程

news2024/9/20 16:26:16

一、客户端自动注册实例流程

1.首先客户端需要引入服务发现包

  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  <version>2.2.6.RELEASE</version>

2.  NacosServiceRegistryAutoConfiguration 配置类

此类在spring-cloud-starter-alibaba-nacos-discovery客户包里面会自动在当前SPRINGBOOT容器注册

3.此配置类最核心的实体注册类为NacosAutoServiceRegistration,

查看此类的继承属性

发现此类继承于spring cloud common的AbstractAutoServiceRegistration抽象继承类,此类包含了与SPRING对接的一系列自动注册功能。并且实现了ApplicationListener接口,所以会监听SPRING WEB事件。

4.监听ServletWebServerInitializedEvent事件

5.AbstractAutoServiceRegistration自动更新服务端口

6.NacosAutoServiceRegistration更新端口,以及配置里面的分组,集群等信息。

7.跳到父类的注册方法

8.最终调用了NacosServiceRegistry.registry

9.接着触发了NacosNamingService.registerInstance

注意这里,如果是临时节点,还会触发客户端定时发送心跳。

这里已经跳到了nacos-client-1.4.2的包,相当于是具体注册中心客户端的实现。

10.接着跳到了NamingProxy.registerService,

11.最终发起HTTP调用请求,NamingProxy

public String reqApi(String api, Map<String, String> params, Map<String, String> body, List<String> servers,
            String method) throws NacosException {
        
        params.put(CommonParams.NAMESPACE_ID, getNamespaceId());
        
        if (CollectionUtils.isEmpty(servers) && StringUtils.isBlank(nacosDomain)) {
            throw new NacosException(NacosException.INVALID_PARAM, "no server available");
        }
        
        NacosException exception = new NacosException();
        
        if (StringUtils.isNotBlank(nacosDomain)) {
            for (int i = 0; i < maxRetry; i++) {
                try {
                    return callServer(api, params, body, nacosDomain, method);
                } catch (NacosException e) {
                    exception = e;
                    if (NAMING_LOGGER.isDebugEnabled()) {
                        NAMING_LOGGER.debug("request {} failed.", nacosDomain, e);
                    }
                }
            }
        } else {
            Random random = new Random(System.currentTimeMillis());
            int index = random.nextInt(servers.size());
            
            for (int i = 0; i < servers.size(); i++) {
                String server = servers.get(index);
                try {
                    return callServer(api, params, body, server, method);
                } catch (NacosException e) {
                    exception = e;
                    if (NAMING_LOGGER.isDebugEnabled()) {
                        NAMING_LOGGER.debug("request {} failed.", server, e);
                    }
                }
                index = (index + 1) % servers.size();
            }
        }
        
        NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}", api, servers, exception.getErrCode(),
                exception.getErrMsg());
        
        throw new NacosException(exception.getErrCode(),
                "failed to req API:" + api + " after all servers(" + servers + ") tried: " + exception.getMessage());
        
    }
    

如果是带域名,或者单机运行,则直接发起HTTP调用,如果是集群NACOS服务列表,则随机找到一台NACOS服务器发起请求。

12.客户端注册完成

二、服务端注册流程

1.下载1.4.2源码,本地启动

-Dnacos.standalone=true -Dnacos.home=e:\\nacos

启动类为com.alibaba.nacos.Nacos

2.服务端是SPRINGBOOT项目,找到控制器接口

3.首先进入InstanceController.register

4.进入ServiceManager.register,此类就是客户端服务实例的管理类,保存客户端实例的注册表。

@Component
public class ServiceManager implements RecordListener<Service> {
    
    /**
     * Map(namespace, Map(group::serviceName, Service)). 真正的注册表
     */
    private final Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
    
    private final LinkedBlockingDeque<ServiceKey> toBeUpdatedServicesQueue = new LinkedBlockingDeque<>(1024 * 1024);
    
    private final Synchronizer synchronizer = new ServiceStatusSynchronizer();
    
    private final Lock lock = new ReentrantLock();
    
    @Resource(name = "consistencyDelegate")
    //一致性协调协议 
    private ConsistencyService consistencyService;
    
    private final SwitchDomain switchDomain;
    
    private final DistroMapper distroMapper;
    
    private final ServerMemberManager memberManager;
    
    private final PushService pushService;
    
    private final RaftPeerSet raftPeerSet;

5.如果服务不存在,则会创建一个空的Service对象。

6.调试日志输出等级

因为服务端源码有多个线程协作,调试比较麻烦,建议看代码,然后加日志打印输出。

可以把naming的LOGBACK日志输出等级调成DEBUG

<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<included>

    <springProperty scope="context" name="logPath" source="nacos.logs.path" defaultValue="${user.home}/nacos/logs"/>
    <property name="LOG_HOME" value="${logPath}"/>

    <appender name="naming-server"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-server.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>2GB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>7GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level  [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="naming-raft"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-raft.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-raft.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>20MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>128MB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level  [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="naming-event"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-event.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-event.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>20MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>128MB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="naming-push"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-push.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-push.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>20MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>128MB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level  [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="naming-rt"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-rt.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-rt.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>1GB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level  [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-performance"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-performance.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-performance.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>512MB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level  [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-router"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-router.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-router.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>2GB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>7GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date|%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-cache"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-cache.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-cache.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>1GB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date|%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-device"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-device.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-device.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>2GB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>7GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date|%msg%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-tag"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-tag.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-tag.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>1GB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-debug"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-debug.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-debug.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>20MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>128MB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="naming-distro"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/naming-distro.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/naming-distro.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxFileSize>1GB</maxFileSize>
            <maxHistory>7</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <Pattern>%date %level  [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="CONSOLE2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>%date %level [%thread] [%C:%M:%L] %msg%n%n</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <logger name="com.alibaba.nacos.naming.main" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-server"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.raft" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-raft"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.distro" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-distro"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.event" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-event"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.push" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-push"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.rt" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-rt"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.performance" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-performance"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.router" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-router"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.cache" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-cache"/>
    </logger>
    <logger name="com.alibaba.nacos.naming.debug" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="naming-debug"/>
        <appender-ref ref="CONSOLE2"/>
    </logger>

</included>

7.业务日志APPENDER类分析

有一个统一的日志输出类,将各种业务分别用不同的APPENDER对象输出

public class Loggers {
    
//客户端推送
    public static final Logger PUSH = LoggerFactory.getLogger("com.alibaba.nacos.naming.push");
    
//心跳检测
    public static final Logger CHECK_RT = LoggerFactory.getLogger("com.alibaba.nacos.naming.rt");
    
//服务相关业务
    public static final Logger SRV_LOG = LoggerFactory.getLogger("com.alibaba.nacos.naming.main");
    
//通知事件,如新服务注册,变更,下线等。
    public static final Logger EVT_LOG = LoggerFactory.getLogger("com.alibaba.nacos.naming.event");
    

//一致性RAFT系统 CP
    public static final Logger RAFT = LoggerFactory.getLogger("com.alibaba.nacos.naming.raft");
    
//一致性协议 ,AP
    public static final Logger DISTRO = LoggerFactory.getLogger("com.alibaba.nacos.naming.distro");
    

//性能分析
    public static final Logger PERFORMANCE_LOG = LoggerFactory.getLogger("com.alibaba.nacos.naming.performance");

8.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1974636.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux中,MySQL存储引擎

存储引擎 在数据库中保存的是一张张有着千丝万缕关系的表&#xff0c;所以表设计的好坏&#xff0c;将直接影响着整个数据库。而在设计表的时候&#xff0c;最关注的一个问题是使用什么存储引擎。 MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种都…

【书生大模型实战营第三期 | 入门岛第1关-Linux基础知识】

学习心得&#xff1a;掌握InternStudio开发机与Linux基础 摘要 通过阅读这份详尽的InternStudio开发机与Linux基础教程&#xff0c;我对如何在云端算力平台上进行开发工作有了初步的了解。学习过程中&#xff0c;我不仅掌握了SSH远程连接和端口映射的技巧&#xff0c;还对Lin…

将后台传来的数据,转成easyui-tree所需格式

easyui 中文文档 EasyUI Tree组件需要一个包含特定属性&#xff08;如id, text, children等&#xff09;的JSON对象数组来初始化。 而后台返回的数据&#xff0c;它可能不是我们直接能拿来用的。 方式一&#xff1a;使用loadFilter函数处理来自Web Services的JSON数据。 $(#…

虚拟机处理yum缓存堆积问题

虚拟机处理yum缓存堆积问题 场景&#xff1a;虚拟机用的时间长了&#xff0c;网络不好&#xff0c;yum显示无法安装。此时我们因考虑到Yum软件包管理器的仓库配置文件地方对方太多而导致的问题。 解决方案&#xff1a; 一&#xff1a;首先检查虚拟机设置&#xff1a;确保设备…

东方古全艺藏委八一画展翰墨抒真情,当代艺术家挥笔颂军魂

在2024年这个意义非凡的夏日&#xff0c;随着“八一”建军节的脚步日益临近&#xff0c;一场旨在铭记历史、颂扬英雄、传承精神的书画盛宴——“中国东方文化研究会艺术品收藏交流委员会书画中心”举办的纪念中国人民解放军建军 97 周年书画邀请展&#xff0c;于8月1日在北京饭…

PTA—基础编程题目集(7-19)

7-19 支票面额 目录 题目描述 输入格式&#xff1a; 输出格式&#xff1a; 输入样例1&#xff1a; 输出样例1&#xff1a; 输入样例2&#xff1a; 输出样例2&#xff1a; 参考代码 总结 题目描述 一个采购员去银行兑换一张y元f分的支票&#xff0c;结果出纳员错给了…

Golang内存管理——堆分配

go语言的内存自动分配和回收的&#xff0c;因此内存的使用流程大致为&#xff1a;获取内存——分配内存——回收内存——再分配内存。 其中分配内存分为两方面&#xff0c;堆内存分配和栈内存分配&#xff0c;堆内存和栈内存是两种不同的分配方式&#xff0c;本篇文章主要是堆…

Leetcode刷题——9 基本数据结构(哈希表,并查集)

注&#xff1a;以下代码均为c 1. 哈希表 1.1 重复的DNA序列 什么数据结构既可以保存数据又可以计数&#xff1a;哈希表 vector<string> findRepeatedDnaSequences(string s) {unordered_map<string, int> hash;vector<string> ans;for(int i 0; i 10 &l…

Docker部署RabbitMQ指南

1. Rabbit概述 RabbitMQ是基于Erlang语言开发的开源消息通信中间件&#xff0c;官方地址&#xff1a;https://www.rabbitmq.com/。 2. 单机部署 我们在CentOS7虚拟机中使用Docker来安装。 2.1 下载镜像 方式一&#xff1a;在线拉取 docker pull rabbitmq:3-management 方…

Linux 内核源码分析---文件系统关联与字符设备操作

文件系统关联 设备文件都是由标准函数处理&#xff0c;类似于普通文件。设备文件也是通过虚拟文件系统来管理的&#xff0c;和普通文件都是通过完全相同的接口访问。 inode 中设备文件的成员数据 虚拟文件系统每个文件都关联到一个 inode&#xff0c;用于管理文件的属性。 …

RIP、OSPF 协议详解 / Stub/Totally Stub/NSSA/Totally NSSA 区域测试

注&#xff1a;原出处 https://javaforall.cn/204275.html 图片已挂。下文来自 腾讯云 全栈君 RIP、OSPF 协议详解 1、路由协议简介 在互联网中&#xff0c;一个自治系统 (AS) 是一个有权自主地决定在本系统中应采用何种路由协议的小型单位。这个网络单位可以是一个简单的网络…

我们如何提高 Baklib 的 SEO 性能

搜索引擎已经成为我们日常生活中不可或缺的一部分&#xff1b;谷歌甚至成为英语中的动词。因此&#xff0c;每个企业都需要关注其搜索引擎排名。在 Baklib&#xff0c;我们最近遇到了 SEO 排名的挑战。因此&#xff0c;在我们讨论这个问题之前&#xff0c;让我们先了解一下爬行…

宠物空气净化器可以除毛吗?室内浮毛空气净化器推荐

家里养了5只猫&#xff0c;满天飞的猫毛发&#xff0c;随风飘到各个角落&#xff0c;可以说苦不堪言。真的不建议养猫&#xff0c;除非你能接受空气中飞舞着浮毛&#xff0c;衣服、床、筷子、鼻子里全都是猫毛&#xff0c;拉臭臭有异味等等。感觉到处都被猫毛覆盖了&#xff0c…

【多线程】线程状态与并发三大特性的细节剖析

这篇文章主要用于对于多线程的一些查缺补漏。 一、 线程的状态 1&#xff0c;操作系统层面&#xff0c;线程的5种状态 关于线程有几种状态&#xff0c;有多种说法&#xff0c;5、6、7都有。 首先对于操作系统来说&#xff0c;只有5种状态&#xff0c;状态如下新建&#xff…

mac|安装hashcat(压缩包密码p解)

一、安装Macports&#xff08;如果有brew就不用这一步&#xff09; 根据官网文档&#xff1a;The MacPorts Project -- Download & Installation&#xff0c;安装步骤如下 1、下载MacPorts&#xff0c;这里我用的是tar.gz &#xff0c;可以通过keka&#xff08;keka安装在…

《pygame游戏开发实战指南》第三节 理解pygame中的坐标体系

pygame中的坐标体系非常的简单&#xff0c;其实就是一句话&#xff1a;任何对象的左上角都为坐标原点(0, 0)&#xff0c;向右为X轴正方向&#xff0c;向下为Y轴正方向。如下图所示。本节主要通过一些示例来带大家理解这一句话。如果读者已经理解的话&#xff0c;可以直接跳过这…

iPhone不下载APP直接投屏到电脑,这些投影设置你会用吗【电脑投影设置需添加】

最近小编一直在追唐朝诡事录之西行&#xff0c;太好看了&#xff0c;就是手机屏幕有点小&#xff0c;虽然也可以在电脑上看&#xff0c;但是小编心血来潮想投屏到此电脑看看&#xff0c;因此就写了这篇文章。 ①首先打开电脑的设置&#xff0c;打开系统 ②左侧栏中找到投影到此…

学习Java的日子 Day63 文件上传,文件下载,上传头像案例

文件上传下载 1.文件上传 文件上传的应用 比如个人信息的管理&#xff0c;上传头像 比如商品信息的管理&#xff0c;上传商品的图片 这些都需要通过浏览器客户端将图片上传到服务器的磁盘上 2.文件上传原理 所谓的文件上传就是服务器端通过request对象获取输入流&#xff0c;将…

VMware安装Centos虚拟机使用NAT模式无法上网问题处理

NAT模式无法上网问题处理 Centos7与Ubuntu使用同一个NAT网络&#xff0c;Ubuntu正常访问互联网&#xff0c;Centos无法正常访问。 处理方案&#xff1a; cd /etc/sysconfig/network-scripts vi ifcfg-ens33 修改配置项&#xff1a; 重启网络&#xff1a; service network resta…

vue的nextTick是下一次事件循环吗

如题&#xff0c;nextTick的回调是在下一次事件循环被执行的吗&#xff1f; 是不是下一次事件循环取决于nextTick的实现&#xff0c;如果是用的微任务&#xff0c;那么就是本次事件循环&#xff1b;否则如果用的是宏任务&#xff0c;那么就是下一次事件循环。 我们看下Vue3中…