多渠道消息网关与并发消息去重队列
深度透视 gateway/run.py 多平台适配、dedup_key 重复拦截与进度消息坍缩算法
📊 图 5-1:多租户消息网关的分流架构与消息去重过滤原理图
🔌 1. 网关分流模型与 GatewayRunner 调度
消息网关是智能体常驻后台的触角,用于连接飞书、Telegram、钉钉等 20 多种不同聊天平台。网关的主控中枢为 gateway/run.py:
- GatewayRunner 类:网关的核心管理进程。它会在服务拉起时拉取
config.yaml中的平台参数配置,并在独立的 asyncio 事件循环中,并行为每一个启用的通讯平台单独起一个Adapter。 - 模块动态加载:每个平台对应的通讯逻辑被隔绝在
gateway/platforms/的单独子脚本(例如telegram.py、feishu.py)中。系统动态加载它们以维持低开销。
🛡️ 2. 并发防抖与 dedup_key 消息去重拦截
在网络状况糟糕的环境下,通信平台会因为 Webhook 响应延迟(如系统设置的 3 秒内未回包)自动发起消息重试。如果网关层没有把关,大模型便会被相同的请求重复呼叫多次,产生巨额 Token 账单。Hermes 在 gateway/run.py 实现了内存态与持久化态消息过滤防重入:
- 拼装去重键 `dedup_key`:当收到 Webhook 抛来的事件载荷时,网关对其进行结构化映射,并解析出特定的三个变量:
dedup_key = (platform_str, chat_id, thread_id) - notified 去重队列:系统维护了一个并发安全的
notified集合。如果一个dedup_key已经被加入,说明当前正有一个对应该对话的AIAgent实例在后台推理运转。新进的重复请求会被当场拦截丢弃而不会被推进任务队列,从底层保障了智能体交互的幂等性。
📉 3. 进度消息合并坍缩 (Progress Deduplication)
在工具密集调用的任务中,智能体会不停输出 [Executing: read_file],[Executing: terminal] 的运行提示。如果在聊天框里每完成一步就发一条独立消息,会让用户的 IM 界面充斥无用气泡(刷屏)。为了净化体验,网关在处理下行进度提示时,将重复状态压入特定的进度消息合并机制,其流转关系如下图所示:
📊 图 5-2:进度消息合并坍缩 client-side 动态修改气泡时序流转图
# gateway/run.py 中的进度合并逻辑
def handle_progress_stream(progress_queue):
last_progress_msg = None
repeat_count = 0
while True:
raw_msg = progress_queue.get()
# 检测是否和上一条进度消息一致
if raw_msg == last_progress_msg:
repeat_count += 1
# 放入带有特殊 __dedup__ 标签的元组,通知网关这是个重复的进度事件
progress_queue.put(("__dedup__", raw_msg, repeat_count))
else:
last_progress_msg = raw_msg
repeat_count = 0
progress_queue.put(raw_msg)
当网关向平台发送消息时,如果解析到 "__dedup__",则不调用 send_message,而是直接调用该平台的 edit_message API 将上一个气泡内容追加 (x3) 等重复计数。这样在聊天软件前端看去,只会有单行文字进度在流畅变化,体验极为premium。
⏳ 4. 优雅停机信号拦截与反向中断广播
当网关作为守护进程在后台运行时,随时会因为 systemd 或 K8s 部署更新,收到操作系统发出的 SIGTERM 强制停机信号。如果粗暴直接退出,可能会导致正处于写入事务中的 SQLite 崩溃。网关设计了完善的退避广播:
- 信号劫持与上下文输出:网关在启动时利用
signal.signal(signal.SIGTERM, ...)绑定自定义的回调句柄。一旦捕获到信号,立即保存包括parent_pid,parent_cmdline,loadavg_1m(最近一分钟负载)在内的Shutdown context诊断日志。 - 反向中断置位:在清退前,网关会获取当前所有处于活跃在途运行状态的
AIAgent实例列表,将其_interrupt_requested属性强制置为True。 - 平滑持久化:大模型主循环会由于该布尔标志立即被拦截中断(中断当前的 LLM 线程),把当前状态刷入
state.db后安全断开 WebSocket 通信,优雅关闭进程。
🔗 本章子任务深入剖析专栏
为深度掌握 IM 消息网关机制,推荐阅读以下子技术专题: