
看到一个问题说 Nginx 的 upstream 不就是负载均衡嘛配几台后端机器请求自动分发和 Nacos、Eureka 这些注册中心干的事有什么本质区别为什么还要额外引入一整套服务注册发现的东西这个问题热度挺高其实这个问题问得挺好好因为很多人对这个似是而非感觉挺明白面试问他他又不知道怎么组织语言。Nginx和注册中心解决的他就不是一个问题啊Nginx 解决的是「请求该转发给谁」属于转发规则注册中心解决的是「后端服务实例的状态」属于实时状态感知。Nginx 负载均衡的不足Nginx 负载均衡缺点很明显实例列表是写死的Nginx 做负载均衡的配置大家都见过非常的简单upstream order-service{ server192.168.1.10:8080; server192.168.1.11:8080; server192.168.1.12:8080; } server{ location/api/orders{ proxy_passhttp://order-service; } }三台机器轮询转发服务数量少、实例基本不变动的情况下这完全没问题。问题是这个列表是静态的写死在配置文件里了。我每次后端实例变化比如扩容加机器、缩容摘机器、某台挂了就需要修改配置文件然后执行nginx -s reload如果部署了多台 Nginx每台都得改比较麻烦。机器少的时候这还能接受微服务都几十个服务打底、每个服务多个实例、还要支持弹性扩缩容靠手工改配置上个线那肯定要通宵啊Nginx 感知不到实例挂了Nginx 有被动健康检查机制后端连续返回错误时会把那台机器暂时摘掉。但这个机制有个前提必须有真实请求打过去失败了才能发现这台机器有问题。举个具体场景T1和T2的请求是用真实用户的流量去试错的在这段时间内所有打到 .11 的请求全部超时。注册中心的机制不一样服务实例启动后会持续向注册中心发送心跳默认 5 秒一次。心跳超时没收到注册中心直接把这个实例从注册表里摘掉。消费方下次拉取实例列表时这个实例就已经不在了整个过程不需要用真实流量去探路。Nginx 开源版没有主动健康检查商业版 Nginx Plus 有你也可以装nginx_upstream_check_module来补但那又引入了额外的运维负担问题只是转移了没有根本解决。弹性扩缩容 Nginx 做不到云环境下实例数量随时在变没法处理。业务高峰期自动扩容从 3 个实例扩到 20 个低峰期缩回去发版时滚动更新旧实例下线、新实例上线。K8s上的Pod被驱逐后在另一个节点重新调度IP 直接变了每一次变化Nginx 的upstream列表都需要同步更新。靠人工或脚本去改配置再reload这条路在自动化伸缩的场景下根本走不通根本不知道什么时候扩了、扩到哪台机器、IP 是什么。注册中心解决的就是这个问题实例启动时自动向注册中心注册自己的 IP 和端口实例下线时自动注销心跳断了自动被摘除。消费方持续订阅注册中心的变更实例列表实时更新整个过程不需要任何人工介入。对比一下两种流程一个是秒级自动完成一个是分钟级人工操作而且依赖人不出错。服务间调用全走 NginxNginx 是中心化的反向代理如果微服务之间的所有内部调用都经过 Nginx调用链路是服务A → Nginx → 服务B微服务架构下服务间调用非常频繁订单服务可能同时依赖库存服务、用户服务、优惠服务。如果所有内部流量都经 Nginx 中转Nginx 的吞吐量就成了整个系统的天花板而且多了一跳网络转发延迟也上去了。有了注册中心服务间调用走的是客户端负载均衡去掉 Nginx 这一跳之后延迟减少也消除了 Nginx 单点的风险。每个服务自己做负载均衡负载分散到各个调用方。Spring Cloud 里的 Spring Cloud LoadBalancer 就是干这个的。从 Nacos 或 Eureka 拉实例列表在客户端本地做负载均衡然后直接发请求过去。这些 Nginx 很难做注册中心不只是存 IP 和端口每个实例注册时还可以带元数据{ serviceName: order-service, ip: 192.168.1.10, port: 8080, metadata: { version: v2, region: shanghai, env: gray, weight: 80 } }基于这些元数据能做一些 Nginx 做不到或者实现起来很麻烦的事。灰度发布v1 和 v2 同时在线希望 95% 流量走 v15% 走 v2。在注册中心里给 v2 的实例打上versionv2的标签消费方路由规则按标签分流配置改一下就生效。Nginx 实现同样效果要写split_clients或者 Lua 脚本每次版本变更还得改配置再 reload。同机房优先调用服务在上海和北京都有实例希望上海的请求优先打上海的实例减少跨机房网络延迟。注册中心里每个实例带region元数据消费方按 region 就近路由直接配置路由策略就行。这个需求放在 Nginx 上要做额外的 geo 路由配置实现起来繁琐。动态权重调整某个实例性能差一些想降低它的流量权重。Nacos 控制台上直接改权重秒级生效不需要改任何配置文件。Nginx 改 weight 参数还得 reload。这几个需求在微服务场景下都很常见注册中心天然支持Nginx 要实现得费很大力气。Nginx 适合的场景Nginx 是必须要有的Nginx 和注册中心不是互相替代的关系分工不同。外部用户请求进入系统走 Nginx 或 API Gateway——统一入口、SSL 终止、限流、WAF这是 Nginx 的主场没有任何东西能替代它。微服务内部互相调用走注册中心加客户端负载均衡——动态发现实例、直连、去中心化。两者各管一段没有重叠也不需要选择。如果你的系统就三五个服务、实例基本不变动Nginx 完全够用不需要引入注册中心。注册中心是解决动态环境下实例管理问题的规模上不去的时候引入反而增加复杂度。