第 8 章:访问应用程序:服务、路由和服务发现
本章围绕云原生应用的服务抽象、动态路由和服务发现展开,重点分析服务端与客户端负载均衡的区别,并通过实际案例说明如何构建可扩展、高可用的系统。
本章要点
- 单个服务代表多个应用程序实例
- 服务器端负载均衡与客户端负载均衡
- 服务实例的动态路由
- 服务发现机制
服务抽象与应用实例
在云原生环境中,一个服务通常由多个应用实例组成。每组实例作为一个逻辑实体运行,确保系统具备弹性和可扩展性。下图展示了示例系统中三个应用的多个实例。

在实际部署中,应用实例之间的连接方式决定了系统的健壮性。通过引入服务抽象,可以消除微服务之间的脆弱耦合。如下图所示,每组实例由逻辑实体表示,并用应用名称标记。

进一步抽象后,软件系统可视为一组相互连接的服务,每个服务由一组实例实现。

服务寻址、路由与服务发现
服务抽象的左侧是服务寻址和发现,右侧是路由和负载均衡。服务发现让客户端能通过名称找到服务,动态路由则将请求分发到不断变化的实例集合。

服务寻址、路由和服务发现的设计通常在部署阶段决定。理解这些技术有助于做出合理的架构选择。
服务示例分析
用 Google 进行搜索
当你在浏览器输入 www.google.com 时,DNS 将域名解析为 IP 地址,客户端通过该地址访问服务。实际部署中,IP 地址通常指向负载均衡器,由平台维护最新的实例路由列表。

博客聚合器示例
在博客聚合器中,相关帖子服务通过硬编码 IP 地址访问帖子服务,缺乏服务发现机制,导致部署脆弱。Kubernetes 通过标签和选择器动态维护实例列表,实现路由自动更新。

动态路由与负载均衡
服务端负载均衡
服务端负载均衡通过集中式组件(如 F5、nginx、云厂商负载均衡服务)分发请求。负载均衡器维护所有实例的路由列表,采用轮询或随机等算法分发流量。集中式实现技术成熟,配置简单,但需避免单点故障。

客户端负载均衡
客户端负载均衡将路由逻辑嵌入客户端,每个客户端实例维护自己的路由列表,直接向服务实例发送请求。该模式减少网络跳转,提升性能,但配置和升级更复杂,需结合具体框架(如 Netflix Ribbon、Istio Sidecar)。

路由刷新机制
路由列表需实时更新,反映实例的实际状态。平台通过健康检查和标签选择器自动维护路由表,确保请求始终分发到可用实例。

在 Minikube 环境中,Kube Proxy 作为负载均衡器,动态维护实例 IP 地址列表,实现服务端负载均衡。

服务发现机制
服务发现通过名称服务(如 DNS)将服务名称与 IP 地址解耦,提升系统弹性。名称服务优先保证可用性,可能存在短暂的不一致,客户端需实现重试机制以应对过期记录。

当 DNS 记录未及时更新时,客户端可通过重试和重新查询获取最新地址,提升访问成功率。

服务发现的实际应用
Web 服务发现
Web 应用通过 DNS 显式注册名称与 IP 地址映射,部署流程自动添加记录。如下图所示,CloudDNS 控制台展示了多条名称与 IP 地址的映射。

客户端负载均衡与服务发现
客户端负载均衡框架(如 Ribbon)允许通过服务名称引用依赖服务,服务发现协议用于更新客户端路由列表。服务注册与查询通常结合 Eureka 等服务发现框架实现。
例如,在 Spring 框架中,可通过注解和配置实现服务注册与发现,具体代码可参考 Ribbon 和 Eureka 官方文档。
Kubernetes 服务发现
Kubernetes 默认集成 CoreDNS,自动为服务注册名称与地址。所有 Pod 配置 CoreDNS 地址,服务名称解析自动完成。服务发现协议的注册和查询流程均由平台自动管理。

实际案例:消除脆弱配置
通过服务发现协议,服务间不再通过 IP 地址绑定,客户端可直接通过服务名称访问依赖服务。部署清单中环境变量统一采用服务名称,简化配置,提升弹性。
例如,相关帖子服务的环境变量可配置为:
CONNECTIONPOSTSCONTROLLER_POSTURL: "http://posts-svc/posts?userIds="
REDIS_HOSTNAME: "redis-svc"
SPRING_CLOUD_CONFIG_URI: "http://sccs-svc:8888"
Redis 服务端口号设置为 6379,服务名称与 CoreDNS 关联,实现东西向流量路由,提升内部通信效率。
具体部署和配置流程可参考 Kubernetes 官方文档和相关 YAML 清单示例。
总结
- 服务抽象将客户端与依赖服务松耦合,提升系统弹性。
- 负载均衡分为服务端和客户端两种模式,各有优缺点。
- 路由列表需动态自动更新,确保请求分发到可用实例。
- DNS 等名称服务是服务发现协议核心,需考虑最终一致性和重试机制。
- 服务发现协议显著提升云原生软件的部署弹性和可维护性。
参考文献
- Cloud Native Patterns - manning.com
- Kubernetes 官方文档 - kubernetes.io
- Spring Cloud 官方文档 - spring.io
- Netflix Ribbon - github.com
- Netflix Eureka - github.com