Swift服务API网关:如何将微服务整合为统一系统

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

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
\n\n

API网关通过成为统一入口点来解决这些问题。它可以将来自多个微服务的数据聚合到一个响应中,应用安全策略并记录所有请求。对于Swift开发者来说,这还意味着可以在网关层面利用语言的强类型特性。

\n\n

工具选择:Vapor + Hummingbird

\n\n

创建Swift API网关的理想工具是Vapor——生态系统中最为成熟的Web框架。它提供中间件、路由、客户端请求(通过Client)以及对async/await的支持。替代方案是Hummingbird(轻量、快速、来自Apple),但作为示例我们选择文档更完善的Vapor。

\n\n

我们的网关将实现三个功能:

\n
    \n
  • 将请求代理到相应的微服务
  • \n
  • 通过JWT进行认证
  • \n
  • 将两个服务的数据聚合到一个响应中
  • \n
\n\n

步骤1. 项目基本结构

\n\n

创建一个新的Vapor项目:

\n
vapor new APIGateway --template=api\ncd APIGateway
\n\n

在Package.swift中添加JWT依赖:

\n
.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\n
import 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                

博客

书籍推荐