返回文档导航

Worker 当前架构与演进边界

v1.0 · 2026-07-17 · 依据 beex-service 当前代码与现网部署修订
BeeX 已经完成运行形态拆分。业务代码仍由同一套 beex-service 构建,但在部署时通过 SEAHUB_SERVICE_ROLE 分成 api、wa、worker、webhook 四个独立进程;只有 worker 开启 Spring Scheduling。本文记录当前事实,不再把已完成的拆分写成未来计划。

1. 当前结论

api · 7002

App/H5 用户接口,不运行定时任务。

对外服务
wa · 7010

WhatsApp 登录、消息与机器人链路,不运行定时任务。

消息入口
worker · 7020

订单同步、结算、清理、刷新与推送调度。

唯一调度进程
webhook · 7030

Xendit、平台和其他第三方回调,不运行定时任务。

回调入口
已落地:四个角色拥有独立应用名、端口、systemd/JAR 和云效流水线;生产 worker 无公网业务入口。管理后台是独立仓库 beex-admin-service,不属于这四个角色。

2. 运行角色和流量边界

flowchart LR
  CLIENT["App / H5"] --> ALB["ALB / Nginx"]
  META["Meta WhatsApp"] --> ALB
  THIRD["Xendit / TikTok / Shopee / Feishu"] --> ALB
  ALB -->|"/api/**"| API["api :7002"]
  ALB -->|"/webhooks/whatsapp"| WA["wa :7010"]
  ALB -->|"其他 /webhooks/**"| WEBHOOK["webhook :7030"]
  WORKER["worker :7020"] --> DB[("MySQL")]
  WORKER --> REDIS[("Redis Lock")]
  WORKER --> PLATFORM["第三方平台 API"]
  API --> DB
  WA --> DB
  WEBHOOK --> DB
      
角色Spring profile / 默认角色SchedulingHTTP 原则
apiapplication-api.properties关闭仅开放用户业务接口和健康检查。
waapplication-wa.properties关闭仅开放 WhatsApp 所需路径。
workerapplication-worker.properties开启不承接外部业务流量,只保留健康与受控诊断。
webhookapplication-webhook.properties关闭只开放指定第三方回调路径。

ServiceRoleHttpFilter 按角色限制 HTTP 路径;不允许通过“部署了同一个 JAR”推断每个进程都能处理所有接口。

3. 当前定时任务清单

当前代码共 13 个 @Scheduled 入口。频率均可由环境变量覆盖,表中为代码默认值。

任务默认周期主要写入/影响风险级别
TikTok CAP 订单同步15 分钟订单、归因、佣金、活动权益资金高风险
TikTok Creator 订单同步15 分钟订单、归因、佣金、活动权益资金高风险
Shopee Conversion 同步15 分钟订单、归因、佣金、活动权益资金高风险
Lazada Conversion 同步15 分钟订单、归因、佣金、活动权益资金高风险
Traveloka 订单同步15 分钟订单、归因、佣金资金高风险
佣金到期释放5 分钟佣金状态、钱包账本资金高风险
Xendit 余额不足提现重试10 分钟提现单、冻结/解冻余额资金高风险
Push 消息派发5 秒推送任务状态、APNs/FCM
优惠券过期扫描5 分钟用户券状态
TikTok Partner Campaign 商品同步30 分钟高返佣商品缓存
TikTok 授权账号 Token 刷新60 分钟平台授权账号
App Store 版本同步60 分钟Native 版本配置
Ops 监控刷新60 秒监控快照与告警
邀请绑定:识别到分享人即直接建立一层邀请关系,WhatsApp JOIN 流程调用 userRepository.bindInviterIfAbsent + growthRepository.bindRelation,与 GrowthController.bind() 同一套逻辑。

4. 调度开关

ServiceSchedulingEnabledCondition 是调度的唯一总门禁:

  1. 如果配置了 seahub.scheduling.enabled,以该布尔值为准。
  2. 没有显式配置时,仅 role=workerrole=all 开启。
  3. api、wa、webhook 的环境配置显式设为 false;worker 显式设为 true
部署约束:生产禁止使用 role=all。它只适合本地兼容启动,否则会重新造成 API 实例跑定时任务。

5. 锁、幂等与游标

