服务端用InstanceController#beat方法接收心跳请求。
InstanceController#beat
这里会判断是否已经有实例,如果没有就创建实例,然后再开始检查心跳。public ObjectNode beat(HttpServletRequest request) throws Exception {
ObjectNode result = JacksonUtils.createEmptyJsonNode();
// 设置心跳时间,会直接改客户端的心跳时间
result.put(SwitchEntry.CLIENT_BEAT_INTERVAL, switchDomain.getClientBeatInterval());
String beat = WebUtils.optional(request, "beat", StringUtils.EMPTY);
// 其他略
// 通过namespaceId, serviceName, clusterName, ip, port获取Instance
Instance instance = serviceManager.getInstance(namespaceId, serviceName, clusterName, ip, port);
// 如果没有,则注册
if (instance == null) {
// 这个是通过beat判断的,如果是第一次,则beat有信息,就会创建clientBeat
// 如果不是第一次,正常instance不为空的,所以此时为空说明可能被移除了
if (clientBeat == null) {
result.put(CommonParams.CODE, NamingResponseCode.RESOURCE_NOT_FOUND);
return result;
}
// 其他略
// 注册
serviceManager.registerInstance(namespaceId, serviceName, instance);
}
// 从serviceMap缓存获取Service
Service service = serviceManager.getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.SERVER_ERROR,
"service not found: " + serviceName + "@" + namespaceId);
}
// 不是第一次,组装clientBeat
if (clientBeat == null) {
clientBeat = new RsInfo();
clientBeat.setIp(ip);
clientBeat.setPort(port);
clientBeat.setCluster(clusterName);
}
// 处理心跳
service.processClientBeat(clientBeat);
result.put(CommonParams.CODE, NamingResponseCode.OK);
if (instance.containsMetadata(PreservedMetadataKeys.HEART_BEAT_INTERVAL)) {
result.put(SwitchEntry.CLIENT_BEAT_INTERVAL, instance.getInstanceHeartBeatInterval());
}
result.put(SwitchEntry.LIGHT_BEAT_ENABLED, switchDomain.isLightBeatEnabled());
return result;
}
ServiceManager#getInstance
通过ip和端口获取实例public Instance get