SYN 队列保存未完成握手的请求,accept 队列保存已建立、等待 accept() 的连接。仅当 listen backlog 配置为 8192、somaxconn 为 4096 时,accept 侧上限为 4096。增加等待容量本身不会提高处理速率;原文全文仍暂缓、待审。

SYN backlog 保存未完成握手的请求

监听中的 TCP 套接字会区分未完成握手的请求,以及已经建立、等待应用 accept() 的连接。真正的参数名是 tcp_max_syn_backlog;本文保留历史 URL 中的拼写。它约束的是内核记住的半开请求,而传给 listen() 的 backlog 约束 accept 队列。先弄清压力发生在哪个阶段,再考虑处理办法,否则调大一个数字很可能没有解决真正的问题。 SYN cookies 是无法继续保存普通握手状态时的兜底机制。它不代表服务器不会过载、不保证报文送达,也不意味着 SYN 队列从此无需关注。即使启用了 cookies,丢包、过滤、资源分配失败和 accept 侧压力仍然可能让连接失败。判断时必须把握手状态、应用接收速度与最终业务响应分开。 SYN 队列保存未完成握手的请求,accept 队列保存已建立、等待 accept() 的连接。仅当 listen backlog 配置为 8192、somaxconn 为 4096 时,accept 侧上限为 4096。增加等待容量本身不会提高处理速率;原文全文仍暂缓、待审。 全文仍暂缓、待审;本图不为文中存疑论断背书。 backlog 参数管的是 accept 队列 Linux 从 2.2 起改变了 listen() backlog 的含义。配置值会受到 somaxconn 限制;只有当两者分别是 8192 和 4096 时,配置上限才是 4096。这是条件明确的配置例子,不是一次测量得到的精确接纳数量。应查看实际监听套接字与其网络命名空间,不能假定默认值,也不能根据短促突发中恰好成功的连接数反推严格容量。 ...

三月 24, 2028 · 1 分钟 · XB Field Notes
blue 与 green 网络范围分离、部分上下文共享;删除 blue 名称后,进程引用仍连接命名空间。

网络命名空间隔离网络资源,名称并不拥有其中所有进程

Linux 网络命名空间分离接口、路由、邻居表、套接字端口和包过滤规则等网络资源。它与其他命名空间共享内核,不是独立操作系统。进程通常继承父进程的网络命名空间,工具也可以在另一个范围中执行进程。这种隔离针对网络资源,不会自动涵盖全部进程身份和文件系统访问,因此需要按实际机制说明边界。 坏掉的样子 运行 ip netns exec 不会自动获得完整容器隔离。PID、用户身份和主机名隔离属于其他机制。应用可能看到不同路由,却仍与父环境共享普通文件和主机名。如果把一个网络命名空间当成完整沙箱,就会赋予它从未配置过的保证。应区分实际改变了哪类资源,以及哪些属性仍然来自原有运行环境。 新命名空间也不会自动得到有用的外部连接。接口需要有意放置和配置,本地回环可能需要启用。移动接口会改变管理它的命名空间,原范围不再把该设备列为自己的接口。因此,从错误范围执行配置命令,可能报告接口不存在,尽管预期设备仍位于另一个命名空间。诊断前应先确认命令的执行上下文。 名称还有独立生命周期。ip netns 按约定在 /run/netns 暴露引用,通常也能通过 /var/run/netns 访问。删除名称会移除这项引用,但进程或其他引用仍可维持命名空间存活。如果清理流程把名称列表中消失,直接等同于所有服务终止,就可能留下网络资源和运行中的进程。名称只是管理入口,不是进程所有权的完整表达。 网络范围不同,而选定上下文仍共享。删除名称后,自有进程引用仍可存活;当前运行仍待验证。 快速验证 文中结果属于历史文章报告;保留验证文件中未找到原始集成日志,本轮没有重新执行特权操作。 将脚本保存为 check-network-namespace.py,只在获准的一次性虚拟机中准备 Docker,并启用 Python 断言运行 python3 check-network-namespace.py。固定的 Python 3.11.16 与 iproute2 6.1.0 软件包仍需可取得。NET_ADMIN 与 SYS_ADMIN 是前提,不保证越过其他安全限制;不要削弱宿主保护。临时 proc 挂载支持其中的网络参数设置,不移动宿主接口,也不发布宿主端口: ...

