缘由
在公司已用nacos,通过使用对比原来的zk发现舒服很多,在原来领导的提点下看下源码,有问题欢迎大家指出
目前已单机版为主(集群部署版怕看不懂,狗头保命)
环境
在github拉下最新nacos,我直接选择的develop分支。目前最新的Latest release是1.4.0
然后启动console模块,需要添加启动参数**-Dnacos.standalone=true**(表明你已单机模式启动)
启动起来才方便你断点调试
注册服务
先从注册开始,有注册才能消费
官网文档介绍注册方法
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080
先找到/instance 的POST接口 在InstanceController中
你会发现在naming模块中。该模块是负责服务发现注册之类的。
上边三个注解@CanDistro涉及到集群部署,且听下回分解
@Secured是从nacos1.2.0开始的注册权限验证(防止恶意注册),此处暂且不提,需要配置nacos.core.auth.enabled=true才会打开
目前说的都是临时实例模式,通过客户端配置ephemeral打开,临时实例模式,nacos为AP模式,
为了服务可用性降低了一致性,所以只适用于临时实例模式。
临时实例 | 持久化实例 |
---|---|
不会持久化到数据库 | 持久化数据库 |
心跳由客户端发起 | 心跳由服务端发起 |
AP模式 | CP模式 |
客户端掉线后直接删除 | 客户端掉线后标记为不健康 |
final Instance instance = parseInstance(request);
在这个方法中将IP与服务名serviceName封装起来
我们看下最关键的一行
serviceManager.registerInstance(namespaceId, serviceName, instance);
点击进去
/**
* Register an instance to a service in AP mode.
*
* <p>This method creates service or cluster silently if they don't exist.
*
* @param namespaceId id of namespace
* @param serviceName service name
* @param instance instance to register
* @throws Exception any error occurred in the process
*/
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
}
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
我们首先看第一行
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
/**
* Create service if not exist.
*
* @param namespaceId namespace
* @param serviceName service name
* @param local whether create service by local
* @param cluster cluster
* @throws NacosException nacos exception
*/
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
throws NacosException {
Service service = getService(namespaceId, serviceName);
if (service == null) {
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
service.setLastModifiedMillis(System.currentTimeMillis());
service.recalculateChecksum();
if (cluster != null) {
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
putServiceAndInit(service);
if (!local) {
addOrReplaceService(service);
}
}
}
在putServiceAndInit(service);开始注册健康检查
/**
* Init service.
*/
public void init() {
HealthCheckReactor.scheduleCheck(clientBeatCheckTask);
for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) {
entry.getValue().setService(this);
entry.getValue().init();
}
}
service初始化好后
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
在addInstance中
/**
* Add instance to service.
*
* @param namespaceId namespace
* @param serviceName service name
* @param ephemeral whether instance is ephemeral
* @param ips instances
* @throws NacosException nacos exception
*/
public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips)
throws NacosException {
String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
Service service = getService(namespaceId, serviceName);
synchronized (service) {
List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);
Instances instances = new Instances();
instances.setInstanceList(instanceList);
consistencyService.put(key, instances);
}
}
在第一行创建key中判断是否是临时实例
如果临时实例key中会包含字符串ephemeral,然后在consistencyService会通过判断key来决定放在临时实例service还是持久service
后面待续