引言
上一篇客户端初始化没有撸完,这篇继续。Nacos从2.0以后增加了对grpc的支持,代码中HTTP的代理初始化还有保留,我们注册发现通常为临时节点,这部分已由gRPC接管。可以对比下新旧逻辑的实现差异。
内容提要
HTTP代理初始化
HTTP心跳检测器
- HTTP心跳检测只适用于注册的节点持久节点,临时节点会使用grpc代理(HTTP的心跳检测默认废弃由grpc替代)
- 在初始化时客户端注册代理NamingClientProxy时,初始化了一个HTTP心跳器用于向Nacos Server发起心跳
- 在注册节点时通过向心跳执行器添加心跳任务addBeatInfo触发
- 心跳执行器通过每隔五秒中向Nacos Server发起HTTP请求
- 如果返回的server not found会向Nacos Server发起注册请求重新注册
UDP接受服务端推送
- Client通过UDP接受到nacos server推动的消息
- 如果服务端推送的为服务信息通过processServiceInfo处理逻辑见上篇,主要实例变更时的通知机制
- 如果dump类型,则客户端发送服务信息serviceInfoMap的ack信息到服务端
gRPC代理初始化
gRPC初始化逻辑概览
- gRPC 客户端代理的初始化主要逻辑为创建gRPC Client并启动
- 并注册ServerRequestHandler用于处理Nacos Server推送的NotifySubscriberRequest请求
- 注册ConnectionListener用于处理gRPC建立和断开连接事件
- 请求超时时间可以通过「namingRequestTimeout」设置,默认为3秒
gRPC Client启动逻辑
- gRPC Client启动逻辑主要在于建立与nacos server的grpc连接,其中两个守护线程一直在运行
- 守护线程1用于处理grpc连接的建立和关闭事件
- 守护线程2用于与nacos server的心跳保鲜,并负责异步建立grpc连接
- 守护线程2同时负责当nacos server的地址信息发生变更时重新与新server建立连接
- nacos server的地址变更通过grpc通道由server推送ConnectResetRequest到client
- grpc client只与nacos server集群中一台建立grpc连接。
源码分析
1 | public NamingClientProxyDelegate(String namespace, ServiceInfoHolder serviceInfoHolder, Properties properties, |
HTTP代理初始化
@注解7.4 Http代理的初始化,该代理主要在nacos 2.0以前版本使用,2.0之后通过grpc与nacos server通信。
1 | public NamingHttpClientProxy(String namespaceId, SecurityProxy securityProxy, ServerListManager serverListManager, |
HTTP心跳检测器
@注解7.4.1 初始化BeatReactor,用于向nacos server发送心跳
1 | public BeatReactor(NamingHttpClientProxy serverProxy, Properties properties) { |
接着一下这个执行器再做什么事情。
1 | public void addBeatInfo(String serviceName, BeatInfo beatInfo) { |
当通过addBeatInfo增加一个心跳信息BeatInfo时,执行器会创建BeatTask(Runnable)延迟5秒运行。
1 | class BeatTask implements Runnable { |
addBeatInfo调用时机,当节点在注册时如果实例为临时节点,则会创建心跳任务发起
1 | public void registerService(String serviceName, String groupName, Instance instance) throws NacosException { |
再跟踪下注册入口,判读使用哪个ClientProxy
1 |
|
小结: HTTP心跳检测只适用于注册的节点持久节点,临时节点会使用grpc代理,即HTTP的心跳检测默认废弃由grpc替代;在初始化时客户端注册代理NamingClientProxy时,初始化了一个HTTP心跳器用于向Nacos Server发起心跳;在注册节点时通过向心跳执行器添加心跳任务addBeatInfo触发;心跳执行器通过每隔五秒中向Nacos Server发起HTTP请求,如果返回的server not found会向Nacos Server发起注册请求重新注册;
UDP接受服务端推送
@注解7.4.2 初始化PushReceiver用于接受nacos server信息推送,使用UDP协议。
1 | public PushReceiver(ServiceInfoHolder serviceInfoHolder) { |
备注: PushReceiver实现Runnable接口,在构造方法中通过守护线程运行。
1 | public void run() { |
小结: Client通过UDP接受到nacos server推动的消息:@1如果推送的为服务信息通过processServiceInfo处理,逻辑见上篇;@2 如果dump类型,则客户端发送服务信息serviceInfoMap的ack信息到服务端。
HTTP重试次数
@注解7.4.3 client通过HTTP向Nacos Server请求的重试次数,默认为3次。可以通过「namingRequestDomainMaxRetryCount」指定
1 | public String reqApi(String api, Map<String, String> params, Map<String, String> body, List<String> servers, |
gRPC代理初始化
gRPC初始化逻辑概览
@注解7.5 下面接着gRPC 客户端代理的初始化逻辑
1 | public NamingGrpcClientProxy(String namespaceId, SecurityProxy securityProxy, ServerListFactory serverListFactory, |
1 | private void start(ServerListFactory serverListFactory, ServiceInfoHolder serviceInfoHolder) throws NacosException { |
小结: gRPC 客户端代理的初始化主要逻辑为创建gRPC Client并启动;并注册ServerRequestHandler用于处理Nacos Server推送的NotifySubscriberRequest请求;注册ConnectionListener用于处理gRPC建立和断开连接事件;另外,请求超时时间可以通过「namingRequestTimeout」设置,默认为3秒。
gRPC Client启动逻辑
@注解7.5.1 gRPC Client启动逻辑
1 | public final void start() throws NacosException { |
备注: grpc client启动时的逻辑:逻辑块@1 守护线程不断从阻塞队列eventLinkedBlockingQueue获取grpc连接/断开事件,并调用上文中注册的namingGrpcConnectionEventListener回调其onConnected/onDisConnect方法。 其中事件添加时机为:
grpc连接建立时,添加连接事件:
1 | // 连接成功添加ConnectionEvent |
grpc连接关闭时,添加关闭事件:
1 | private void closeConnection(Connection connection) { |
逻辑块@2 守护线程不断从阻塞队列reconnectionSignal获取重新连接事件(ReconnectContext)也就是更换nacos server的连接grpc通道:
阻塞队列没有重新连接事件:则做心跳保鲜检测,心跳频率为5秒。当超过5秒时会向Nacos Server发起健康检查,当返回不健康时,将grpc client标记为unhealthy;返回健康则刷新心跳时间lastActiveTimeStamp。
阻塞队列有重新连接事件:重连事件上下文reconnectContext的的server ip在我们设置的nacos server 列表则使用,否则改为随机选择nacos server ip地址,并与新server建立连接。
1 | protected void reconnect(final ServerInfo recommendServerInfo, boolean onRequestFail) { |
备注: 重新切换连接server逻辑:@1当检查失败grpc client会被标记为unhealthy这类型onRequestFail为true,重连时重新发起健康检查,如果检查成功,则退出本次重连。@2 获取重连的server地址和端口,并建立grpc连接,关闭当前缓存的旧连接并重定向到新连接,同时添加连接成功时间到阻塞队列。@3 一直重试直到连接建立成功,每次重试等待一些时间(100ms,200ms…最大为5秒)。
逻辑块@3 当异步与nacos server建立失败时,改为尝试同步建立连接。
逻辑块@4 如果连接建立成功添加连接事件到阻塞队列;连接建立失败发起异步建立连接请求;注册ConnectResetRequestHandler用于处理nacos server推送的重置连接请求;jvm退出时通过hook关闭grpc client。
小结: gRPC Client启动逻辑主要在于建立与nacos server的grpc连接,其中两个守护线程一直在运行。一个用于处理grpc连接的建立和关闭事件;一个用于与nacos server的心跳保鲜,并负责异步建立grpc连接,当nacos server的地址信息发生变更时负责重新与新server建立连接;grpc client只与nacos server集群中一台建立grpc连接。