二月 19, 2028 · 2 分钟 · XB Field Notes
IPv4 DNS 传输承载 AAAA 中的 IPv6 地址;验证服务需要另行连接。

AAAA 发布 IPv6 地址,不证明该地址可达

一条 AAAA 资源记录保存一个一百二十八位 IPv6 地址,A 记录则保存 IPv4 地址。同一个名称可以只有其中一类、同时拥有两类,或者在每类中包含多个地址。A 与 AAAA 属于不同记录集,因此可以使用不同 TTL。发布 AAAA 让地址能够通过 DNS 被发现,却不会替你创建接口、路由、监听套接字或可用应用;这些条件需要在实际服务路径上成立。 AAAA 发布的 IPv6 数据独立于 DNS 查询传输。文章实验另行验证本地 HTTP 可达性,不证明公网 IPv6 连通性或主机名 TLS。 坏掉的样子 AAAA 查询成功之后,连接仍可能失败。发布的地址可能已经停用,服务可能只监听 IPv4,网络也可能缺少可用 IPv6 路由。两种地址族的防火墙与 TLS 配置也可能不同。只通过 IPv4 做可用性检查,会漏掉这些问题,而双栈用户可能正沿着公开的 IPv6 路径遭遇延迟或错误。记录存在与服务可用是两个需要分别观察的事实。 ...

十二月 30, 2027 · 3 分钟 · XB Field Notes
文章的 Reno 例子中,空闲与一字节请求的拥塞窗口均保持10段;一 MiB 传输包含10、20、40、80段这些采样值。它们并非每个 RTT 对应一个值。

TCP 慢启动随数据确认增长,不会仅因时间流逝而翻倍

慢启动在 TCP 发送端探索路径可承受的未确认数据量时,逐步扩大拥塞窗口。数据充足且确认模式合适时,经典行为是在多个往返间近似指数增长。“每个 RTT 翻倍”是有用的简化模式,不是无条件计时器规则。窗口变化依赖传输反馈和实现的增长条件,不能只根据连接已经打开多久,就推断它获得了多少发送预算。 慢启动需要数据及合适的 ACK 反馈。文章中的 Reno 观察展示负载依赖性,并不承诺每个 RTT 翻倍,也不能证明广域网性能。 坏掉的样子 connect 之后等待,不会自动把拥塞窗口预热。应用没有发送数据时,就没有支持这种增长的数据确认。很小的交换,也可能在用满已有发送预算之前便结束。期待每个短请求都出现大幅翻倍序列,是把受应用数据量限制的传输误认成持续积压的发送端。缺少明显增长,并不自动说明慢启动没有工作或连接存在故障。 现代系统初始窗口也不统一为一到两个段。RFC 6928 描述了允许更大初始窗口的实验性扩展,本次 Linux 发送端起步为十个段。单位同样重要:Linux TCP_INFO 的 snd_cwnd 以段为单位,许多协议说明则用字节描述拥塞窗口。推算未确认数据量之前,应同时查看发送 MSS,避免将段数直接当成字节数或当前实际在途段数。 慢启动并非总要持续到第一次丢失,之后统一彻底缩回起点。慢启动阈值帮助决定启动增长与拥塞避免,具体实现还可能采用额外启动检测;重传超时恢复也不同于快速恢复。把同一条示意曲线套到所有算法、丢失信号和工作负载,即使读到了真实指标,也可能作出错误诊断。首先需要确认当前连接处于哪个阶段。 快速验证 将脚本保存为 check-slow-start.py,准备 Docker 后运行 python3 check-slow-start.py。一次性环境使用 Python 3.11.16 和 iproute2 6.1.0,在 Linux 6.12.76 上验证。NET_ADMIN 与 SYS_ADMIN 支持嵌套命名空间。客户端和目标通过新建 veth 相连,netem 在两个方向的出口各添加十毫秒延迟,全部变更仅作用于虚拟端点: ...

十二月 28, 2027 · 2 分钟 · XB Field Notes
两个命名空间边界内的 left0 与 right0 构成一对链路;右侧还拥有回环目的地址。

veth 对在两个端点之间搬运帧,路由决定这些帧承载的路径

