一、客户端自动注册实例流程
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.