比特币节点的工作日常里有一件不停在做的事:主动打电话。全节点会不断从地址库里挑出候选邻居,发起出站连接。拨号这一步有成功、有失败、也有杳无回音,而决定等多久放弃的参数就是 -timeout。本文以 Bitcoin Core 31.0 源码为准,把这五秒的账算清楚。
等待发生在哪一步
出站连接的建立分几层。最底下一层是操作系统的 TCP 三次握手:节点调用 connect,现代实现多为非阻塞模式,函数往往立即返回一个「正在进行中」的错误码,而不是等到握手结束。Bitcoin Core 随后用异步 I/O 接口同步等待这个套接字上出现可写事件——出现即握手完成。ConnectToSocket 函数里的注释把这一流程说得很直白:连接并没有真正失败,而是在异步建立,因此用 select/poll 一类机制同步地检查连接是否成功,并带上一个超时。
这个超时的秒数就来自 -timeout。源码里它被折算成毫秒传给 sock.Wait,等待返回假值意味着超时耗尽,节点记下一条「wait for connect 失败」的日志后放弃;等待成功但事件为零则表示连接尝试超时,同样放弃这个目标地址。一个域名解析出多个地址时,换下一个继续试。

默认五秒,最低一秒
netbase.h 中 DEFAULT_CONNECT_TIMEOUT 定义为 5000 毫秒,init.cpp 里的参数说明写着允许的最小值是 1 毫秒、默认 5000。也就是说缺省配置下,节点对每一次连接建立最多等五秒。把值调小不会让网络变快,只会让节点更早放弃慢路径;调大则拉长每次失败探测的占用时间,在种子与熟人全部失灵时,一轮冷启动要多花好几倍钟点。绝大多数部署没有理由动它。
它不管什么
-timeout 只覆盖「握手前的链路建立」。连接建成之后,version 与 verack 消息交换是否完成、后续消息多久没动静该断线,由另一条时间线管理:-peertimeout 负责在超时未收到 verack 时断开并拉黑,也在连接建立后负责消息停滞的处置(可参考 节点的一条消息帧里有什么 里对消息层的拆解,以及出站连接线程的整体节奏,见 bitcoind 的线程名册)。RPC 层面的等待同样是另一套账。三层各自独立,排查问题时不要互相顶包:连不上先看 -timeout 五秒内是否有 timed out 日志,连上又掉再查 -peertimeout。
什么时候值得看一眼这个参数
有三类场景值得核对它的表现:一是走代理链路或覆盖网络(Tor、I2P)的首连,五秒可能经常不够,节点会表现为反复换目标却始终建不成连接,日志里 connection attempt to ... timed out 密集出现;二是机器负载过高、内核连接队列打满时的出站连接;三是人为把值调得过小的测试环境。普通用户保持默认即可,这个参数的设计初衷就不是性能旋钮,而是失败判定的止损线。
五秒钟很短,但足够区分「对方网络不通」与「对方根本不存在」。还要划清一个容易越界的期待:-timeout 管不了「连上了但握手太慢」,也管不了「对端响应消息迟缓」——那些分别是版本超时与消息停滞的账。它是三层超时体系里最靠外、也最沉默的一层:平时你感觉不到它,只有当某个网段的连通性整体劣化时,它才会以日志里成片的 timed out 现身。Bitcoin Core 把这条线画在连接建立之前,让后续的握手与消息层各自守住自己的时间纪律,节点拨出的每一通电话因此既有耐心也有止损。最后留一个自查动作:翻一遍自己节点的 debug 日志(-debug=net),统计 timed out 出现的频率与目标网段,比凭感觉调整任何超时参数都更有依据。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。