Community编程与开发github.com

swift-microservices/swift-microservices-architect

为 Swift 服务端架构师设计,基于 gRPC 微服务模式,以 Hummingbird 为网关,将每个服务封装为一个 Swift 包,并包含 Core、适配器及可执行组合根。

swift-microservices-architect 是什么?

该项目提供了一个完整的 Swift 微服务架构指南,适用于规划或重构 Swift 服务端应用。它定义了一套清晰的模块划分和代码组织规范:每个服务独立为一个 Swift 包,包含 Core(领域模型、用例、端口)、Postgres(数据库适配器)、gRPC(服务通信)、Temporal(持久化工作流)等目标。核心特性包括:严格的分层边界(Core 不依赖任何驱动或传输层)、基于 mTLS 和 JWT 的零信任安全模型、行级安全的多租户隔离、以及可组合的组合根(Composition Root)。特别适合需要在多人团队中保持代码一致性、并支持 CI/CD 自动化的中大型 Swift 服务端项目。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/swift-microservices/swift-microservices-architect-skill/tree/HEAD/skills/swift-microservices-architect

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Swift 微服务架构师

若后端已采用其他方式构建,则保留其现有结构和约定,除非用户要求更改;仅当后端缺少某部分时,才从本技能中获取相应的模式。

X 代表目标名称中的服务名(如 LoansCore),以及类型名称中的服务名(如 BorrowBookUseCase、LoanService);<Org> 和 <org> 代表组织名。以下是 Bookshelf(一个小型借阅图书馆)的示例:

包包含内容
bookshelf-identity账户、密码、会话;签发所有访问令牌;Valkey 中的重置码;内部供其他服务使用的成员信息
bookshelf-catalog图书:任何人可读取,管理员可编辑;Loans 服务内部通过它查询图书
bookshelf-loans成员的借阅记录,多租户表;一个工作流将逾期借阅标记为已逾期并发送通知
bookshelf-gateway公共 HTTP API,将请求转发给各服务的 gRPC 契约
bookshelf-coreBookshelfAuthentication、BookshelfPersistence、BookshelfTransport、BookshelfTesting
bookshelf-protosIdentityProtos、CatalogProtos、LoansProtos

架构形状

客户端 ── HTTPS ──► 边界(TLS 终结) ── HTTP ──► 网关(Hummingbird, OpenAPI)
网关 ── gRPC, mTLS, 调用者的 JWT ──► 每个服务的 XService
服务、工作进程 ── gRPC, mTLS ──► 另一个服务的 XInternalService
服务、工作进程 ── mTLS ──► Temporal          服务 ──► 自己的 Postgres 数据库、Valkey

每个服务及网关都依赖于 <org>-core、<org>-protos 以及 swift-microservices 库(栈)。

服务的包结构

<org>-x
├── XCore         领域模型、错误、仓库协议和命令、端口、用例
├── XPostgres     每个数据库角色的作用域、仓库、语句、迁移
├── XGRPC         XService 和 XInternalService、Protobuf 转换、用于 Core 端口的 gRPC 客户端
├── XTemporal     工作流、活动容器、用于 Core 工作流端口的 Temporal 客户端
├── XValkey       用于短生命周期值的仓库
├── X<Provider>   封装 Core 端口后的第三方 API(LoansResend)
└── X             可执行文件:命令、配置默认值、迁移、组合根

服务仅包含其所需的目标,每个目标仅导入其所在行列出的模块。硬性规则:

  • XCore 不导入任何驱动、传输层、契约、工作流引擎、配置或生命周期模块(Core 可以链接的内容)。
  • 适配器目标之间永不相互导入;可执行文件通过 Core 的协议将一个适配器传递给另一个。
  • 生成的契约类型永不离开 XGRPC、网关的 HTTP 目标和可执行文件。
  • 只有可执行文件读取配置、构建客户端并运行 ServiceGroup。
  • 没有服务读取另一个服务的数据;数据只能通过契约在服务间传递。

职责归属

