应用参考。 这是一个说明性架构和范围检查清单,并非经过验证的客户项目或经过测量的部署。技术、集成范围和交付项目将根据实际需求确定。
场景与约束
一个服务类产品,iOS 和 Android 使用相同的工作流程,而一个小型团队需要同时维护两个平台。三项约束决定了设计:不稳定的移动网络、导致热修复速度较慢的应用商店审核周期,以及无需发布新版本即可更改业务规则的需求。
架构
层级与职责
| 层级 | 技术 | 负责内容 |
|---|---|---|
| 应用 | Flutter (Dart),分为 UI / 状态 / repository 层 | 页面和交互。只有 repository 层知道数据来自网络还是本地缓存,从而将离线处理排除在 UI 代码之外。 |
| 本地存储 | SQLite (drift) + 平台安全存储 | 缓存实体、待处理写入操作的 outbox,以及存储在安全存储中而非 shared preferences 中的令牌。 |
| API | Go + Gin,版本化路由 | 业务规则、验证和授权。从第一天起进行版本化,因为旧版应用在发布后很长时间内仍会留在用户手中。 |
| 存储 | PostgreSQL | 事务数据;对于确实可变的属性使用 JSONB,而不是不断扩展数据表。 |
| 缓存 / 队列 | Redis | 会话、速率限制、幂等键和后台任务队列。 |
| 推送 | 由统一通知服务封装的 FCM 和 APNs | 为通知提供统一的内部 API;平台差异在服务端处理,而不是放入应用中。 |
| 管理后台 | Vue 管理面板 | 用户、内容和订单管理,以及无需发布即可改变应用行为的远程配置值。 |
数据模型
下面的表承载着其他所有部分所依赖的规则。数据模型设计错误,会将一个可运行的演示变成无法扩展的系统。
核心实体
| 实体 | 关键字段、关系与规则 |
|---|---|
| user / auth_identity | 一个用户可以拥有多个身份(手机号、Apple、Google、微信)。将身份与用户分离,后续添加登录方式时无需进行迁移。 |
| device | 记录每台设备的推送令牌、平台、应用版本和区域设置。通知定向和分阶段发布都会读取这些信息。 |
| order / booking | 领域实体,包含明确的状态字段和转换日志,因此支持人员可以回答“它是如何达到该状态的”。 |
| outbox (客户端) | 使用客户端生成的 UUID 对本地写入操作进行排队。该 UUID 会成为服务端的幂等键,从而使超时后的重试安全可控。 |
| sync_cursor | 按用户记录的 updated_at 水位线,用于驱动增量同步,使应用能够拉取变更数据,而不必重新获取整个集合。 |
| remote_config | 按应用版本和平台保存的键值配置,使规则和功能开关无需发布新版本即可变更。 |
关键接口
承载业务规则的端点
| 端点 | 用途与并发说明 |
|---|---|
| POST /api/v1/auth/token | 签发短期访问令牌和轮换刷新令牌。刷新令牌轮换可以限制被盗令牌在无法触达的设备上造成的损害。 |
| GET /api/v1/sync?since= | 分页并设置响应上限,增量拉取游标之后发生变更的记录,使离线数周后返回的用户不会拉取无界响应。 |
| POST /api/v1/orders | 接受客户端 UUID 作为幂等键;网络超时后重试时返回原订单,而不是创建重复订单。 |
| POST /api/v1/devices | 注册或刷新推送令牌,并将其与用户和应用版本关联,以支持定向通知和分阶段通知。 |
| GET /api/v1/config | 返回请求应用版本对应的远程配置,这是避免因规则变更而发布新版本的机制。 |
技术决策
- 选择 Flutter,而不是两套原生代码库。 工作流程相同且团队规模较小,因此在工作流程重叠的地方,共享应用代码可以减少重复维护;但平台集成、设备检查和发布仍需要分别处理。在支付、推送、生物识别等平台确实存在差异的场景中,应将差异隔离在平台通道之后,而不是让其渗透到共享代码中。
- 支持离线容错,而不是离线优先。 读取操作会缓存,写入操作会排入 outbox,但服务端仍是权威来源。完整的离线优先方案需要处理冲突,成本显著更高,只有在用户确实需要长时间断网工作时才值得采用。
- 使用客户端生成的 UUID 作为幂等键。 移动网络经常在请求过程中超时。没有这一机制,超时重试可能产生重复订单风险,而该风险必须经过测试。
- 从首次发布开始进行 API 版本化。 用户可能推迟更新,因此服务端必须继续为旧版本提供服务。上线后再补充版本化的成本远高于从一开始就采用版本化。
- 使用远程配置管理业务规则。 客户端发布依赖平台审核和用户采用。在平台规则允许的情况下,支持的阈值、文案和功能开关可以在服务端管理;需要发布新应用版本的变更仍然受这一依赖约束。
假设性设计目标
以下数值是假设性的容量规划示例,并非经过测量的客户结果、经过验证的容量建议或 SLA。应在明确工作负载、设备、数据、硬件和第三方依赖后,设定项目专属的验收目标;在承诺生产目标前,通过试点和负载测试进行验证。
容量与性能目标
| 目标 | 数值与假设 |
|---|---|
| 冷启动至首个有意义页面 | 在中端 Android 设备上低于 2 秒,假设缓存数据在网络刷新于后台运行的同时完成渲染。 |
| 增量同步 | 典型回访用户的增量数据载荷低于 200 KB,并限制分页大小,使长时间未上线的用户能够平稳降级,而不是发生超时。 |
| API 延迟 | 标准读取操作的 p95 低于 300 ms,不包括我们无法控制其延迟的第三方调用。 |
| 推送送达 | 定义并测量应用入队和服务提供商确认的时间。最终送达时间取决于平台,本参考不对此作出保证。 |
交付内容
- Flutter 应用源代码、Go 后端源代码和 Vue 管理后台源代码,存放在您的代码库中
- 两个平台的构建和签名配置,以及应用商店页面准备工作
- API 文档、数据库架构和迁移历史
- 部署说明、监控和日志访问、备份与恢复流程
- App Store 和 Google Play 提交支持;审核结果和审核时间仍由 Apple 和 Google 决定
为您的业务进行规划
上述模块是起点,而不是固定套餐。我们通常会将首个版本缩减为一个核心工作流程和一个管理后台工作流程,然后在真实使用情况显示实际负载和边界情况后再进行扩展。提交范围明确的需求,我们会将其与此架构进行对照,并告知您哪些部分目前还不需要。