机制当前要求验收方式
分布式任务锁多 worker 实例只能有一个实例执行同一批任务;TTL 必须覆盖正常执行时间并支持失败释放。并行启动两个 worker,确认同一锁窗口只有一条执行记录。
平台订单幂等平台订单号/明细号建立唯一约束;重复拉取只能更新状态,不能重复创建佣金。对同一时间窗重复同步两次,订单数和钱包账本不增加。
佣金与钱包幂等佣金记录、权益预占和钱包 ledger 使用稳定业务幂等键。重放订单状态回调,用户余额只变化一次。
同步游标与回看窗保存平台游标,同时保留重叠回看时间窗,避免边界订单丢失。模拟任务中断后恢复,边界订单仍能补齐。
失败可重试区分临时错误和永久错误;记录 requestId、平台错误码、重试次数与下一次时间。第三方 5xx 恢复后任务自动成功,4xx 不无限重试。

6. 部署与发布

测试和生产均使用独立流水线发布四个角色,同一 commit 可以分别构建和部署。真实机器、流水线 ID、ALB 路由和 systemd 路径以 部署总览 为唯一来源,本文件不复制易漂移的基础设施明细。

sequenceDiagram
  participant G as Git Commit
  participant P as Yunxiao Pipeline
  participant A as Artifact
  participant E as ECS Role Instance
  participant H as Health Check
  G->>P: 选择同一 commit
  P->>A: Maven 构建并生成制品
  P->>E: 按 api/wa/worker/webhook 发布
  E->>H: 角色、端口、健康检查
  H-->>P: 成功或自动失败
      

任何修改都必须走对应云效流水线;不以手工复制 JAR 或 SSH 启动作为正式发布方式。

7. 监控与告警

  • 每个同步任务记录:开始时间、结束时间、扫描范围、拉取数、新增数、更新数、失败数、平台 requestId。
  • 核心指标:最后成功时间、连续失败次数、同步延迟、订单未归因率、佣金生成失败数、锁等待时间。
  • 订单同步超过两个正常周期未成功、资金任务发生异常、Token 即将过期时必须通知飞书。
  • 告警消息显示环境、国家、任务名、代码版本和可定位的 trace/requestId,不能只写“任务失败”。

8. MQ 演进条件

当前核心模式仍是 Worker 定时拉取 + 数据库事务 + 分布式锁。§3 里标"中/低"风险的 5 个非资金任务已经启动 Outbox + RocketMQ 迁移(不等触发条件,现在就做,理由、采购决策和方案见 Outbox + RocketMQ 接入技术方案)。资金相关的 7 个任务不在这次范围内,继续按下面的触发条件评估是否需要接入:

  • 订单后处理耗时显著拖慢平台同步游标推进。
  • 佣金、活动、通知、BI 需要独立重试和独立扩容。
  • 单任务批次持续超过调度周期,或 DB 扫描成为瓶颈。
  • 需要可回放的业务事件审计,而数据库任务表已不足以支撑。
flowchart LR
  SYNC["平台订单同步"] --> DB["订单事务落库"]
  DB --> OUTBOX["Outbox 事件"]
  OUTBOX --> MQ["RocketMQ(Phase 1 非资金任务已启动, 资金路径触发后再评估)"]
  MQ --> REWARD["佣金/活动消费者"]
  MQ --> NOTICE["通知消费者"]
  MQ --> BI["BI/埋点消费者"]
      

演进顺序固定为:先落 Outbox,再发布消息;消费者使用业务幂等键。禁止在数据库事务提交前直接发消息。

非资金任务的具体技术方案:Outbox + RocketMQ 接入技术方案——阿里云 RocketMQ 在雅加达没有 Serverless 可用区,只能买标准版/专业版,年付 ≈¥17,000,已确认接受该成本按此采购;同时做了可替换的发布/订阅接口设计,以后 broker 要再换只改实现类。

9. 运维验收清单

  • api、wa、webhook 日志中不出现定时任务执行记录。
  • worker 日志显示 role=worker 且调度开启,但外部业务路径返回 404。
  • 双 worker 部署时,同一任务不会重复生成订单、佣金、钱包账本或通知。
  • 任一角色单独发布不会覆盖其他角色 JAR,也不会重启其他角色。
  • 任务连续失败、订单延迟和授权过期均有飞书告警。
  • 测试验证后,生产用同一 commit 分角色发布,并记录发布人与版本。