关注点负责人
业务规则、授权决策、错误的含义用例(位于 XCore);适配器仅进行转换和委托
服务知晓的另一服务的数据模型XCore 中 Ports/ 下的模型,位于返回该模型的端口旁
Protobuf ↔ 领域、HTTP ↔ protobufXGRPC 的 Protobuf/ 转换;网关的 Schemas/
进程间消息;公共 API<org>-protos;网关的 openapi.yaml
调用者身份网关验证并转发令牌;每个服务再次验证
哪些进程可以调用内部 RPC监听器上的 mTLS:环境中授权机构签名的所有进程
租户隔离行级安全性;<Org>Persistence 将调用者绑定到每个事务,每个受众的用例以其数据库角色运行
持久化、延迟或多服务工作XTemporal 中的 Temporal 工作流
每个服务都相同需要的部分<org>-core:身份、租户绑定、传输读取器

代码风格

代码读起来应像其所实现的业务需求,以 Apple 的 WWDC 示例代码为标杆(风格)。用例和适配器按以下方式映射错误:

do {
    …  // 工作代码,按需求陈述的顺序
} catch let error as BorrowBookUseCaseError {
    throw error
} catch CatalogClientError.unavailable {
    logger.warning("借阅失败:目录不可用")
    throw .catalogUnavailable
} catch {
    logger.error("借阅失败:未知错误", metadata: ["error": "\(String(reflecting: error))"])
    throw .unknown
}
  • 一个 do 块包含直至 return 的整个工作;每个 catch 结束自身路径:不要在 do 之前声明任何供 catch 填充的变量。
  • 构建,再调用:调用所接收的值应是一个命名的 let,绝不允许在参数中直接进行转换、try 或 await(构建,再调用)。
  • 用例、工作流或活动中无辅助方法,无 Result 周转、引导标志、try?、catch 中的嵌套 do 或强制解包。
  • Swift 6 模式,启用 ExistentialAny、MemberImportVisibility、InternalImportsByDefault 和 NonisolatedNonsendingByDefault(Swift 设置);在服务的目标之间使用 package 访问权限。
  • 跨越边界的所有内容都必须是 Sendable;不得使用 Task {} 或 Task.detached,仅当并发允许时才使用未检查的并发。

注意事项

  • 如果某个组件未包含在 ServiceGroup 中,它将永远不会运行:未运行的 GRPCClient 或 PostgresClient 永远不会连接,因此其调用将一直等待直到超时。
  • 以数据库所有者身份连接的进程会绕过行级安全性,因此每个进程应以其角色连接,只有 serve --migrate-database 以所有者身份运行。
  • Temporal 仅在运行时检查 Codable:每个工作流和活动负载,以及其中包含的每个类型,都必须是 Codable, Sendable(工作流)。
  • 工作流代码会被重放:工作流中的 Date.now、UUID()、随机数、Task.sleep 或任何 I/O 都会破坏它(确定性)。
  • 在自有代码中使用简单的或有作用域的 import Foundation 会在 Linux 上链接完整的 Foundation;请使用条件导入 FoundationEssentials。

检查清单

将任务的检查清单复制到回复中,并逐项标记完成;每个标明的 .md 文件均位于 references/ 中。

规划后端

