在微服务架构中,由于服务实例数量多、位置动态变化,需要一套机制来管理服务的位置信息,也就是注册中心。
Nacos与Eureka有相同点,也有不同之处,可以从以下几点来描述:
Nacos与Eureka都对外暴露了Rest风格的API接口,用来实现服务注册、发现等功能
# 服务注册
POST /eureka/apps/{appID}
Content-Type: application/json
{
"instance": {
"instanceId": "user-service-001",
"hostName": "192.168.1.100",
"app": "USER-SERVICE",
"ipAddr": "192.168.1.100",
"port": {"$": 8080, "@enabled": "true"},
"securePort": {"$": 443, "@enabled": "false"},
"status": "UP"
}
}
# 服务发现
GET /eureka/apps/{appID}
Accept: application/json
# 心跳续约
PUT /eureka/apps/{appID}/{instanceID}
# 服务下线
DELETE /eureka/apps/{appID}/{instanceID}
# 服务注册
POST /nacos/v1/ns/instance
Content-Type: application/x-www-form-urlencoded
serviceName=user-service&ip=192.168.1.100&port=8080&namespaceId=dev&groupName=DEFAULT_GROUP&ephemeral=true
# 服务发现
GET /nacos/v1/ns/instance/list?serviceName=user-service&namespaceId=dev&groupName=DEFAULT_GROUP
# 心跳续约
PUT /nacos/v1/ns/instance/beat
serviceName=user-service&ip=192.168.1.100&port=8080&beat={"state":"up"}
# 服务下线
DELETE /nacos/v1/ns/instance?serviceName=user-service&ip=192.168.1.100&port=8080
可以看到两者虽然都是Rest风格的接口,但是仍然有差别
Nacos的实例有永久和临时实例之分;而Eureka只支持临时实例
对于Nacos的永久实例,即使实例宕机,服务信息仍保留在注册中心,恢复后可快速重新提供服务,而Eureka只有临时实例,实例宕机后会被注册中心删除,需要重新注册,因此Nacos的可以选择性地提高某些服务数据的安全性,更加灵活
Nacos对临时实例采用心跳模式检测,对永久实例采用主动请求来检测;Eureka只支持心跳模式
临时实例:
客户端
服务端
非临时实例:
因此与eureka相比,Nacos与Eureka在临时实例上都是基于心跳模式实现,差别不大,主要是心跳周期不同,eureka是30秒,Nacos是5秒。
另外,Nacos支持永久实例,而Eureka不支持,Eureka只提供了心跳模式的健康监测,而没有主动检测功能。
Nacos支持定时拉取和订阅推送两种模式;Eureka只支持定时拉取模式,而且两者的定时拉取模式也略有差异
Nacos的拉取模式采用自适应间隔+指数退避策略,是一个通过递归提交方式实现的定时任务
服务拉取成功 →按正常(自适应)节奏继续
服务拉取失败→ 放慢节奏(指数退避)
恢复后 → 立即回到正常节奏
//UpdateTask定时任务的对应部分
@Override
public void run() {
long delayTime = DEFAULT_DELAY;
try {
// ... 获取和更新服务信息的逻辑 ...
// ... 检查订阅状态和实例列表 ...
// 服务拉取成功 → 使用服务端建议的间隔时间,按正常节奏继续
delayTime = serviceObj.getCacheMillis();
resetFailCount(); // 恢复后 → 立即回到正常节奏状态
} catch (Throwable e) {
incFailCount(); // 服务拉取失败 → 增加失败计数,准备放慢节奏
NAMING_LOGGER.warn("[NA] failed to update serviceName: " + serviceName, e);
} finally {
// 服务拉取失败 → 放慢节奏(指数退避),给系统喘息时间
executor.schedule(this, Math.min(delayTime << failCount, DEFAULT_DELAY * 60), TimeUnit.MILLISECONDS); //递归提交
}
}
同时服务端会根据服务变更频率动态调整拉取间隔
而Eureka的拉取模式则是固定间隔+指数退避
服务拉取成功 →按正常(固定)节奏继续,这里的正常节奏可以在配置文件中配置
服务拉取失败→ 放慢节奏(指数退避)
恢复后 → 立即回到正常节奏
Nacos的服务端在各处对服务进行变更操作时,会同时发布服务变更事件,监听器监听到后,就会准备数据(同样是调用doSrvIpxt())通过UDP推送给所有已注册的客户端
因此与Eureka相比,Nacos的订阅模式服务状态更新更及时,消费者更容易及时发现服务列表的变化,剔除故障服务。拉取模式也更智能,可以适应不同频率的的服务变更