Skip to content

15 - 离线推送通知协议 (Push Notification)

概述

当目标 AID 的所有设备均离线时,AUN Gateway 通过事件通知将推送摘要发送给 push_notify_aid(推送代理 AID),由其完成最终的平台推送(APNs / FCM / WebPush 等)。

设计原则:

  • push_notify_aid 是普通客户端 AID,不是 AUN 内部服务
  • 通过事件通知(非 P2P 消息)下发推送摘要——轻量、实时、不持久化
  • push_token 对 Gateway 完全不透明(opaque),push_notify_aid 自签自验
  • 任意一台设备在线即不触发推送
  • 推送内容仅含元数据,不含消息正文(E2EE 安全保证)
  • 背压控制:串行确认,Gateway 等 push_notify_aid ack 后再发下一批
  • 跨域推送:推送由目标 AID 所属域的 Gateway 触发,发送方域不参与

架构

关键约束:

  • push_notify_aid 作为普通客户端 AID 连接到 Gateway,通过事件通知接收推送摘要
  • push_notify_aid 离线时事件丢弃——推送是 best-effort,消息可靠性由 message.pull 保证
  • 目标 AID 有任意一台设备在线时,不触发推送

推送注册流程

应用层:客户端向推送代理注册

push_token 的格式、签名算法、有效期完全由 push_notify_aid 自行决定。AUN 协议不做任何约束。

协议层:connect 时携带推送配置


离线推送时序


背压与 in-flight 控制

参数

参数默认值说明
max_in_flight1同一 push_notify_aid 未确认批次上限(串行)
ack_timeout30s超时未 ack 自动释放槽位
batch_size50每批最多聚合多少个 target_aid 的通知

行为规则

  • in_flight < max → 发送事件,in_flight++
  • in_flight = max → 排队等待
  • 收到 push.ack(batch_id) → in_flight--,触发队列中下一批
  • 超时 → in_flight--,不重试(推送是 best-effort,过时推送是噪音)
  • push_notify_aid 离线 → 事件丢弃,in_flight 不增加

在线判断规则

边界情况:

  • 目标 AID 上线瞬间:清空该 AID 的聚合桶,取消待发推送
  • 最后一台设备断连:不立即触发推送,只有后续新消息到达时发现全离线才走推送路径

跨域推送

核心原则:推送由目标 AID 所属域的 Gateway 触发。

发送方域不感知目标域的 push_config 和白名单,也不需要任何跨域配置同步。

规则:

关注点行为
推送配置存储仅存于目标 AID 所属域,不跨域同步
白名单管理各域独立配置 allowed_notify_aids,互不影响
push_notify_aid 必须连接位置目标 AID 所属域的 Gateway
push_notify_aid 跨域时不支持。push_notify_aid 必须与其服务的 AID 同域
summary.senders 中的跨域 AID保留完整 AID(含域名),如 alice.domain-a.com

约束: push_notify_aid 必须与其服务的目标 AID 处于同一域。如果应用希望在多个域提供推送服务,需要在每个域部署独立的 push_notify_aid 并分别加入白名单。


聚合与频控

PushAggregator 数据结构

每个离线目标 AID 一个聚合桶:

bucket[target_aid] = {
    push_notify_aid: "push.myapp.com",
    push_token: "eyJhb...",
    pending: [{from, msg_id, ts}, ...],
    first_enqueue_ts: timestamp,
    last_push_ts: timestamp,
}

去重规则

同一 target_aid 在频控窗口内只产生一次推送通知。具体行为:

  • 首条消息触发推送后,该 target_aid 进入频控冷却期(默认 60s)
  • 冷却期内新消息只更新聚合桶的 summary(unread_count++、senders 去重追加),不产生新推送
  • 冷却期结束时,若桶内有新增未推送内容,合并为一条推送发出

效果:无论短时间内收到多少条消息,target_aid 最多每 60s 收到一次推送通知,且 summary 是累积聚合的。

触发规则

规则说明默认值
首条即推桶为空且不在冷却期时,第一条消息立即触发开启
窗口聚合首条之后的消息等待窗口合并5 秒
数量上限桶内积累 N 条立即触发(不等窗口)20 条

