hyapp-server/docs/多App租户架构.md

5.0 KiB
Raw Permalink Blame History

Multi App Tenant Architecture

本文定义 hyapp-server 同时服务多个 App 时的租户边界。当前后端不再默认只服务单个 Apppopoolalusiya 这类产品都必须先解析成内部 app_code,再进入用户、房间、钱包、活动和 host 业务链路。

Core Rule

app_code 是后端内部租户键。客户端包名、Bundle ID、渠道名和展示 App 名都不能直接作为业务表隔离键。

首个内置映射:

package_name platform app_code status
com.org.laluparty android lalu active

新增 App 时,只新增 apps 注册表记录和对应 App 的基础配置/种子数据,不新建一套服务,也不复制业务代码。

App Registry

apps 表由 user-service 持有,放在 hyapp_user 库:

apps(
  app_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  app_code VARCHAR(32) NOT NULL,
  app_name VARCHAR(128) NOT NULL,
  package_name VARCHAR(191) NOT NULL,
  platform VARCHAR(32) NOT NULL DEFAULT '',
  status VARCHAR(32) NOT NULL,
  created_at_ms BIGINT NOT NULL,
  updated_at_ms BIGINT NOT NULL,
  UNIQUE KEY uk_apps_code (app_code),
  UNIQUE KEY uk_apps_package_platform (package_name, platform)
);

gateway-service 可以通过包名和平台解析 app_code,也可以校验显式传入的 app_code。解析入口是 user-service.AppRegistryService.ResolveApp

Request Flow

sequenceDiagram
  participant C as Client
  participant G as gateway-service
  participant U as user-service
  participant R as room-service / wallet-service / activity-service

  C->>G: HTTP request + package/platform/app_code header
  G->>U: ResolveApp(package_name, platform, app_code)
  U-->>G: active app_code
  G->>G: write request context and JWT claims
  G->>R: gRPC RequestMeta.app_code
  R->>R: all reads and writes are scoped by app_code

Header 约定:

Header Meaning
X-App-Code / X-HY-App-Code / App-Code 已知内部 app_code
X-App-Package / X-Package-Name / X-App-Bundle-ID / X-Bundle-ID 客户端包名或 Bundle ID
X-App-Platform / X-Platform androidios

已登录请求以 JWT 里的 app_code 为准。未登录登录/注册请求允许通过包名解析;解析成功后,user-service 签发的 token 必须带同一个 app_code

App Scoped IDs

对客户端暴露的用户长 ID 和房间长 ID 都带 App 前缀,格式为:

<app_code>_<uuid>

例如 com.org.laluparty 解析到 lalu 后,新用户的 user_id 是数值型主键,新房间的 room_id 仍按 App 生成 lalu_<uuid>。服务间主关联使用 users.user_idJWT 只携带数值型 user_idgateway 直接把该 ID 透传给后端 RPC。

用户短号 display_user_id 按 App 独立发号,首个号段从 163000 开始。创建房间时 room_short_id 等于创建者当前短号,用于客户端搜索、分享和展示。

Data Boundary

以下业务库表都必须有 app_code,并且查询、唯一键和幂等键都必须带 app_code

Service Database Scope
user-service hyapp_user users、登录身份、session、国家、区域、短号、host/Agency/BD 事实
room-service hyapp_room 房间元数据、房间列表、快照、命令日志、room outbox
wallet-service hyapp_wallet 账户、交易、分录、wallet outbox、礼物价格
activity-service hyapp_activity 活动状态、事件消费幂等、activity outbox

规则:

  • 跨 App 可以存在相同 display_user_id、相同三方 provider_subject、相同钱包 command_id;对外长 ID 自带 app_code 前缀,仍然要求落库唯一键带 app_code
  • 业务查询不能只用 user_idroom_idcommand_id;必须同时带 app_code
  • outbox envelope 必须带 app_code,消费者按事件所属 App 落库和幂等。
  • 默认 lalu 只用于本地开发和历史测试兜底;真实客户端请求必须能解析出明确 App。

Admin Boundary

后台管理后端使用独立 hyapp_admin 库,不把后台审计表写进 App 业务库。后台操作某个 App 的用户、区域、host、钱包或房间时HTTP 请求必须显式携带或由后台上下文选择 app_code,再调用对应业务能力。

hyapp_admin.admin_operation_logs 可以在 detail 中记录 app_code、目标对象和变更摘要;不要为了审计把 admin 表复制到各 App 业务库。

Adding A New App

以新增 popoo 为例:

  1. apps 表插入 app_code=popoo、包名、平台和状态。
  2. popoo 初始化国家、区域、礼物价格、登录 provider/Firebase 配置。
  3. 客户端请求携带包名和平台gateway 解析到 popoo
  4. 注册、房间、钱包、活动、host 数据自动按 app_code=popoo 写入现有表。

新增 App 不需要拆新微服务;只有当业务规则、部署生命周期或数据合规要求必须强隔离时,才考虑单独部署一套服务集群。