本篇文章延续文章“如何理解Nacos的CP和AP架构模型?”,大家可以配套一起学习。
Nacos注册中心处理HTTP注册请求
在文章“如何理解Nacos的CP和AP架构模型?”中已经提到过,Nacos注册中心用Restful API InstanceController的方法register()处理HTTP类型的注册请求。
第1步,从HTTP请求HttpServletRequest中解析出待注册的实例Instance。
代码语言:javascript复制final Instance instance = HttpRequestInstanceBuilder.newBuilder()
.setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();
第2步,执行注册请求,这一步可以参考Nacos的InstanceOperatorClientImpl类的方法registerInstance()。
在执行注册之前,Nacos注册中心会判断实例Instance的类型(是否是临时实例),这一步主要是为了组装clientId,并用该clientId去标记实例Instance对应的应用服务的唯一性。
代码语言:javascript复制public static String getClientId(String address, boolean ephemeral) {
return address ID_DELIMITER ephemeral;
}
依据实例Instance解析出待注册的Service信息。
代码语言:javascript复制Service.newService(namespaceId, groupName, serviceNameNoGrouped, ephemeral);
第3步,调用接口ClientOperationService的实现类的方法registerInstance(),去注册实例Instance和Service信息。
代码语言:javascript复制void registerInstance(Service service, Instance instance, String clientId) throws NacosException;
其中接口ClientOperationService的实现类有三个,分别是:PersistentClientOperationServiceImpl类、EphemeralClientOperationServiceImpl类和ClientOperationServiceProxy类。
在 Nacos 中,PersistentClientOperationServiceImpl,EphemeralClientOperationServiceImpl 和 ClientOperationServiceProxy 是三种不同的客户端操作服务实现,它们之间的主要区别在于服务的持久性和生命周期。
- PersistentClientOperationServiceImpl:这是一个持久的客户端操作服务实现,意味着它的状态是持久化的。一旦被创建,它就会一直存在,直到显式地被删除或者 Nacos 服务器崩溃。这种类型的服务主要用于需要保存状态的情况,例如配置管理或者一些需要长期保存的信息。
- EphemeralClientOperationServiceImpl:这是一个非持久化的客户端操作服务实现,它的状态是不保存的。一旦客户端断开连接,这个服务就自动消失。这种类型的服务主要用于临时或者短期的服务,例如动态服务发现或者一些短暂的连接。
- ClientOperationServiceProxy:这是一个代理类型的客户端操作服务实现。它主要用于对远程服务的代理操作,例如调用远程服务的方法。它的行为和具体的远程服务相关,但是它本身并不持有状态。
以上三种客户端操作服务实现的主要区别在于它们的使用场景和生命周期。在 Nacos 中,你可以根据实际的需求选择合适的实现来使用。
关于Nacos注册中心如何选择以上三个类去做注册请求,我会在下一篇文章中去做分析。
利用PersistentClientOperationServiceImpl类去处理注册请求
假如采用持久化的方式,也就是利用PersistentClientOperationServiceImpl类去处理注册请求,具体过程如下。
第1步,构造注册写请求WriteRequest,这个写请求会存储序列化之后的实例信息和Service信息。
代码语言:javascript复制inal InstanceStoreRequest request = new InstanceStoreRequest();
request.setService(service);
request.setInstance(instance);
request.setClientId(clientId);
final WriteRequest writeRequest = WriteRequest.newBuilder().setGroup(group())
.setData(ByteString.copyFrom(serializer.serialize(request))).setOperation(DataOperation.ADD.name())
.build();
第2步,将写请求推送给CP一致性协议CPProtocol,当然Nacos注册中心的使用的是CPProtocol的实现类JRaftProtocol。
代码语言:javascript复制@Override
public Response write(WriteRequest request) throws Exception {
CompletableFuture<Response> future = writeAsync(request);
// Here you wait for 10 seconds, as long as possible, for the request to complete
return future.get(10_000L, TimeUnit.MILLISECONDS);
}
这样基于JRaft的一致性协议的服务就能够感知该写请求,并执行基于CP协议的一致性持久化操作。
第3步,Raft Server处理该写请求。
代码语言:javascript复制@Override
public CompletableFuture<Response> writeAsync(WriteRequest request) {
return raftServer.commit(request.getGroup(), request, new CompletableFuture<>());
}
注意这个Raft Server需要伴随着Nacos注册中心进程一起启动,关于这一块我会在接下来的文章中去给大家解读(具体可以关注JRaftServer类)。
当然大家也可以关注我的书Spring Cloud Alibaba微服务架构实战派上下册中关于Nacos的章节,里面也有详细的分析。
在Raft Server处理处理持久化的注册请求的过程中,Nacos注册中心就会实时的将该请求转发给Nacos集群中的Leader节点,当然该Leader节点就是采用CP算法选举出来的,这样就能确保整个Nacos集群中关于注册信息的CP一致性。
整个选举过程和执行过程是非常复杂的,本篇文章没办法全部讲解完成,我会在接下来的文章中去分析。