正向代理反向代理负载均衡和API网关

如何管理成千上万的访客(用户请求)和内部员工(服务间调用)的流动,确保一切井然有序、安全高效?这就是今天要讨论的这套“交通管理系统”要解决的问题。

1. 概念

1.1 正向代理 (Forward Proxy)

一个位于客户端和原始服务器之间的服务器,为了从原始服务器获取内容,客户端向代理发送一个请求并指定目标,然后代理向原始服务器转交请求并将获得的内容返回给客户端。

关键点:它为客户端服务,隐藏了客户端的真实身份。

“一句话”类比:它就像你出国玩时用的“代购”。你想买一个国外的限定商品(访问某个网站),但你不能或不想亲自去。于是你找了当地的代购(正向代理),告诉他你要什么,他帮你买回来再交给你。对于国外的商家来说,他们只知道是代购在买,完全不知道你这位最终买家的存在。

重要性:

  • 访问控制与安全: 公司的网络通常会设置一个正向代理,只允许员工通过它访问外部互联网,便于审计和过滤不安全的内容。
  • 匿名访问: 隐藏客户端的 IP 地址,保护用户隐私。
  • 缓存: 缓存热门资源,加速多个客户端对同一资源的访问。

1.2 反向代理 (Reverse Proxy)

一个位于客户端和一组后端服务器之间的服务器。客户端只与反向代理通信,不知道也不关心后端的服务器是哪一台或哪几台。关键点:它为服务端服务,隐藏了服务端的真实身份和架构。

“一句话”类比:它就像一家大公司的总机/前台。你打电话给 400-123-4567(访问 a.com),接电话的是总机(反向代理)。你告诉总机你要找销售部(请求 /api/sales),总机就会把电话转接到销售部的某个具体分机(后台服务),但你全程都不知道那个分机的具体号码。

重要性:

  • 安全屏障: 保护后端服务器不直接暴露在公网,抵御攻击。
  • 负载均衡: 可以将请求分发到多个后端服务器。
  • SSL 终止: 集中处理 HTTPS 加解密,减轻后端服务器的负担。
  • 缓存与压缩: 缓存静态内容,压缩响应,提升性能。

1.3 负载均衡 (Load Balancer)

一种特殊且常见的反向代理,其核心任务是将网络流量高效地分发到后端的多台服务器上,以提高系统的处理能力、可用性和可靠性。

重要性:

  • 高可用性 (High Availability): 当一台服务器宕机时,负载均衡器会自动将流量切换到其他健康的服务器,服务不中断。
  • 水平扩展 (Scalability): 当流量增加时,只需简单地向服务器集群中添加更多服务器即可,无需改动客户端。

负载均衡器通常是反向代理的一种实现或核心功能。它通过不同的策略来分发流量。

  • 轮询 (Round Robin): 像发牌一样,依次分配给每个服务器。
  • 最少连接 (Least Connections): 分配给当前连接数最少的服务器。
  • IP 哈希 (IP Hash): 基于客户端 IP 地址计算哈希值,确保来自同一客户端的请求总是被发送到同一台服务器,这对于维持会话(Session)很有用。

1.4 API 网关 (API Gateway)

在微服务架构中,它是一个更高级、功能更丰富的反向代理,是所有外部客户端访问后端微服务的唯一入口。它不仅仅是转发流量,还处理了大量与业务相关的横切关注点。

“一句话”类比:如果反向代理是公司总机,API 网关就是“行政服务中心总管”。他不仅会帮你转接电话(路由),还会做访客登记(认证授权)、检查你的预约(速率限制)、帮你把需要跑腿多个部门的事情一次性办好(请求聚合),并记录下所有的来访信息(日志监控)。

重要性:

  • 简化客户端: 客户端只需与一个端点通信,无需知道后端有多少微服务以及它们的地址。
  • 解耦: 后端服务的重构、拆分、合并对客户端无感。
  • 中心化管理: 统一处理认证、授权、安全、监控、日志、缓存、速率限制、协议转换(如 HTTP 转 gRPC)等。