veth 对由两个互联的虚拟以太网设备组成。从一端发送的帧到达另一端,再由接收网络栈或网桥处理。两端可以放在不同 Linux 网络命名空间,因此常用于容器网络。创建这一对设备只提供链路,地址、路由、桥接关系、转发和访问策略都需要另外配置。不能把接口已经出现,等同于完整网络已经准备好。 坏掉的样子 接口显示管理状态 UP,仍可能因为 veth 对端关闭而没有载波。只读取 UP 标志,会让尚未完成的配置看起来已经就绪。应检查两个端点,并区分管理状态与 LOWER_UP。路由也可能已经指向这个接口,但链路仍无法承载有效流量,所以路由列表本身不是连通性检查,更不能代替一次真实应用交换。 veth 对不会把 IP 载荷限制为对端接口自身地址。路由选择报文经过哪个链路,随后以太网转发或接收网络栈决定下一步处理。发往容器直接邻居之外的流量,也可以通过这一对设备到达路由器或网桥。声称“不发给对端的包都会留在本地”,混淆了链路交付与 IP 目的地选择,容易误导容器出口排障。 两端生命周期也相互关联。删除一个 veth 端点,会移除另一个端点,即使对端由另一个命名空间管理。因此宿主侧清理动作可能删除容器接口。影响活跃工作负载时,应有意识地安排停止流量、调整路由和删除设备的顺序。命名空间分离了管理视图,却没有让成对设备变成两项互不影响的资源。 veth:跨命名空间设备对:概念机制与预期检查,不是新增运行证据。 快速验证 将脚本保存为 check-veth.py,仅在已获授权的一次性 Linux 实验环境中,使用核实为本地的 Docker daemon,并保留 Python 断言。配方注明 Python 3.11.16、iproute2 6.1.0,但镜像架构、包与宿主内核仍需核对。NET_ADMIN、SYS_ADMIN 无法覆盖强制策略的挂载拒绝,Docker 默认 AppArmor 配置即存在此限制。应使用兼容且获批的实验环境,不应为运行示例削弱宿主保护。嵌套命名空间与 proc 挂载需要实际内核权限,运行时隔离不代表拉取镜像和构建离线;清理命令仅尝试执行,未全部核对退出码。 ...

十一月 21, 2027 · 2 分钟 · XB Field Notes
外层 IPv4 内依次包含 UDP 4789、VXLAN VNI 42、内层以太网,以及内层 IP 与 HTTP。

VXLAN 既需要底层可达,也需要两端隧道参数一致

VXLAN 把以太网帧装进 UDP 数据包,使覆盖网络能够跨越底层 IP 网络。隧道端点负责封装与解封装,二十四位 VXLAN 网络标识符 VNI 用来标识虚拟网段。外层 IP 地址负责端点之间的选路,内层以太网与 IP 地址服务于覆盖网络。这是具有不同配置和可达性条件的两个层次,不能用其中一层的成功替另一层作结论。 坏掉的样子 能够 ping 通隧道端点,无法充分证明特定覆盖网段正常。两端地址可能均可达,却使用不同 VNI、UDP 目的端口或远端节点配置。底层防火墙也可能允许 ICMP,却丢弃封装后的 UDP。排查应针对真正的传输协议和虚拟网段,不能因为底层一次 ping 成功,就认为其上所有租户流量都已验证通过。 封装占用底层包容量。无内层 VLAN 标签、采用普通外层 IPv4 时,覆盖 IP MTU 一千四百五十可放入底层 IP MTU 一千五百:内层以太网十四、VXLAN 八、UDP 八、IPv4 二十字节。内层 VLAN 标签、外层 IPv6 或额外封装会改变这个 IP 预算;外层以太网 VLAN 标签影响的是链路帧大小。RFC 7348 禁止 VTEP 主动分片,并允许目的端丢弃分片。小请求成功不能验证路径 MTU 或大包。 ...

十月 28, 2027 · 3 分钟 · XB Field Notes
已建立连接在 accept 队列等待;accept() 箭头将连接移到已接受套接字区域,套接字仍可保持打开。

listen backlog 保存等待 accept 的连接

