启动日志里那句收缩连接数:文件描述符预算怎么决定节点真正的连接上限 图 1
启动日志里那句收缩连接数:文件描述符预算怎么决定节点真正的连接上限 · 图 1

在配置里写了 maxconnections=200,启动日志里却出现一句“Reducing -maxconnections from 200 to 37, because of system limitations.”——很多人以为这是节点在讨价还价,实际上它是节点在报一个物理事实:这台机器能同时持有的网络句柄只有这么多,你写的数字它拿不到。比特币核心在启动阶段会做一次文件描述符预算核算,算出来的结果才是要生效的连接上限。理解这本账,比背参数表更能解决“连接数上不去”的问题。

核算过程在 v31.0 的启动代码里读起来很直白。节点先算出一个最低需求,由三部分相加:核心自身必须占用的描述符(源码里的 MIN_CORE_FDS 常量)、手动连接的名额上限(MAX_ADDNODE_CONNECTIONS,值为 8)、以及本机绑定的监听接口数量。这部分是先划走的“不可动预算”,因为它保证即使外部连接一个都没有,节点也能正常起来并维持绑定的端口。接下来,节点尝试把自己的描述符上限抬到“用户要求的连接数 + 私有广播的临时连接数 + 最低需求”这个水平;如果不使用 poll 而退回 select 实现,还会再用 FD_SETSIZE 削一次,因为 select 的集合本身有硬边界。

拿到实际可用的描述符数以后,判断分两支。如果可用数连最低需求都不够,节点直接以错误终止,日志里是那句“Not enough file descriptors available”,后面的数字把可用与所需都写清楚了。这一支不是警告,进程不会带着残缺状态启动。反之,如果最低需求能满足,节点把真正生效的连接上限设为“可用数减去最低需求”与“用户要求数”的较小值,并且只在结果小于用户要求时打那句众所周知的警告。换句话说,这句话本身不代表配置错误,它只是把系统的真实天花板报给你看。

预算清楚了,为什么机器上的天花板常常比想象中低,就要看描述符是什么。在类 Unix 系统里,一条 TCP 连接、一个打开的文件、一个监听套接字都占一个描述符,它们是同一种资源。比特币节点同时还要打开区块文件、撤销数据文件、链状态与索引数据库,这些不挂在对端计数里,却同样吃预算。所以节点要的连接数只是最终账单的一部分,操作系统给它的份额要先被这些东西瓜分完。

于是排障顺序就很清楚了。第一步别看比特币配置,先看系统给进程的额度:用 ulimit 查看软限制,或者直接看节点的启动日志里那句“Using at most N automatic connections (M file descriptors available)”——它把两个关键数字都写了出来,是这件事最权威的答案。第二步看额度是不是被启动方式吃掉了:用 systemd 托管的进程要看服务的文件描述符限制设置,容器环境要看容器的资源限制,macOS 与 Linux 的默认值也不同,同一份配置在两台机器上给出不同的连接上限是完全正常的。第三步才是比特币侧:如果你在同一个数据目录上绑了很多监听地址,或者给了大量 addnode,这些确实会从预算里先扣走。

有两条常见误判值得写明。一是把上限调得极高:节点会自动收缩,但收缩不代表问题消失,如果你的进程在别处(备份脚本、日志采集、监控代理)也占描述符,节点抢到的额度会忽多忽少,表现为连接数在运行中莫名下降。二是把警告当故障:如果收缩后的数字仍然满足你的使用需要(比如只需要十几条出站中继连接),那么这条警告可以安全忽略,真正需要处理的是“连接数低于我实际业务需要”这种情形。

还有一个隐蔽入口是私有广播。v31.0 在预算里为它留了一份独立名额(最多六十四条短连接),这部分不计入 maxconnections,但在核算最低需求时会被计入总量。如果关闭该功能,预算公式里那一项就是零,能剩下的额度反而多一点。这不代表关闭它更好,只是说明:在一个描述符紧张的小机器上,任何额外功能都可能压到连接预算上。

落到实践,一条健康检查值得写进运维清单:把启动日志里那句“available”数字与当前配置的 maxconnections 做对比,两者相等说明预算刚好被吃满、没有余量,长期在临界状态运行;有几十的富余才是舒适区。要扩大舒适区,优先动系统限制而不是比特币配置——因为比特币的那个数字从来只是请求值,真正的门是操作系统手上的。

风险提示:本文为节点运维机制说明,不涉及任何资产建议;文中行为与常量以比特币核心 v31.0 源码为准,不同版本与不同操作系统表现可能不同,请以实机日志为准。

启动日志里那句收缩连接数:文件描述符预算怎么决定节点真正的连接上限 图 2
启动日志里那句收缩连接数:文件描述符预算怎么决定节点真正的连接上限 · 图 2