当微服务变得过多时
\n\n你用 TypeScript 编写了第一个微服务。它运行良好。接着是第二个、第三个、第十个。然后你突然发现,大部分时间不是花在编写业务逻辑上,而是花在让微服务能够相互通信上。超时、重试、负载均衡、流量加密、指标——所有这些都需要在每个服务中单独实现。
\n\n这时 Service Mesh 登场了——这项技术将所有通信基础设施从代码中抽离出来,放入一个独立的层。是的,它与 TypeScript 微服务配合得很好。在本文中,我们将通过真实的代码示例,深入探讨它在实践中的工作原理。
\n\n用简单的话说,什么是 Service Mesh
\n\n想象一下,你的每个 TypeScript 微服务都是大办公室里的一个员工。没有 Service Mesh,每个员工都必须自己铺设电缆、设置电话,并确保不被窃听。有了 Service Mesh,一个专门的 IT 部门会为每个员工连接一个“个人助理”(sidecar proxy)。
\n\n在技术世界中,这个助理被称为 Envoy Proxy,而管理整个基础设施的是像 Istio 或 Linkerd 这样的编排器。最棒的是,你的 TypeScript 代码几乎保持不变。
\n\nService Mesh 的关键功能
\n\n- \n
- 流量管理 — 智能路由、A/B 测试、金丝雀发布 \n
- 安全 — 服务间的自动 mTLS 加密 \n
- 可观测性 — 开箱即用的指标、日志、追踪 \n
- 弹性 — 基础设施级别的重试、熔断器、超时 \n
为什么 TypeScript 微服务尤其受益于 Service Mesh
\n\nTypeScript 是一种拥有强大类型系统的语言,但其主要运行时环境(Node.js)在 I/O 性能方面并不总是出众。当你用 TypeScript 编写微服务时,每一个额外的 HTTP 请求、每一次手动实现的重试或 TLS 握手,都会给事件循环带来额外负担。
\n\nService Mesh 将这些负担接管过来。你的 TypeScript 代码保持简洁:只需接收请求并响应,而所有“管道工程”都由 Envoy 完成。当你有几十个微服务时,这一点尤其重要——每个服务都有自己的重试逻辑和超时设置。
\n\n实践示例:Service Mesh 下的 TypeScript 微服务
\n\n假设我们有两个 TypeScript 微服务:user-service 和 order-service。Order-service 需要获取用户数据。没有 Service Mesh,我们可能会编写类似这样的代码:
// 没有 Service Mesh — 手动管理 HTTP\nimport axios from 'axios';\n\nclass UserClient {\n private baseUrl = 'http://user-service:3000';\n private retries = 3;\n\n async getUser(id: string): Promise<User> {\n for (let i = 0; i < this.retries; i++) {\n try {\n const response = await axios.get(`${this.baseUrl}/users/${id}`, {\n timeout: 5000,\n httpsAgent: new https.Agent({ rejectUnauthorized: true })\n });\n return response.data;\n } catch (error) {\n if (i === this.retries - 1) throw error;\n await delay(1000 * Math.pow(2, i));\n }\n }\n }\n}\n\n而有了 Service Mesh,这变成了:
\n\n// 使用 Service Mesh — 简单的 HTTP 请求\nimport axios from 'axios';\n\nclass UserClient {\n async getUser(id: string): Promise<User> {\n const response = await axios.get(`http://user-service/users/${id}`);\n return response.data;\n }\n}\n\n注意到区别了吗?所有的复杂性——重试、超时、加密——都