2. 服务发现与注册:Consul、Eureka、Nacos原理对比,客户端发现与服务端发现模式

说到微服务,服务发现是个绕不开的话题。我记得刚接触微服务那会儿,最头疼的就是服务之间怎么找到对方。你想想看,几十上百个服务实例,IP和端口都是动态的,总不能写死在配置文件里吧?

服务发现要解决的核心问题就两个:服务注册服务发现。说白了,就是让服务启动时告诉注册中心「我来了」,让调用方知道「你在哪」。今天我就把Consul、Eureka、Nacos这三个主流方案掰开揉碎讲清楚。

2.1 服务发现的两种模式

先聊模式,再聊工具。服务发现分两种:客户端发现服务端发现。这个选择会直接影响你的架构设计。

2.1.1 客户端发现模式

客户端发现,就是调用方自己从注册中心拉取服务列表,然后自己选一个实例去调用。Eureka就是典型的客户端发现模式。

我在项目中遇到过一个问题:某个服务有20个实例,客户端拉取列表后,每次随机选一个。结果有个实例CPU飙到90%,还是被随机选中,导致请求超时。嗯,这里要注意,客户端发现模式下,负载均衡的逻辑在客户端,你得自己实现健康检查和权重策略。

客户端发现的特点:

  • 调用方直接感知服务实例变化,延迟低
  • 没有额外的代理层,网络路径短
  • 每个客户端都要实现发现逻辑,语言绑定强
  • 适合同语言、同技术栈的团队

2.1.2 服务端发现模式

服务端发现,就是加一个中间层(比如负载均衡器),客户端只请求这个中间层,由它去查询注册中心并转发请求。Kubernetes的Service就是这种模式。

我曾经帮一个团队排查问题,他们用Nginx做服务端发现,结果Nginx的upstream配置更新有延迟,导致新上线的服务一直拿不到流量。说白了,服务端发现虽然对客户端友好,但中间层成了瓶颈和单点

对比维度 客户端发现 服务端发现
架构复杂度 低,无额外组件 高,需要负载均衡器
语言耦合 强,需集成SDK 弱,客户端无感知
运维成本 低,但客户端升级麻烦 高,需维护中间层
典型代表 Eureka, Consul Kubernetes, Nacos

2.2 三大注册中心原理对比

好,模式讲完了,咱们看看具体工具。Consul、Eureka、Nacos,这三个我都用过,各有各的脾气。

2.2.1 Eureka:AP原则的坚守者

Eureka是Netflix开源的,遵循AP原则(可用性+分区容忍性)。什么意思?就是宁可返回旧数据,也不能让服务不可用

Eureka的核心机制是自我保护模式。当心跳丢失比例超过阈值(默认15分钟内85%),Eureka会停止剔除服务实例。我遇到过最典型的情况:网络抖动导致大量服务心跳超时,Eureka直接进入自我保护,虽然有些实例已经挂了,但至少活着的服务还能正常调用。

我的建议:Eureka适合内部网络稳定的场景。如果你在公有云上跑,网络波动频繁,记得调大心跳间隔和自我保护阈值。

// Eureka客户端配置示例
eureka:
  instance:
    lease-renewal-interval-in-seconds: 10  # 心跳间隔
    lease-expiration-duration-in-seconds: 30  # 过期时间
  client:
    registry-fetch-interval-seconds: 5  # 拉取注册表间隔

2.2.2 Consul:CP原则与健康检查

Consul基于Raft协议,遵循CP原则(一致性+分区容忍性)。它用强一致性保证所有节点看到的服务列表是一样的。

Consul最让我喜欢的是它的健康检查机制。Eureka只检查心跳,Consul可以执行自定义脚本——比如检查HTTP接口返回200、检查磁盘空间、甚至执行一条SQL。我曾经用Consul的健康检查自动摘除数据库连接池满的服务实例,效果非常好。

避坑指南:Consul的强一致性是有代价的。当Leader节点挂了,重新选举期间(通常3-5秒),服务发现会不可用。我曾经在线上遇到过,刚好赶上大促流量高峰,那几秒的延迟导致大量请求失败。所以,对一致性要求不高的场景,慎用Consul

// Consul健康检查配置
{
  "service": {
    "name": "user-service",
    "port": 8080,
    "check": {
      "http": "http://localhost:8080/health",
      "interval": "10s",
      "timeout": "5s",
      "deregister_critical_service_after": "30s"
    }
  }
}

2.2.3 Nacos:AP+CP动态切换

Nacos是阿里巴巴开源的,它最牛的地方是支持AP和CP动态切换。你可以在创建服务时指定是临时实例(AP)还是持久化实例(CP)。

我个人习惯这样用:核心服务用CP模式,保证数据一致性;边缘服务用AP模式,追求高可用。Nacos还内置了配置中心,省去了单独部署配置中心的麻烦。

我记得有个项目,刚开始用Eureka,后来发现配置管理太分散,就迁移到了Nacos。迁移过程还算平滑,但要注意Nacos的数据持久化——默认用内嵌数据库,生产环境一定要切换到MySQL。

特性 Eureka Consul Nacos
一致性 AP CP AP/CP可切换
健康检查 心跳 心跳+自定义脚本 心跳+HTTP
配置中心 有(Key/Value) 有(强)
语言支持 Java为主 多语言 多语言
运维复杂度

2.3 选型建议

说了这么多,到底怎么选?我给出几个实际场景的推荐:

  • Spring Cloud全家桶用户:Eureka最省事,但注意它已经进入维护模式。新项目建议用Nacos。
  • 多语言、多技术栈:Consul的HTTP API和DNS接口最友好,任何语言都能调用。
  • 需要配置中心:直接上Nacos,省一个组件就是省一份运维成本。
  • Kubernetes环境:用K8s内置的Service发现就够了,除非你有跨集群的需求。

最后说一句:服务发现没有银弹。我见过用Eureka跑得飞起的,也见过被Consul坑惨的。关键是要理解每个工具的设计哲学,结合自己的业务场景做选择。嗯,今天就聊到这儿,下一章咱们聊聊配置管理。