Prhub

#51219 [Bugfix] Close usage telemetry HTTP sessions

原始 PR 作者 matteso1 合并时间 2026-08-08 08:29 文件变更 1 提交数 1 评论 6 代码增减 +2 / -3

执行摘要

关闭用量上报残留 HTTP 会话,兼容进程快照检查

PR body 指出:#6600 将 HTTP 调用统一到共享 session,但用量上报只在启动和每 10 分钟发送一次,共享连接会在两次上报之间在前端保留外部 HTTPS socket。作者实测 d36f24b66 在启用上报时进程树保留一个已建立的外部 IPv6 HTTPS socket,导致 #51360 的快照检查在创建快照前拒绝该状态;关闭上报(VLLM_NO_USAGE_STATS=1)后为零外部 socket。修复目标是保持 telemetry 开启的同时让进程快照可用,避免用户被迫关闭上报。

值得快速浏览:这是一个精准、低风险的兼容性修复,展示了 vLLM 中共享 HTTP 连接与进程快照(文件描述符状态检查)之间的权衡。关注 _send_to_server 的一次性 Session 取舍,以及低频路径用自己的连接、高频资源路径用共享连接的分层策略;对想理解 vLLM checkpoint/restore 前置条件的读者有参考价值。

讨论亮点

核心讨论围绕两点:一是动机确认,simon-mo 在 issue 评论区询问 'what's the benefit of doing this? Is this for safe processing snapshotting?',matteso1 确认是 safe process snapshotting,并说明 #51360 会拒绝 established external HTTPS socket,否则用户需 VLLM_NO_USAGE_STATS=1 才能快照;二是测试取舍,simon-mo 在 tests/test_envs.py 的 review 评论 'you can skip the test for this change given the behavior is explanatory',matteso1 回复 'removed',新增的 test_usage_report_closes_http_session 最终未合入。

实现拆解

  1. 变更入口:vllm/usage/usage_lib.pyUsageMessage._send_to_server(),这是启动上报和 10 分钟心跳共用的发送路径。
  2. 核心改动:将 global_http_connection.get_sync_client().post(...) 替换为 with requests.Session() as client: client.post(...),并同步删除 from vllm.connections import global_http_connection 导入。上下文管理器保证每次上报完成后 session 关闭、底层 socket 释放。
  3. 影响范围:仅影响 usage telemetry 路径;asset、media 与 batch 请求仍走 global_http_connection 共享连接,行为不变。
  4. 测试配套:作者最初在 tests/test_envs.py 添加了 test_usage_report_closes_http_session(mock Session 验证 post 调用与 __exit__),但 review 中 simon-mo 建议跳过,最终从 PR 移除,合入版本无新增测试。
文件 模块 状态 重要度
vllm/usage/usage_lib.py 用量上报 modified 5.3

关键符号

_send_to_server _report_continuous_usage

关键源码片段

vllm/usage/usage_lib.py core-logic

唯一变更文件,将用量上报从全局共享 HTTP 客户端改为上下文管理的一次性 requests.Session,并删除对应导入,消除两次上报间残留 socket,使进程快照检查不再被拒。

class UsageMessage:
    """用量上报入口:启动时上报一次,之后每 10 分钟心跳一次。"""
​
    def _report_continuous_usage(self):
        while True:
            time.sleep(600)
            data = {
                "uuid": self.uuid,
                "log_time": _get_current_timestamp_ns(),
            }
            data.update(_GLOBAL_RUNTIME_DATA)
            self._write_to_file(data)
            # 心跳数据同样走一次性 session,上报后连接立即关闭
            self._send_to_server(data)
​
    def _send_to_server(self, data):
        try:
            # 使用 requests.Session 上下文管理器:请求结束后立即关闭连接,
            # 避免两次上报之间(最长 10 分钟)残留外部 HTTPS socket,
            # 从而兼容进程快照(checkpoint/restore)对已建立连接的状态检查。
            with requests.Session() as client:
                client.post(_USAGE_STATS_SERVER, json=data)
        except requests.exceptions.RequestException:
            # 静默失败:telemetry 不阻塞主流程,仅保留 debug 日志
            logging.debug("Failed to send usage data to server")

评论区精华

变更动机:safe process snapshotting question

simon-mo 在 issue 评论区询问这样做的好处,以及是否为安全进程快照;matteso1 确认是,并说明 #51360 拒绝 established HTTPS socket 的状态检查导致快照无法创建,而共享连接无法被安全恢复。

结论:确认动机为进程快照兼容,修复采用一次性 session 保持 telemetry 开启。 · 已解决

是否保留新增单元测试 测试

simon-mo 在 tests/test_envs.py 的 diff 上评论 'you can skip the test for this change given the behavior is explanatory',建议移除新增的 test_usage_report_closes_http_session;matteso1 回复 'removed'。

结论:测试从 PR 中移除,最终仅保留源码改动。 · 已解决

风险与影响

  1. 配置绕行风险:requests.Session() 是裸会话,不再经过 global_http_connection 的统一客户端。若共享客户端承载了代理、超时、重试或 TLS 配置,上报路径将不再继承,特殊网络环境下可能上报失败;失败会被现有 except 静默吞掉,不直接影响服务。
  2. 回归风险:合入版本无新增测试,_send_to_server 的异常路径与 session 关闭行为依赖人工验证;未来若有人重新引入共享客户端,可能回归。
  3. 性能影响:每 10 分钟新增一次 TCP/TLS 连接建立,开销可忽略;但相比原来复用连接,心跳上报延迟略有增加。

用户侧:启用 telemetry 的前提下,进程快照/恢复(checkpoint/restore,#51360)不再被残留 HTTPS socket 拒绝,快照可正常创建与恢复;无需再设置 VLLM_NO_USAGE_STATS=1。系统侧:外部连接从无限期保持到下次上报变为请求完成即关闭,进程文件描述符环境更干净。团队侧:遥测数据采集不受影响,上报成功率预期不变;但若未来需要统一 HTTP 客户端配置,需额外考虑 telemetry 路径。

共享客户端配置绕行 无新增测试覆盖 每 10 分钟一次新连接

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论