基于 Swift 的无服务器函数:高级 AWS Lambda
使用 Swift 开发无服务器应用程序正变得越来越受欢迎。在本指南中,我们将探讨使用 AWS Lambda 的高级技术:异步处理器、与 VPC 的集成、创建自定义层 (Layers) 以及配置监控。本材料面向已经熟悉 Swift 和 AWS Lambda 基础的开发人员。
1. 异步处理器 (async/await)
现代 Swift 通过 async/await 支持异步。AWS Lambda SDK 允许使用此模型,这大大简化了与输入/输出和外部服务的交互。
基本异步处理器:
import AWSLambdaRuntimeimport AWSLambdaEvents
struct AsyncHandler: LambdaHandler { typealias Event = APIGatewayV2Request typealias Output = APIGatewayV2Response
func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws -> APIGatewayV2Response { let result = await fetchData(from: "https://api.example.com/data") return APIGatewayV2Response(statusCode: .ok, body: result) }
private func fetchData(from url: String) async -> String { // 模拟异步请求 try? await Task.sleep(nanoseconds: 100_000_000) return "{\\"status\\": \\"ok\\", \\"data\\": \\"\\(url)\\"}" }}并行处理:
func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws -> APIGatewayV2Response { async let user = fetchUser(id: event.queryParameters?["userId"] ?? "") async let orders = fetchOrders(userId: event.queryParameters?["userId"] ?? "")
let (userData, ordersData) = try await (user, orders) let combined = """ { "user": \\(userData), "orders": \\(ordersData) } """ return APIGatewayV2Response(statusCode: .ok, body: combined)}使用 Task 可以精细控制优先级和操作取消。这在处理缓慢的外部 API 时至关重要。
2. 与 VPC 集成及安全性
基于 Swift 的 Lambda 函数可以在 VPC 内运行,以访问私有资源(RDS、ElastiCache)。然而,由于需要创建 ENI,这会使冷启动时间增加 5-10 秒。
高级 VPC 配置:
- 最小化子网: 仅在不同可用区中使用 2-3 个子网。
- NAT 网关: 如果需要访问互联网,请务必在公有子网中配置 NAT 网关。
- VPC 终端节点: 对于 AWS 服务(S3、DynamoDB、SQS),请使用 VPC 终端节点而不是 NAT。
- 安全组: 配置最小必要的规则(仅针对特定端口的入站/出站规则)。
通过 VPC 连接到 RDS 的示例:
import Vaporimport MySQLNIO
struct DatabaseHandler: LambdaHandler { typealias Event = APIGatewayV2Request typealias Output = APIGatewayV2Response
private let db: MySQLConnection
init(context: LambdaInitializationContext) async throws { let eventLoop = context.eventLoop self.db = try await MySQLConnection.connect( to: .init(hostname: "private-rds-endpoint", port: 3306), username: "admin", password: "secret", database: "mydb", on: eventLoop ).get() }
func handle(_ event: APIGatewayV2Request, context: LambdaContext) async throws -> APIGatewayV2Response { let rows = try await db.simpleQuery("SELECT * FROM users LIMIT 10") let jsonData = try JSONEncoder().encode(rows) return APIGatewayV2Response(statusCode: .ok, body: String(data: jsonData, encoding: .utf8) ?? "[]")