- [ ] 每个服务拥有的能力及数据;每项能力对应一个服务(system.md#将系统拆分为服务)
- [ ] 命名每个服务;对照图中的所有模块检查其目标名称
- [ ] 每个服务:按受众划分的 XService RPC、内部使用的 XInternalService RPC 及调用者(无调用循环)、表(租户或非租户)、工作流、短生命周期状态
- [ ] 每个服务:其目标、命令和数据库角色
- [ ] <org>-core 的产品、<org>-protos 的契约、网关按层级划分的路由
- [ ] 构建顺序:<org>-core 和 <org>-protos、令牌签发者、每个服务在其调用者之前、网关
- [ ] 根据 system.md#计划 编写计划;在任何代码编写之前对照硬性规则检查

添加服务

- [ ] <org>-protos:包含 XService 的 XProtos,如果进程需要则包含 XInternalService
- [ ] 根据 packages.md#packageswift-template 创建包 <org>-x,仅包含计划中命名的目标
- [ ] XCore:模型、错误、仓库、端口、每个 RPC 一个用例(use-cases.md)
- [ ] XPostgres:角色、表、行级安全、语句、每个角色一个作用域(persistence.md)
- [ ] XGRPC:基于用例的 proto 服务、转换、端口客户端(grpc.md)
- [ ] 根据需要添加 XTemporal、XValkey、X<Provider>
- [ ] X:命令、InMemoryProvider 默认值、迁移、Serve 和包含工作进程的 Run(composition.md)
- [ ] 网关:公开 RPC 的路由(gateway.md)
- [ ] 每个模块基于 mock 的测试目标(testing.md)
- [ ] 其 CI 工作流、Containerfile 和 Dependabot(delivery.md)
- [ ] swift build 和 swift test;修复并重复直到无警告通过

添加操作

- [ ] 契约:在其受众下的 XService 或 XInternalService 中添加 RPC
- [ ] XCore:用例的五个文件;其作用域仅列出它涉及的内容(use-cases.md)
- [ ] XPostgres:它可能以某些角色运行的作用域需采用该作用域协议
- [ ] XGRPC:处理器和输入的转换,每个错误情况映射到位
- [ ] 可执行文件:用例在其角色的数据库上运行,传递给服务
- [ ] 网关:如果是公共路由,则在其层级中添加路由
- [ ] 测试:基于 mock 验证用例的输出和处理器的状态码
- [ ] swift build 和 swift test;修复并重复直到无警告通过

添加持久化流程

- [ ] XCore:XWorkflowClient 端口;其活动执行的用例,由工作进程作用域采纳
- [ ] XTemporal:工作流、其活动、TemporalXWorkflowClient、命名的 ActivityOptions(workflows.md)
- [ ] 启动它的用例,在其事务提交后,使用确定性 ID
- [ ] 可执行文件:Serve 中的 Temporal 客户端;工作进程组及其 Run 根
- [ ] 测试:基于时间跳跃服务器的工作流,基于 mock 的活动
- [ ] swift build 和 swift test;修复并重复直到无警告通过

设置 CI/CD

- [ ] 包的类别:公共库、系统库或服务(delivery.md#包类别)
- [ ] 其 CI 工作流,引用 swift-microservices/ci 的发布版本提交;dependabot.yml;.license_header_template 和 .licenseignore;机密
- [ ] 如果是库:semver 标签和 .github/release.yml;如果是服务:其 Containerfile
- [ ] 使用 CI 的标记运行 swift build 和 swift test;修复并重复直到通过

审查后端

- [ ] 运行边界检查(packages.md#检查边界)
- [ ] 每个用例:五个文件、类型化抛出、每个 case 只有一个 catch、无辅助方法、正确数据库角色
- [ ] 每个适配器仅做转换和委托;每个错误情况都已映射
- [ ] 每个根:仅在此处读取配置,所有组件按依赖顺序放入 ServiceGroup
- [ ] Swift 设置、FoundationEssentials 导入、包访问权限、命名规范(conventions.md)
- [ ] 严重级别排序的发现:阻塞级(租户隔离、授权、凭据、构建)、主要级(架构形状)、次要级(命名、布局、日志记录),每个发现引用文件及行号或空 grep 结果,附带规则和修复方案;然后是用户决策。仅在被要求时修改代码
- [ ] swift build 和 swift test;报告每个结果,或无法运行的原因

参考资料

根据需要阅读相应的参考资料:

参考资料内容
system.md拆分为服务、契约、服务间通信、共享包、计划
packages.md目标及其导入、Package.swift、Swift 设置、特性与 Foundation、布局、边界检查
stack.md库、每个目标链接哪些库、Foundation 链接、选择版本
use-cases.md模型、错误、仓库、端口、用例的五个文件和主体、事务、授权
persistence.md每个数据库角色的作用域、行级安全、语句、迁移、Valkey
grpc.md契约、proto 服务、处理器、转换、分页、状态码、客户端、传输
gateway.mdOpenAPI 类型、请求上下文和层级、控制器、Webhook、错误、上游客户端
workflows.md启动工作流、负载、确定性、活动和选项、版本、工作进程
composition.md命令、组合根、配置、日志记录、ServiceGroup
security.md信任模型、mTLS、用户令牌、授权层、机密、Webhook
style.md代码风格:错误处理、并发、导入、Foundation、类型、格式化
testing.md测试目标、每个目标验证的内容、mock
delivery.md按包类别的 CI 工作流、发布、部署、Containerfile、Dependabot
conventions.md命名包、目标、类型、文件、键或文件夹

相关技能

对于架构形状内部的代码实现,当这些技能已安装时加载;若本技能已规定形状,则遵循本技能:

  • Actor、任务组、取消、Sendable 诊断、Swift 6 迁移:swift-concurrency
  • 参数标签、方法名、文档注释:swift-api-design-guidelines
  • 用例、处理器和工作流的测试:swift-testing-expert

相关技能