1.5 服务网格

一个用于处理服务之间(东西向流量)通信的专用基础设施层。它通过在每个服务旁部署一个轻量级代理(称为 Sidecar)来工作,这些代理组成了服务之间通信的“网格”。

“一句话”类比:它就像公司总部大楼内部的“智能通信管道系统”。每个部门办公室(微服务)门口都有一个智能收发器(Sidecar Proxy)。部门 A 要给部门 B 发送一份机密文件,只需把文件丢进自己门口的收发器。收发器会自动加密文件,确保B部门的收发器能收到,如果B正忙,它会稍后重试,并记录下这次通信。部门 A 和 B 的员工根本不需要关心这些复杂的通信细节。

重要性: 它将服务通信的复杂性(如服务发现、负载均衡、加密、重试、熔断、监控)从业务代码中剥离出来,让开发人员可以专注于业务逻辑。

1.6 总结

  • 正向代理用于保护客户端。反向代理旨在保护服务器。

  • 一个简单的应用可能只需要一个带负载均衡功能的反向代理。随着服务拆分得更细,再引入 API 网关。只有当微服务数量众多、调用关系极其复杂时,才考虑引入服务网格,因为它会带来额外的性能开销和运维复杂度。

  • 保持网关“薄”: API 网关的职责是处理通用逻辑,应避免在网关层实现过多的业务逻辑。否则,网关会演变成一个新的“单体应用”,成为瓶颈和故障点。

    现代 API 网关应该是轻量级的,只做通用能力,避免成为新的瓶颈。业务逻辑应该保留在各个微服务中。

2. API Gateway

2.1 作用和能力

API 网关的核心价值就是:为后端庞杂的微服务提供一个简洁、统一、可管理的门面,并把所有服务都需要的通用能力(如身份认证,监控报警/调用链追踪,限流隔离/熔断降级、安全、监控、限流)从业务代码中抽离出来,集中处理。

认证 (Authentication): 你是谁?

  • 做什么: 这是验证请求者身份的过程。就像进入公司大楼时,你需要刷门禁卡或人脸识别来证明你是公司的员工。
  • 网关如何做: 当一个请求到达 API 网关时,网关会检查请求中携带的“凭证”,比如请求头里的 Authorization: Bearer <JWT_TOKEN>。网关会验证这个 Token 是否有效、是否过期、签名是否正确。
  • “统一处理”的意义: 如果没有网关,每个微服务(用户服务、订单服务、商品服务)都需要自己去实现一遍验证 JWT Token 的逻辑。这不仅是巨大的代码重复,而且一旦 Token 逻辑变更(比如更换加密算法),所有服务都要修改和重新上线,简直是灾难。而有了网关,所有身份验证都在网关这一层统一完成。只有通过了身份验证的、合法的请求,才会被放行到后端的微服务。后端服务可以完全信任“凡是进来的请求,都已经是合法的已知用户”,从而大大简化了自身逻辑。

