一个连接要经过几次超时,才有资格说失败

举报
yd_48584989 发表于 2026/11/04 08:51:07 2026/11/04
【摘要】 我原来只给探测设一个超时:1 秒。十次探测十次超时,我就把「超时」当成了「端口没开」。后来量了一遍才知道,一次连接要穿过好几层等待,每层的量级差三四个数量级,用同一个数字去量全部,结论必然是错的。

我写过一段很短的探测代码,核心就三行:建 socket、设一个 1 秒的超时、连一下。

s = socket.socket()
s.settimeout(1)
try:
    s.connect((host, port))
    print("up")
except socket.timeout:
    print("down")            # 我把这里当成「端口没开」

这段代码在我手里跑了很久,结论一直很稳定:目标「没开」。直到有一天我把异常类型和耗时一起打出来, 才发现十次探测里有十次抛的是 socket.timeout,一次 ConnectionRefusedError 都没有。 而在我这台机器上,拒绝一个连接要花 2032 ~ 2060 毫秒——比 1 秒长。 也就是说,我的超时永远先到期,我从来没等到过那个「拒绝」。

拒绝和超时是两个完全不同的事实。前者说明有东西在回应你,只是它不认识这个端口; 后者说明你可能连说话的对象都没有。把它们合并成一个布尔值,等于主动放弃分辨能力。

一次连接要穿过的四层等待

把整条链路上会等的地方列出来,量级差得离谱:

层 我在实测里看到的量级 给多少合适
TCP 连接建立(含被防火墙丢包时的重传) 本机被拒 2.0 ~ 2.1 秒;远端跨省 30 ~ 120 毫秒 3 ~ 5 秒
单点登录回跳(302 链 + 票据校验) 一次完整登录 20.7 秒 30 秒
应用层首次响应(容器/工作区启动) 从点进去到侧边栏可用约 100 秒 不是超时问题,是异步任务
WebSocket 连接建立 不设上限时可能永远挂着 必须显式给 10 秒

第一行那个 2 秒最反直觉。它不是因为服务慢,是因为握手包被丢了,客户端按操作系统的重传节奏 等了一轮。整齐的两秒(十个样本全落在 30 毫秒的区间里)说明它是一条固定的路径, 不是随机的网络抖动。这个「整齐」本身就是判据:抖动不整齐,机制才整齐。

超时要按层设,不能设一个总数

我后来把探测改成三段,每段一个数字,各管各的:

t_connect = 4        # 连接建立:要能覆盖被丢包后的重传
t_read    = 15       # 等服务端第一个字节:跟业务有关

s.settimeout(t_connect)
s.connect((host, port))
s.settimeout(t_read)          # 连上之后换一个超时,不要复用

关键在于第二行 settimeout:连接阶段和读取阶段该用不同的值。 连接阶段慢通常意味着包丢了,读取阶段慢通常意味着服务在算。这两件事的对策完全相反: 前者的对策是换网络路径,后者的对策是加时间或者异步化。 用一个 5 秒把两段都盖住,两种问题会产出同一种日志。

WebSocket 那一层最容易忘

HTTP 客户端基本都带默认超时,而 WebSocket 客户端常见的行为是「一直等」。 我现在的连接代码里,建立连接这一步固定写成:

ws = await websockets.connect(url, open_timeout=10, ping_interval=None)

open_timeout 是建立握手那一步的上限,跟收到第一条消息之后的空闲超时不是一回事。 少了它,对方不回应握手的时候,进程会安静地停在那里,日志上什么都不写—— 既不报错也不退出,看上去像「卡住了」,实际上是在等一个永远不会来的响应。

同一次改造里我还把 ping_interval 显式设成 None。 默认的心跳在某些服务上会被当作异常流量直接断开,断开发生在空闲期, 症状是「用着用着突然没了」,很难归因。

三条结论

一、超时值必须大于你实测到的正常上限,而不是你期望的值。我实测拒绝要 2 秒, 设 1 秒就等于把「拒绝」永久翻译成「超时」。

二、连接阶段和读写阶段的超时要分开设。它们的失败含义不同,混在一起就再也分不开。

三、WebSocket 一类长连接,建立阶段必须显式给上限。没有上限的等待不会报错, 它只是让进程安静地停住,这是最难查的一类故障。

这三条都不需要多聪明,只需要在写第一行网络代码的时候问一句: 我准备等的这个东西,正常情况下要花多久?如果答不上来,那个数字就是猜的。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。