Skip to content

NACP 生命周期 ​

NACP 生命周期分为 NApp 链路生命周期和消息生命周期。

前者维护了一个NApp链接情况,后者用于维护一个消息的情况。

App 链路生命周期 ​

每个已完成 Register 的 App ID 都处于以下状态之一:

状态含义出站消息
onlineApp 已绑定且当前可达立即尝试发送
offlineApp 暂时不可达,等待重新连接进入 积压表 暂存
droppedApp 已被彻底遗忘放弃并结算相关等待方

online ​

Register 握手成功后,NACP 建立 App ID 与 NACT Peer 的绑定,App 进入 online。

发往该 App 的消息会先进入 积压表Backlog,再立即尝试提交给对应 Peer。提交后等待 Provider 接纳确认;接纳完成后,可靠消息才开始 ACK 超时计时。

TIP

正常情况下 Backlog 只是出站通道,不会长期持有消息。

offline ​

当出现以下情况,会把 NApp 标记为 offline:

  • 承载该 NApp 的 NACT Peer 断开。
  • 发往该 NApp 的可靠消息超过 ackTimeoutMs 仍未收到 ACK。
  • NApp 在下一心跳周期到达时,发现上一条心跳仍未收到 Response。

进入 offline 时,NACP 会:

  • 保留 App ID、请求等待方和订阅记录,包括 AutoSubscribe。
  • 将已经发出但尚未收到 ACK 的消息移回 Backlog 队首。
  • 将仍在等待本端 Provider 接纳的消息放回 Backlog,等待重连后重新提交。
  • 启动 reconnectGraceMs 宽限计时。
  • 将后续出站消息继续加入 Backlog。

TIP

注意区分 ACK 超时和 Req 超时。前者用于判断链路可达性,不是 Request 的业务处理时限。

TIP

空闲链路没有业务消息时,NApp 也会周期性发送 NApp.heartbeat。它既会触发正常的 ACK 检查,也会在下一周期检查对应 Response。离线后只结束这条心跳自己的等待,普通业务请求继续保留在宽限期内。周期与关闭方式见 NAppOpts。

Re-online ​

同一 App ID 在宽限期内重新完成 Register 后,NACP 会取消宽限计时,并按 Backlog 中的原始顺序补发消息。

应用层心跳在离线时已被清理,重新注册后由 NApp 发起新的探测。

WARNING

可靠消息可能因此被重复发送,接收方会再次回复 ACK,但在去重记录有效期间不会重复处理。

dropped ​

以下情况会使 App 进入 dropped:

  • offline 超过重连宽限期。
  • 对端主动发送 Unregister。

进入 dropped 后,NACP 会彻底清理该 App 的协议状态:

  • 放弃 Backlog、提交中和 ACK 等待表中的消息,并以 false 结算对应发送等待方。
  • reject 仍在等待 Response 的调用。
  • 移除 SubscribeTable 与 ListenTable 中属于该 App 的记录。
  • 结束显式订阅与 AutoSubscribe 的本地监听。
  • 删除该 App 的入站去重记录和链路绑定。

Unregister 表示对端明确离开。本端先将回复交给 Provider 接纳,再清理状态并关闭连接,不等待 ACK 或重连宽限期。

消息生命周期 ​

需要 ACK 的消息 ​

Request、Response、Signal、Register、Unregister、Subscribe 和 Unsubscribe 使用两段出站队列:

BacklogTable 积压表 保存尚未提交或等待重发的消息。提交后、Provider 接纳确认前的记录单独跟踪,不再占用 Backlog;AckPendingTable确认表 保存已被 Provider 接纳、正在等待 ACK 的消息。

Notify与AckMessage ​

Notify 和 Ack 不等待 ACK,也不进入 AckPendingTable:

消息停留在离线 Backlog 中时,对应 Promise 保持 pending。

WARNING

Notify 是过程消息,最终结果由 Response 保证。

因此容量不足时会优先放弃 Notify,避免过程流挤占最终消息。

如果所有Notify都被放弃了,则按照FIFO顺序移除最早的消息。

Response 等待 ​

NACP区分消息已接收和消息已处理两个行为。

对于消息接收限时,默认为10s,超时则认为对端NApp离线。

对于消息处理限时,则区分:

操作Response 等待时间
request不设置业务超时
register / unregister10 秒
subscribe / unsubscribe10 秒

普通业务调用的 Response 等待方和 AutoSubscribe 会在 App 在线或处于重连宽限期时保留。心跳请求由 NApp 在下一周期检查应答,并在离线时结束自身等待。

容量限制 ​

BacklogTable 与 AckPendingTable 默认各自最多保存 1024 条、4 GiB。

两个队列分别执行容量限制,容量限制由queueMaxBytes和queueMaxCount决定

Backlog 溢出时按以下顺序处理:

  1. 新消息是 Notify:拒绝该 Notify,notify() 返回 false。
  2. 新消息是其他类型:先逐出最早的 Notify。
  3. 仍然超限:按 FIFO 逐出最早的其他消息。

AckPendingTable 不包含 Notify,溢出时按 FIFO 逐出等待 ACK 的消息,并以 false 结算对应 ACK 等待方。

具体告警可以通过 nacp:internal:backlog:warning 与 nacp:internal:ack:warning 观察。详见可观测

NACP 终止 ​

nacp.terminate() 会立即结束全部 NACP 状态:

  • reject 所有 Response 等待方。
  • 移除全部 EventBus 转发监听和本地订阅记录。
  • 清空链路、Backlog、ACK、去重记录与计时器。
  • 以 false 结算尚未完成的发送等待方。

各阶段使用的数据结构见内部记录表,生命周期事件见可观测。

Released under the MIT License.