nacos 2.0 源码学习之服务注册
NamingFactory 实例化的过程

NamingFactory的初始化
NamingFactory 初始化有两种方式:
- 按照serverList初始化
- 传入Properties初始化
NamingFactory 工厂类中没有什么特殊的处理,仅用反射调用NacosNamingService的构造方法。
NacosNamingService 参数
namespace
服务的命名空间
logName
日志名称
serviceInfoHolder
服务列表
changeNotifier
实例变化通知时间器
clientProxy
请求nacos服务代理类
按照serverList初始化
先看一下源码NamingFactory.createNamingService(String serverList)
public static NamingService createNamingService(String serverList) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");//反射调用
Constructor constructor = driverImplClass.getConstructor(String.class);
NamingService vendorImpl = (NamingService) constructor.newInstance(serverList);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
}
}
按照Properties初始化
源码:
public static NamingService createNamingService(Properties properties) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
NamingService vendorImpl = (NamingService) constructor.newInstance(properties);
return vendorImpl;
} catch (Throwable e) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
}
}
NacosNamingService的初始化
NacosNamingService有两个构造方法,分别为:接收字符串的serverList和接收Properties的构造器。
最终都会调用init(Properties properties)方法。这个是初始化的关键代码。
private void init(Properties properties) throws NacosException {
ValidatorUtils.checkInitParam(properties);
this.namespace = InitUtils.initNamespaceForNaming(properties);//
InitUtils.initSerialization();
InitUtils.initWebRootContext(properties);
initLogName(properties);
this.changeNotifier = new InstancesChangeNotifier();//注册事件-实例变化通知
NotifyCenter.registerToPublisher(InstancesChangeEvent.class, 16384);
NotifyCenter.registerSubscriber(changeNotifier);
this.serviceInfoHolder = new ServiceInfoHolder(namespace, properties);
this.clientProxy = new NamingClientProxyDelegate(this.namespace, serviceInfoHolder, properties, changeNotifier);
}
- checkInitParam 检查context path.的合法性
- 初始化namespace,默认为:public
- 初始化JacksonUtils
- 初始化nacos远程连接url的上下文
- 初始化注册事件-实例变化通知
- 注册事件InstancesChangeEvent
- 初始化ServiceInfoHolder,后面文章会讲初始化过程
- 初始化NamingClientProxyDelegate
ServiceInfoHolder
属性
- serviceInfoMap 保存服务列表
- failoverReactor 故障发生器
- pushEmptyProtection 是否推空保护
先看源码
public ServiceInfoHolder(String namespace, Properties properties) {
initCacheDir(namespace);//设置cacheDir
if (isLoadCacheAtStart(properties)) {//是否加载本地磁盘
this.serviceInfoMap = new ConcurrentHashMap<String, ServiceInfo>(DiskCache.read(this.cacheDir));
} else {
this.serviceInfoMap = new ConcurrentHashMap<String, ServiceInfo>(16);
}
this.failoverReactor = new FailoverReactor(this, cacheDir);//故障转移落盘
this.pushEmptyProtection = isPushEmptyProtect(properties);//是否推空保护
}
private void initCacheDir(String namespace) {
String jmSnapshotPath = System.getProperty("JM.SNAPSHOT.PATH");
if (!StringUtils.isBlank(jmSnapshotPath)) {
cacheDir =
jmSnapshotPath + File.separator + "nacos" + File.separator + "naming" + File.separator + namespace;
} else {
cacheDir = System.getProperty("user.home") + File.separator + "nacos" + File.separator + "naming"
+ File.separator + namespace;
}
}
- 初始化故障落盘路径,默认为:~/nacos/naming/“namespace”
- 通过参数 namingLoadCacheAtStart 判断是否加载磁盘服务列表
- 初始化故障发生器FailoverReactor
- 设置 pushEmptyProtection 推空保护
FailoverReactor 故障发生器
属性
- failoverDir 故障后读取文件的路径
- serviceInfoHolder
- executorService 任务线程池
- serviceMap 服务列表
- switchParams 存放是否启动了故障读盘标识
- DAY_PERIOD_MINUTES= 24 * 60; 落盘任务启动间隔时间
初始化
public FailoverReactor(ServiceInfoHolder serviceInfoHolder, String cacheDir) {
this.serviceInfoHolder = serviceInfoHolder;
this.failoverDir = cacheDir + "/failover";
// init executorService
this.executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("com.alibaba.nacos.naming.failover");
return thread;
}
});
this.init();
}
public void init() {
executorService.scheduleWithFixedDelay(new SwitchRefresher(), 0L, 5000L, TimeUnit.MILLISECONDS);
executorService.scheduleWithFixedDelay(new DiskFileWriter(), 30, DAY_PERIOD_MINUTES, TimeUnit.MINUTES);
// backup file on startup if failover directory is empty.
executorService.schedule(new Runnable() {
@Override
public void run() {
try {
File cacheDir = new File(failoverDir);
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new IllegalStateException("failed to create cache dir: " + failoverDir);
}
File[] files = cacheDir.listFiles();
if (files == null || files.length <= 0) {
new DiskFileWriter().run();
}
} catch (Throwable e) {
NAMING_LOGGER.error("[NA] failed to backup file on startup.", e);
}
}
}, 10000L, TimeUnit.MILLISECONDS);
}
- 设置故障落盘文件标识 this.failoverDir = cacheDir + “/failover”;
- 设置任务调度线程池
- 启动SwitchRefresher线程为:立即执行,下次执行间隔5秒
- 启动服务列表落盘线程DiskFileWriter:延迟30分钟执行,间隔24小时
- 执行一次DiskFileWriter
SwitchRefresher
故障落盘标识批量,通过读取**~/nacos/naming/“namespace”/failover/00-00—000-VIPSRV_FAILOVER_SWITCH-000—00-00** 文件来设置failover-mode故障落盘标识。
File switchFile = new File(failoverDir + UtilAndComs.FAILOVER_SWITCH);
if (!switchFile.exists()) {
switchParams.put("failover-mode", "false");
NAMING_LOGGER.debug("failover switch is not found, " + switchFile.getName());
return;
}
long modified = switchFile.lastModified();
if (lastModifiedMillis < modified) {//判断文件修改时间,减少读取文件次数
lastModifiedMillis = modified;
String failover = ConcurrentDiskUtil.getFileContent(failoverDir + UtilAndComs.FAILOVER_SWITCH,
Charset.defaultCharset().toString());
if (!StringUtils.isEmpty(failover)) {
String[] lines = failover.split(DiskCache.getLineSeparator());
for (String line : lines) {
String line1 = line.trim();
if ("1".equals(line1)) {
switchParams.put("failover-mode", "true");
NAMING_LOGGER.info("failover-mode is on");
new FailoverFileReader().run();
} else if ("0".equals(line1)) {
switchParams.put("failover-mode", "false");
NAMING_LOGGER.info("failover-mode is off");
}
}
} else {
switchParams.put("failover-mode", "false");
}
}
DiskFileWriter
读取serviceInfoHolder.getServiceInfoMap(),循环写入**~/nacos/naming/“namespace”/**
- 文件名称为:groupName@@serviceName@@clusters
- 文件内容为json格式
NamingClientProxyDelegate
属性
- securityInfoRefreshIntervalMills 安全信息刷新时间
- serverListManager 服务列表
- serviceInfoUpdateService 服务更新service
- serviceInfoHolder
- httpClientProxy http代理工具类
- grpcClientProxy GRpc工具类
- securityProxy 与nacos连接加密代理服务
- executorService

6937

被折叠的 条评论
为什么被折叠?



