正向代理反向代理负载均衡和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)想批准李四的请假单。张三是李四的直属上司吗?” |
- API 网关做“门卫”:它负责面上的、基于角色和范围 (Scope) 的访问控制。它不知道“订单 ABC”和“订单 XYZ”的区别,但它知道只有“用户”角色的请求才能访问
/api/orders
路径。这是一种业务无关的授权。 - 微服务做“业务专家”:它负责具体的、与业务逻辑紧密相关的权限判断。当一个请求“查看订单 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 网关的经典组合:
- 一个请求的生命周期:
- 用户请求到达 API 网关 (Kong)。
- 网关完成认证、限流,然后将请求路由到订单服务。
- 请求实际上被订单服务的 Sidecar (Envoy) 拦截。
- 订单服务代码里调用库存服务。
- 这个调用再次被订单服务的 Sidecar 拦截,它负责加密(mTLS)、找到健康的库存服务实例、如果调用失败就智能重试。
- 流量到达库存服务的 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): 对临时的网络抖动或服务重启,自动进行重试。
- 服务间熔断 (Inter-Service Circuit Breaking): 这是服务网格的核心价值!当
业务代码层 (房间专属守卫)
- 它的使命: 执行与具体业务场景强相关的、精细化的、有状态的限流和降级策略。它是与业务逻辑绑定的、最精细的。
- 在这里做什么最好?
- 业务级别的限流: “每个普通用户每天只能发布 5 篇帖子,而 VIP 用户可以发布 50 篇。” 这种逻辑依赖用户的身份和等级,API 网关和服务网格都无法感知。
- 资源级别的限流: “单个用户最多只能同时进行 2 个文件的转码任务。”
- 业务降级 (Graceful Degradation): “当支付服务不可用时,订单服务可以先创建一个‘待支付’状态的订单,并提示用户稍后重试”,而不是直接报错。或者,“在双十一高峰期,商品详情页不显示非关键的‘买家秀’模块,以保证核心交易流程的顺畅。” 这种带有业务逻辑的回退 (fallback) 策略,只有业务代码自己最清楚怎么做。
5. 负载均衡写法
5.1 Nginx
1 | # 定义一个名为 "my_app_backend" 的后端服务器池 |
5.2 Docker Compose
1 | # docker-compose.yml |
在 frontend
服务的 nginx.conf
中,你可以这样写:
1 | # frontend 服务的 nginx.conf |
5.3 Kubernetes
定义一个 Service
,它通过 selector
匹配一组 Pod
。这个 Service
会获得一个稳定的虚拟 IP 和 DNS 名称,所有发往此地址的流量由 Kube-proxy 自动负载均衡到后端的 Pods。
1 | # my-app-deployment.yaml |
在集群内的任何其他 Pod 中,都可以通过 http://my-app-service
来访问,K8s 会自动做负载均衡。
5.4 Istio (服务网格)
基础设施增强层,对 Kubernetes 的 Service
提供更精细的流量控制。
1 | # 首先,你仍然需要上面定义的 Kubernetes Service 'my-app-service' |