授权 (Authorization): 你能做什么?

  • 做什么: 这是验证一个已通过身份验证的用户,是否有权限执行某个特定操作。就像你虽然是公司员工(已认证),但你的门禁卡是否有权限进入 CEO 办公室。
  • 网关如何做: 这是你提出那个绝佳问题的关键所在!授权是分层的。网关通常负责粗粒度 (Coarse-Grained) 的授权。
  • 什么是粗粒度授权? 它是基于用户的角色或请求的宏观特征来进行判断,不关心具体的业务数据。例如,网关可以解析 JWT Token 中包含的roles: ["admin", "user"] 声明。然后配置一条规则:“所有访问路径 /admin/** 的请求,请求者的角色中必须包含 admin”。如果一个普通用户试图访问,网关会直接拒绝(返回 403 Forbidden),请求根本不会到达后端的管理服务。

2.2 用户授权不是应该需要在业务层做吗?

完全正确!但这和网关做授权并不矛盾。它们负责不同粒度的授权,协同工作。

层面授权类型回答的问题例子
API 网关粗粒度 (Coarse-Grained)“你是否有权敲这扇门?”“只有角色为 manager 的用户,才能访问 /api/approvals 这个路径。”
微服务 (业务层)细粒度 (Fine-Grained)“敲门进来后,你能否修改桌上这份具体的文件?”“用户张三(manager)想批准李四的请假单。张三是李四的直属上司吗?”
  1. API 网关做“门卫”:它负责面上的、基于角色和范围 (Scope) 的访问控制。它不知道“订单 ABC”和“订单 XYZ”的区别,但它知道只有“用户”角色的请求才能访问 /api/orders 路径。这是一种业务无关的授权。
  2. 微服务做“业务专家”:它负责具体的、与业务逻辑紧密相关的权限判断。当一个请求“查看订单 ABC”到达订单服务时,订单服务必须在自己的数据库里检查:当前这个用户 ID 是否就是订单 ABC 的所有者 ID。这个信息,API 网关无从知晓,也不应该知道。

这种分层授权的模式,既利用了网关实现了统一的安全策略,又保持了微服务内部业务逻辑的内聚和独立性,是一种非常优雅的架构实践。

2.3 BFF 层又是什么?(Backend For Frontend)

BFF(为前端服务的后端)是 API 网关模式的一种演进和细化。

想象一下,你的公司不仅有网站 (Web),还有 iOS App 和 Android App。

  • Web 端: 屏幕大,网络好,可以一次性显示一个订单的所有详细信息(用户信息、商品列表、物流状态),所以希望调用一个接口就返回所有数据。
  • App 端: 屏幕小,流量宝贵,可能首页只需要显示订单的概要(商品名、总价)。如果调用和 Web 一样的接口,会浪费大量流量去下载用不上的数据。

如果只有一个“一刀切”的通用 API 网关,很难同时完美地满足这两种截然不同的需求。

BFF 模式就是为此而生的:

我们不设一个统一的 API 网关,而是为每一种前端体验(或每一种客户端类型)提供一个专门的、量身定制的后端服务(BFF)。

  • BFF for Web: 专门服务于 Web 应用。它可能会调用用户、商品、物流三个微服务,将数据聚合、裁剪、重组成最适合 Web UI 展示的格式,然后一次性返回。
  • BFF for Mobile: 专门服务于移动 App。它可能只调用商品和订单服务,返回一个极简的数据结构,以节省流量。

BFF 和 API 网关的关系:

  • BFF 本质上就是一个 API 网关。它具备 API 网关的路由、聚合等所有能力。
  • 关键区别在于职责的专一性。通用 API 网关追求的是“统一”,而 BFF 追求的是“定制”和“适配”。
  • 在实践中,它们可以共存。你可以有一个“边缘网关”(Edge Gateway)负责全局的防火墙、限流和路由,然后它再根据请求来源(是来自 Web 域名还是 App 的 API 域名)将请求转发给不同的 BFF。此时,BFF 更专注于为前端做数据编排,而边缘网关更专注于安全和流量管理。

3. 技术演进路线

演进的核心驱动力: 随着应用从单体 (Monolith) 走向微服务 (Microservices),流量的模式从简单的“用户 -> 应用”变成了复杂的“用户 -> 入口 -> 服务A -> 服务B/C …”的网状结构。我们的工具也必须随之进化。

3.1 技术层级、工作层与主流工具对比

组件技术层级 / 抽象度工作网络层 (OSI)演进角色 / 解决的核心问题主流工具/产品
反向代理 / 负载均衡基础 (Fundamental)L4 (传输层) & L7 (应用层)[演进起点] 解决了单体应用的高可用和水平扩展问题。隐藏了后端服务器的IP地址,实现了最基本的流量分发。NGINX, HAProxy, Apache httpd, F5 (硬件), AWS NLB (L4) / ALB (L7)
API 网关聚合 (Aggregate)L7 (应用层)[微服务入口管家] 解决了微服务架构下,外部流量 (南北向) 的统一入口和治理问题。将认证、限流、监控等通用逻辑从各服务中剥离。Kong, Tyk, Apigee (Google), AWS API Gateway, Spring Cloud Gateway, KrakenD
BFF适配/编排 (Adaptation/Orchestration)L7 (应用层)[API 网关的细化] 解决了通用API网关“一刀切”无法满足多样化前端体验的问题。为特定前端“量身定制”API,提供数据裁剪和聚合。一种模式, 非特定工具)
服务网格基础设施 (Infrastructure)L4 & L7[微服务内部交通枢纽] 解决了大规模微服务下,内部服务间流量 (东西向) 的可靠性、安全性和可观测性问题。将服务治理能力下沉到基础设施。Istio, Linkerd, Consul Connect, Kuma, AWS App Mesh

3.2 反向代理 / 负载均衡 (基础层)

  • 层级定位: 这是整个体系的基石。你可以认为 API 网关是一种功能增强的、有状态的 L7 反向代理。
  • 低级 vs. 高级:
    • L4 负载均衡 (较“低级”): 工作在 TCP/UDP 层。它只看 IP 地址和端口号,像个盲人邮递员,只按地址分发包裹,不看包裹里面是什么。优点是极快,因为不做复杂计算。AWS 的 NLB (Network Load Balancer) 就是典型。
    • L7 负载均衡 (较“高级”): 工作在 HTTP/HTTPS 层。它能拆开包裹,看到里面的信件内容(HTTP 请求路径、头部信息),然后根据内容做更智能的转发。比如,访问 /api/users 的请求发给用户服务,访问 /api/products 的请求发给商品服务。NGINX 和 AWS 的 ALB (Application Load Balancer) 是典型。L7 是 API 网关的前置条件。

3.3 API 网关 (应用聚合层)

  • 层级定位: 它构建在 L7 反向代理/负载均衡的能力之上。它不仅仅是“转发”,更是“管理”和“处理”。
  • 高级之处: 它关心的不再是网络连接,而是 API 本身。它理解“用户认证”、“API Key”、“请求速率”、“响应缓存”这些更贴近业务应用的概念。它的存在,是为了简化客户端和后端微服务集群之间的交互。

3.3 BFF (体验适配层)

  • 层级定位: 这是 API 网关模式的一种设计范式,而不是一个全新的技术类别。它逻辑上位于通用网关和微服务之间,或者它本身就扮演了针对特定客户端的“迷你网关”。
  • 高级之处: 它的抽象层次最高,因为它直接面向用户体验。它的设计目标不是通用的 API 管理,而是“如何让我的手机 App 加载得最快?”、“如何让我的网站一次调用就拿到所有需要渲染的数据?”。它处理的是数据聚合和裁剪的逻辑。

3.4 服务网格 (透明基础设施层)

  • 层级定位: 这是一个非常独特的层。它不直接参与南北向(用户到服务)的流量,而是渗透到所有微服务之间,管理东西向(服务到服务)的流量。它和 API 网关是互补关系,而非替代关系。

  • 低级或高级? 从概念上讲它非常高级,因为它创建了一个抽象的应用网络层。但从实现上讲,它的 Sidecar 代理(如 Envoy)是一个性能极高的低级网络代理,可以精细地控制 TCP 连接和 HTTP 请求。

  • 它和 API 网关的经典组合:

    • 一个请求的生命周期:
      1. 用户请求到达 API 网关 (Kong)。
      2. 网关完成认证、限流,然后将请求路由到订单服务。
      3. 请求实际上被订单服务的 Sidecar (Envoy) 拦截。
      4. 订单服务代码里调用库存服务。
      5. 这个调用再次被订单服务的 Sidecar 拦截,它负责加密(mTLS)、找到健康的库存服务实例、如果调用失败就智能重试。
      6. 流量到达库存服务的 Sidecar,解密后交给库存服务。

    在这个流程里,API 网关是对外的大门,服务网格是内部的智能高速公路系统。两者各司其职,共同保障了整个微服务体系的健壮性。

4. 提问问题

4.1 代理工具是属于正向代理吗?

是的,它是一种加密的、特殊的正向代理。

4.2 客户端负载均衡是什么?

客户端负载均衡 (Client-Side LB) - 决策权下放

客户端启动时,先从一个服务注册中心 (Service Registry) 拉取一份“订单服务”的可用实例列表(比如 [10.0.0.1:8080, 10.0.0.2:8080, 10.0.0.3:8080])。
当客户端需要调用订单服务时,它自己从这个列表中根据内置的负载均衡策略(如轮询)选择一个地址(比如 10.0.0.2:8080),然后直接发起调用。

  • 决策者: 客户端自己。
  • 客户端状态: 客户端是“全知”的,它清楚地知道后端有哪些服务实例。

优点: 少了一次网络跳跃(请求无需经过一个独立的 LB),性能更好,架构更简单。
缺点: 负载均衡的逻辑侵入了客户端,增加了客户端的复杂度,并且客户端需要和服务注册中心耦合。

4.3 Nginx 可以是 API 网关吗?界限是什么

NGINX 既可以做正向代理、反向代理,也可以通过插件实现 API 网关的部分功能。要理解你是在使用这个工具来实现哪个角色的功能。

Nginx 是一个极其出色的 L7 反向代理。它能做到:

  • 路由: 根据请求的 URL 路径、域名、Header 转发到不同的后端服务。
  • 负载均衡: 将流量分发到多个后端实例。
  • SSL 卸载: 统一处理 HTTPS 加解密。
  • 静态内容服务: 直接提供静态文件服务。

以上这些,已经是一个 API 网关的核心骨架了。所以,仅使用开源 Nginx,通过复杂的 nginx.conf 配置,你完全可以搭建一个“简易版”的 API 网关。

真正的 API 网关 vs. Nginx (界限在此!)

一个成熟的 API 网关产品(如 Kong, Tyk, Apigee)是在 Nginx 这种高性能代理引擎的基础上,增加了大量围绕 API 生命周期管理 的高级功能。界限就在这些增值能力上:

功能维度开源 Nginx成熟的 API 网关 (如 Kong)界限说明
配置管理依赖静态配置文件 (nginx.conf),修改后需 reload通过 API/UI 动态配置,无需重启服务即可增删改 API、插件和消费者运维友好度是巨大差异。动态配置是云原生时代的关键能力。
认证授权可通过插件 (如 Lua 脚本) 实现,但较复杂内置的、一等公民的功能:API Key, OAuth2, JWT, LDAP 等认证方式,开箱即用网关把“安全”从“需要自己写代码实现”变成了“点几下鼠标配置”。
流量控制有基础的限流模块 (limit_req)精细化的速率限制与配额管理:可针对具体用户、具体 API、具体分组设置不同的访问速率和调用配额提供了更丰富的商业化和安全策略。
可观测性提供访问日志,需借助 ELK 等外部工具分析内置丰富的监控和分析:提供 Dashboard,实时监控每个 API 的延迟、流量、错误率,并能轻松集成到 Prometheus, Grafana 等从“记录日志”到“提供洞察”。
插件化架构社区有很多模块,但集成和管理分散强大的插件生态系统:拥有一个统一的、热插拔的插件市场,覆盖日志、监控、转换、安全等方方面面极大地扩展了网关的能力,且易于管理。
开发者门户无此概念自动生成 API 文档,提供开发者注册、获取 API Key 的自助服务从一个技术组件,扩展到了一个服务于“API 经济”的平台。

一个绝佳的例子:
Kong 就是基于 Nginx 构建的! Kong 把 Nginx 作为其高性能的代理核心,然后在上层用 Lua 语言开发了一个功能强大的管理插件系统,并通过 Admin API 和数据库(如 PostgreSQL)实现了所有 API 和策略的动态管理。

4.4 有了服务网格还需要API 网关吗?

简短回答:绝大多数情况下,是的,仍然需要。它们是天作之合的互补品,而非替代品,因为它们解决的是不同维度的问题。

  • API 网关 (API Gateway) 是这栋大楼的前台和安保大厅 (Lobby)。
    • 它的职责是管理所有外部访客(来自互联网的用户和第三方应用)。
    • 它会检查访客的身份证件(认证/授权),进行安检(安全策略),告诉访客去哪个部门的电梯(请求路由),并记录访客信息(日志和监控)。它甚至会限制某个时段内进入大楼的人数(限流)。
    • 它关心的是进出大楼的流量,即 南北向流量 (North-South Traffic)。
  • 服务网格 (Service Mesh) 是这栋大楼内部的智能交通和安防系统。
    • 它的职责是管理所有内部员工(各个微服务)之间的沟通。
    • 它确保员工 A(服务 A)在和员工 B(服务 B)沟通时,走的是最快的内部通道,并且他们的对话是加密的、私密的(mTLS 加密)。如果 B 员工正在开会,它会智能地让 A 稍等再联系(重试机制)。它还监控着所有内部人员的动向和健康状况(可观测性)。
    • 它关心的是大楼内部的流量,即 东西向流量 (East-West Traffic)。

因此,最佳实践是:使用 API 网关作为系统总入口,管理南北向流量;使用服务网格作为基础设施,治理东西向流量。

4.5 限流降级究竟在哪一层做?

  • API 网关: 就像城堡最外围的护城河和吊桥。它的职责是管理所有想进城堡的人(外部流量)。它只做最基础、最关键的盘查。
  • 服务网格: 就像城堡内部的巡逻卫队和内部关卡。它不管城外的人,只负责管理城堡内部不同区域之间的人员流动(服务间流量),确保一个区域的骚乱不会迅速蔓延到整个城堡。
  • 业务层代码: 就像每个房间(核心业务逻辑)门口的专属守卫。他拥有这个房间的最高权限和最详细的知识,负责执行最精细、最特殊的保卫规则。
API 网关层 (护城河和吊桥)
  • 它的使命: 保护整个系统集群,防止被来自互联网的、恶意的或突发的流量打垮。它是对外的、粗粒度的、全局性的。
  • 在这里做什么最好?
    • 全局速率限制 (Global Rate Limiting): “我们整个网站最多只接受每秒 10000 次请求。”
    • 基于身份的限流 (Per-Consumer Limiting): “每个 API Key 每分钟只能调用 100 次。” “来自 IP 地址 x.x.x.x 的请求每秒不能超过 10 次。”
    • 熔断 (Circuit Breaking): 当网关发现某个后端服务(比如 user-service)的健康检查持续失败或错误率飙升时,网关直接“拉下吊桥”,在入口处就拒绝所有发往 user-service 的请求,并快速返回一个错误。这可以保护网关自身,也避免无效请求占用内部资源。
服务网格层 (内部巡逻卫队)
  • 它的使命: 防止系统内部出现“雪崩效应”。一个服务出现问题,不能拖垮依赖它的所有上游服务。它是对内的、细粒度的、基础设施级别的。
  • 在这里做什么最好?
    • 服务间熔断 (Inter-Service Circuit Breaking): 这是服务网格的核心价值!当 order-service 调用 inventory-service 时,如果 inventory-service 挂了,服务网格的 Sidecar 代理会立刻熔断这条通路,让 order-service 快速失败,而不是傻傻地等待超时。
    • 服务间限流 (Inter-Service Rate Limiting): “我们允许 recommendation-service 每秒最多调用 product-service 500 次。” 这可以防止某个非核心服务(如推荐)把核心服务(如产品)打挂。
    • 重试机制 (Retries): 对临时的网络抖动或服务重启,自动进行重试。
业务代码层 (房间专属守卫)
  • 它的使命: 执行与具体业务场景强相关的、精细化的、有状态的限流和降级策略。它是与业务逻辑绑定的、最精细的。
  • 在这里做什么最好?
    • 业务级别的限流: “每个普通用户每天只能发布 5 篇帖子,而 VIP 用户可以发布 50 篇。” 这种逻辑依赖用户的身份和等级,API 网关和服务网格都无法感知。
    • 资源级别的限流: “单个用户最多只能同时进行 2 个文件的转码任务。”
    • 业务降级 (Graceful Degradation): “当支付服务不可用时,订单服务可以先创建一个‘待支付’状态的订单,并提示用户稍后重试”,而不是直接报错。或者,“在双十一高峰期,商品详情页不显示非关键的‘买家秀’模块,以保证核心交易流程的顺畅。” 这种带有业务逻辑的回退 (fallback) 策略,只有业务代码自己最清楚怎么做。

5. 负载均衡写法

5.1 Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 定义一个名为 "my_app_backend" 的后端服务器池
# Nginx 默认使用轮询 (round-robin) 策略
upstream my_app_backend {
server app1.example.com:8080;
server app2.example.com:8080;
server app3.example.com:8080 weight=5; # 可以指定权重,流量是其他服务器的5倍
# server app4.example.com:8080 backup; # 标记为备份服务器
}

server {
listen 80;
server_name my.app.com;

location / {
# 将所有进入 / 的请求代理到 my_app_backend 服务器池
proxy_pass http://my_app_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

5.2 Docker Compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# docker-compose.yml
version: '3.8'

services:
# api 服务,我们想要负载均衡的目标
api:
image: my-awesome-api
build: .
ports:
- "8000" # 只暴露端口,不映射到主机
networks:
- my_network
deploy:
replicas: 3 # 关键!声明需要3个此服务的副本

# 一个调用方服务,比如前端
frontend:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf # 挂载 Nginx 配置
ports:
- "80:80"
networks:
- my_network
depends_on:
- api

networks:
my_network:

frontend 服务的 nginx.conf 中,你可以这样写:

1
2
3
4
5
6
7
8
# frontend 服务的 nginx.conf
...
location /api/ {
# 关键!直接使用服务名 `api` 作为主机名
# Docker DNS 会将其解析到3个 api 容器中的一个 IP
proxy_pass http://api:8000/;
}
...

5.3 Kubernetes

定义一个 Service,它通过 selector 匹配一组 Pod。这个 Service 会获得一个稳定的虚拟 IP 和 DNS 名称,所有发往此地址的流量由 Kube-proxy 自动负载均衡到后端的 Pods。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# my-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3 # 声明需要3个 Pod 副本
selector:
matchLabels:
app: my-app # 这个标签是 Service 和 Pod 关联的纽带
template:
metadata:
labels:
app: my-app # Pod 必须有这个标签
spec:
containers:
- name: my-app-container
image: my-app-image:latest
ports:
- containerPort: 8080

---
# my-app-service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app-service # 其他服务将通过这个名字访问
spec:
selector:
app: my-app # 关键!选择所有带 `app: my-app` 标签的 Pod
ports:
- protocol: TCP
port: 80 # Service 暴露的端口
targetPort: 8080 # 流量转发到 Pod 的 8080 端口
type: ClusterIP # 默认类型,只在集群内部可见

在集群内的任何其他 Pod 中,都可以通过 http://my-app-service 来访问,K8s 会自动做负载均衡。

5.4 Istio (服务网格)

基础设施增强层,对 Kubernetes 的 Service 提供更精细的流量控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 首先,你仍然需要上面定义的 Kubernetes Service 'my-app-service'

# istio-destination-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-app-dr
spec:
host: my-app-service.default.svc.cluster.local # 目标服务
trafficPolicy:
loadBalancer:
# 关键!定义负载均衡策略
simple: RANDOM # 可以是 ROUND_ROBIN, LEAST_CONN, RANDOM
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
maxRequestsPerConnection: 1

6. 参考资料