Swift服务API网关:在微服务之间搭建桥梁
\n\n想象一下,你的后端是一个巨大的购物中心。里面有几十家商店(微服务):认证、商品目录、购物车、支付、通知。客户端(iOS应用)需要分别进入每家商店——这会造成混乱、耗时且不安全。API网关集主入口、安保和导航于一体。它接收请求、检查通行证、转发到相应部门并返回结果。
\n\n在Vapor和Hummingbird日益流行的Swift世界中,为可扩展项目创建自己的API网关不是奢侈,而是必需。今天我们将探讨如何用Swift编写一个轻量级网关,将你的服务整合到统一生态系统中。
\n\n为什么Swift架构需要API网关?
\n\n当你有2-3个微服务时,客户端可以直接与每个服务通信。但当服务数量达到10+(金融科技、电商或SaaS的典型场景)时,就会出现问题:
\n\n- \n
- 客户端代码臃肿——每个服务都有自己的端点、错误格式和认证协议 \n
- 安全漏洞——每个服务都必须自行处理CORS、速率限制、JWT验证 \n
- 重构困难——重命名服务?需要修改所有客户端代码 \n
- 额外流量——客户端需要发送5个请求而不是1个来加载页面 \n
API网关通过成为统一入口点来解决这些问题。它可以将来自多个微服务的数据聚合到一个响应中,应用安全策略并记录所有请求。对于Swift开发者来说,这还意味着可以在网关层面利用语言的强类型特性。
\n\n工具选择:Vapor + Hummingbird
\n\n创建Swift API网关的理想工具是Vapor——生态系统中最为成熟的Web框架。它提供中间件、路由、客户端请求(通过Client)以及对async/await的支持。替代方案是Hummingbird(轻量、快速、来自Apple),但作为示例我们选择文档更完善的Vapor。
我们的网关将实现三个功能:
\n- \n
- 将请求代理到相应的微服务 \n
- 通过JWT进行认证 \n
- 将两个服务的数据聚合到一个响应中 \n
步骤1. 项目基本结构
\n\n创建一个新的Vapor项目:
\nvapor new APIGateway --template=api\ncd APIGateway\n\n在Package.swift中添加JWT依赖:
.package(url: "https://github.com/vapor/jwt.git", from: "4.0.0")\n\n并在target中引入:
\n.target(name: "App", dependencies: [\n .product(name: "Vapor", package: "vapor"),\n .product(name: "JWT", package: "jwt")\n])\n\n步骤2. 认证中间件
\n\n创建一个中间件,用于验证JWT令牌并将用户信息传递给后续处理。这是Swift API网关的经典模式:
\n\nimport Vapor\nimport JWT\n\nstruct JWTAuthenticator: AsyncMiddleware {\n func respond(to request: Request, chainingTo next: AsyncResponder) async throws -> Response {\n guard let token = request.headers.bearerAuthorization?.token else {\n throw Abort(.unauthorized, reason: "Missing Bearer token")\n }\n \n // 验证签名和有效期\n let payload = try await request.jwt.verify(token, as: UserPayload.self)\n \n // 将用户信息保存到请求存储中\n request.storage.set(UserPayloadKey.self, to: payload)\n \n return try await next.respond(to: request)\n }\n}\n\nstruct UserPayload: JWTPayload {\n var userID: UUID\n var role: String\n var exp: ExpirationClaim\n \n func verify(using signer: JWTSigner) throws {\n