对于 Linux TCP 套接字,listen() 的 backlog 关注已经建立、等待应用接受的连接;未完成握手的队列是另一种概念。调用 accept() 会移出一条待处理连接,并返回供应用使用的已连接套接字。即使这个套接字之后长时间保持打开或忙碌,它也不再占用监听器的 accept 队列。因此,等待接受与已经接受后的活动状态需要分别计数。 backlog 限定等待空间。accept() 释放队列位置,返回的已连接套接字仍可保持活动。 坏掉的样子 如果连接到达速度超过应用接受速度,待处理队列会填满。根据内核行为和设置,新客户端可能遇到重传延迟或超时,而已经接受的请求仍可能正常。进程活着,或者部分请求成功,都不能证明监听器正足够快地接受新连接。问题发生在接受之前时,仅查看业务处理成功率可能看不到完整失败路径。 请求的 backlog 还受到 net.core.somaxconn 限制;只把应用值调得更大,不能超过这个上限。但可观察的精确队列边界与实现有关,因此不能把整数直接当成跨平台承诺,认为必定恰好有那么多同时 connect 成功。应测量实际部署内核,而不是把一个很小的实验结果推广成通用的加一或减一规则。 队列计数也需要上下文。ListenOverflows 和 ListenDrops 是网络命名空间计数,不会自动解释到某个具体服务。其他监听器也能贡献计数,客户端超时也可能来自 accept 队列之外。将生产失败归因于某个 backlog 设置,或者宣称扩大队列能修复问题之前,应结合队列占用、接受进度和计数共同判断。 快速验证 本轮复核没有重跑 Docker 套接字实验,内核参数与溢出结果仍属于此前记录。 把脚本保存为 check-listen-backlog.py,准备宿主 Python、Docker 和固定 Python 镜像后运行。真实套接字操作发生在可丢弃 Linux 容器内,网络只保留回环。记录内核为 6.12.76-linuxkit。只在另行获得授权的可丢弃虚拟机中准备镜像并保持断言开启。脚本读取设置,要求 tcp_abort_on_overflow=0;前提不符时应停止,不要为了复现实验而修改宿主配置。这个条件限定历史超时观察的适用范围: ...

十月 25, 2027 · 2 分钟 · XB Field Notes
1448 字节 IPv6 报文遇到 MTU 1280 的链路。转发路由器丢弃报文并向源端报告 Packet Too Big,不会替过境报文分片。

IPv6 路由器报告超大报文,由源端决定怎样适应路径

IPv6 路由器在向目的地转发报文时,不会替它进行分片。如果报文大于下一条链路所能承载的大小,路由器通常丢弃它,并发送 ICMPv6 Packet Too Big 反馈。源端随后可以调整报文大小,或在适当情况下通过 IPv6 分片扩展头发送分片;这些分片在目的端重组。明确各阶段由谁负责,是判断超大报文故障的基础。 坏掉的样子 假定路由器会自动拆开过大的 IPv6 包,会掩盖与大小相关的故障。相同地址与路由上,小 echo 可以成功,大 echo 却失败。端点本地接口可能支持原始大小,中间链路却不支持。应检查整条路径约束,不能仅因接口配置了 MTU 1500,就推断该大小能够端到端通过,也不能用一次小探测成功替代完整大小检查。 Packet Too Big 反馈缺失,会使经典发现更难学到这个限制。分片被过滤,或者其中一片丢失,也可能阻止正确重组。能够生成分片扩展头,不证明沿途策略都允许相应报文。不能把源端分片当作正确路径大小与必要控制流量的万能替代,它有自己的交付条件,需要通过对应流量验证,而不是只检查发送选项已经开启。 反方向也有自己的路径估计。请求发送端学到 MTU,不会自动教会响应端怎样发送较大回复。因此双向 echo 测试需要分别了解两个方向。TCP 分段还不同于 IP 分片:TCP 发送端学到限制后,可以构造更小的段,而不必把每个 IP 包再分片。应先确定观察的是哪一层的切分,避免看到多个包就统称为分片。 路由器不会对转发的 IPv6 流量分片。源端分片、目的端重组与学习路径上限属于不同阶段。报文和开口形状为示意,未按字节比例绘制。网络示例执行仍受阻,本次未重跑。 快速验证 历史报告使用 Linux 6.12.76、Python 3.11.16、iproute2 6.1.0 与 tcpdump 4.99.3;本轮没有重跑。脚本名为 check-ipv6-fragmentation.py,只应留给另外获得授权的可丢弃 Linux 虚拟机实验。容器共享该虚拟机的内核,NET_ADMIN、SYS_ADMIN 与 proc 挂载需要比生产容器更明确的隔离边界。之后运行时的 --network none 不会阻止镜像构建下载软件包。保持断言开启,不要为通过设置而放宽宿主安全策略。新建 veth、地址与路由仅应存在于实验内部: ...

十月 6, 2027 · 3 分钟 · XB Field Notes