频控规则

维度限制说明
同一 target_aid60 秒内最多 1 次推送避免终端刷屏
同一 push_notify_aid1000 次/分钟保护推送代理服务
全局5000 次/分钟系统保护

频控被触发时消息不丢弃,等窗口过后下一次聚合时一并推送。


协议字段

connect 扩展字段

json
{
  "method": "auth.login",
  "params": {
    "aid": "bob.example.com",
    "challenge_response": "...",
    "push_notify_aid": "push.myapp.com",
    "push_token": "eyJhbGciOiJIUzI1NiJ9..."
  }
}
  • push_notify_aidpush_token 均为可选字段
  • 两者必须同时提供或同时不提供
  • 不提供 = 不需要离线推送
  • 每次 connect 覆盖写(最新连接为准)

事件通知格式

Gateway 向 push_notify_aid 下发的事件通知:

json
{
  "method": "event/push.offline_message",
  "params": {
    "batch_id": "uuid-xxx",
    "items": [
      {
        "target_aid": "bob.example.com",
        "push_token": "eyJhbGciOiJIUzI1NiJ9...",
        "summary": {
          "unread_count": 3,
          "senders": ["alice.example.com", "charlie.example.com"],
          "latest_ts": 1716100005,
          "group_ids": ["group-uuid-1"]
        }
      }
    ]
  }
}

安全约束: 不包含消息正文。E2EE 场景下 Gateway 无法解密,推送代理只需知道"有 N 条未读来自谁"即可构造推送文案。

push.ack RPC

push_notify_aid 处理完一批推送后回调确认:

json
{
  "method": "push.ack",
  "params": {
    "batch_id": "uuid-xxx"
  }
}

Gateway 收到后释放 in-flight 槽位,触发下一批。

push.update_config RPC(可选)

允许客户端在不重连的情况下更新推送配置:

json
{
  "method": "push.update_config",
  "params": {
    "push_notify_aid": "push.myapp.com",
    "push_token": "new-token..."
  }
}

push_token 鉴权模型

push_notify_aid 白名单

Gateway 配置允许的 push_notify_aid 白名单,只有白名单内的 AID 才能被设置为推送代理:

  • 客户端 connect 时携带的 push_notify_aid 不在白名单内 → 忽略该字段,不报错,不存储
  • 白名单为空 → 禁用推送功能
  • 白名单配置在 Gateway 启动配置中,运行时不可动态修改
json
{
  "push": {
    "allowed_notify_aids": [
      "push.myapp.com",
      "push.partner.com"
    ]
  }
}

token 透传模型

职责划分:

角色职责
push_notify_aid签发 token、验证 token、决定格式和有效期、处理后 ack
Gateway存储 token、透传 token、不解析不验证、管理 in-flight
Client向 push_notify_aid 申请 token、connect 时携带

持久化

push_config 表

sql
CREATE TABLE push_config (
    aid VARCHAR(255) PRIMARY KEY,
    push_notify_aid VARCHAR(255) NOT NULL,
    push_token TEXT NOT NULL,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
  • 随 connect 写入/更新(UPSERT)
  • 可加内存缓存(TTL 5 分钟)

边界情况

场景处理
push_notify_aid 离线事件丢弃,不持久化。推送是 best-effort,消息可靠性由 pull 保证
目标 AID 未配置推送不推送,消息正常持久化等对方上线 pull
目标 AID 上线瞬间清空聚合桶,取消待发推送
E2EE 消息推送内容只含元数据(发送者、数量),不含密文
群组消息群内每个离线成员独立聚合,summary 含 group_ids
push_token 过期push_notify_aid 丢弃但仍 ack,客户端下次 connect 刷新 token
ack 超时释放槽位,不重试。后续新消息触发新批次时会包含累积通知
同一 AID 多设备不同推送配置以最后一次 connect 为准(单条记录覆盖)
跨域消息推送由目标 AID 所属域的 Gateway 触发,发送方域不参与
push_notify_aid 跨域不支持,必须与目标 AID 同域

AUN Protocol Documentation