长连接说明
grpc 长连接, 连接期间连续多次发送数据包,连续多次响应数据包
NamingClientProxyDelegate 一个包装类,负责选择真实的NamingClientProxy
NamingGrpcClientProxy 使用Grpc通讯的代理实现
NamingHttpClientProxy 使用http1.0协议实现
健康检查
在之前的1.x版本中临时实例走Distro协议内存存储,客户端向注册中心发送心跳来维持自身healthy状态,持久实例走Raft协议持久化存储,服务端定时与客户端建立tcp连接做健康检查。
但是2.0版本以后持久化实例没有什么变化,但是2.0临时实例不在使用心跳,而是通过长连接是否存活来判断实例是否健康。
ConnectionManager负责管理所有客户端的长连接。
每3s检测所有超过20s没发生过通讯的客户端,向客户端发起ClientDetectionRequest探测请求,如果客户端在1s内成功响应,则检测通过,否则执行unregister方法移除Connection。
如果客户端持续与服务端通讯,服务端是不需要主动探活的
@Service
public class ConnectionManager extends Subscriber<ConnectionLimitRuleChangeEvent> {
@PostConstruct
public void start() {
// 启动不健康连接排除功能.
RpcScheduledExecutor.COMMON_SERVER_EXECUTOR.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// 统计过时(20s)连接
//1.获得需要剔除的IP和端口
//2.根据限制获取剔除的IP和端口
//3. 如果还是有需要剔除的客户端,则继续执行
//4.没有活动的客户端执行探测
//5.如果没有马上响应,则马上剔除
//6.剔除后发布ClientDisconnectEvent事件
}
});
}
}
ClientDisconnectEvent
会触发几个事件
1)Distro协议:同步移除的client数据
2)清除两个索引缓存:ClientServiceIndexesManager中Service与发布Client的关系;ServiceStorage中Service与Instance的关系
private void handleClientDisconnect(ClientEvent.ClientDisconnectEvent event) {
Client client = event.getClient();
for (Service each : client.getAllSubscribeService()) {
removeSubscriberIndexes(each, client.getClientId());
}
for (Service each : client.getAllPublishedService()) {
removePublisherIndexes(each, client.getClientId());
}
}
3)服务订阅:ClientDisconnectEvent会间接触发ServiceChangedEvent事件,将服务变更通知客户端。