本文讲的是v1.x版本的nacos服务注册原理,2.0改成grpc调用了,本文用的是2.0的版本,深入剖析一下nacos在注册时一些巧妙的设计和数据结构的选择。
源码流程
1.任务添加到阻塞队列
该接口是服务端接受注册的接口,服务注册就是通过该接口来实现的。
/**
* Register new instance.
*
* @param request http request
* @return 'ok' if success
* @throws Exception any error during register
*/
@CanDistro
@PostMapping
@Secured(action = ActionTypes.WRITE)
public String register(HttpServletRequest request) throws Exception {
// 拿到namespaceId
final String namespaceId = WebUtils
.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
// 拿到serviceName
final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
NamingUtils.checkServiceNameFormat(serviceName);
// 创建instance实例,用于注册
final Instance instance = HttpRequestInstanceBuilder.newBuilder()
.setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();
// core 注册。
getInstanceOperator().registerInstance(namespaceId, serviceName, instance);
return "ok";
}
1.x版本选择第二个实现类
进入到ServiceManager
/**
* 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);
checkServiceIsNull(service, namespaceId, serviceName);
// 核心逻辑
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
添加instance到服务中
/**
* 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) {
// 将服务实例比对,确定要更新、删除的instance
List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);
// 封装成instances对象
Instances instances = new Instances();
instances.setInstanceList(instanceList);
// 核心 放进注册表中
consistencyService.put(key, instances);
}
}
进入DistroConsistencyServiceImpl查看put方法
@Override
public void put(String key, Record value) throws NacosException {
// 核心onPut方法
onPut(key, value);
// If upgrade to 2.0.X, do not sync for v1.
if (ApplicationUtils.getBean(UpgradeJudgement.class).isUseGrpcFeatures()) {
return;
}
distroProtocol.sync(new DistroKey(key, KeyBuilder.INSTANCE_LIST_KEY_PREFIX), DataOperation.CHANGE,
DistroConfig.getInstance().getSyncDelayMillis());
}
/**
* Put a new record.
*
* @param key key of record
* @param value record
*/
public void onPut(String key, Record value) {
if (KeyBuilder.matchEphemeralInstanceListKey(key)