-
我的服务平时稳如老狗,可每次大促整点开闸流量一瞬间涌进来就有一批用户连接直接超时连不上、而服务端应用日志干干净净没有任何报错 CPU 内存也都没满,我盯着监控百思不得其解,最后才挖出来是 TCP 三次握手完成后那个全连接 accept 队列被挤满了、新完成握手的连接被内核静默丢弃了的深度复盘
我有个接口平时 QPS 不高服务稳得很,可每次运营搞活动整点开闸的那一瞬间,大量用户几乎同一秒涌进来,就有一批人连不上——页面打不开、一直转圈最后超时、刷新几次又好了。我上去看监控越看越糊涂:连不上的请求在我的应用日志里根本没有任何记录、就像从没到达过应用,CPU 内存也就五六成远没满,下游 DB 全绿,客户端报的是 connect timeout 连接阶段就超时了、有的显示 SYN 重传几次放弃…- 4
- 0
-
我把一个大文件从国内服务器传到海外节点、两边带宽都是千兆、可实际传输速度死活只有几 MB 每秒慢得令人发指,我换了更快的机器查了磁盘网卡都没问题,最后才搞懂瓶颈根本不在带宽而在这条高延迟链路上 TCP 窗口太小根本填不满这根又粗又长的管道的深度复盘
我要把一个几十 GB 大文件从国内机房传到海外节点,两端网卡和出口带宽都是千兆,满以为几分钟传完,结果速度稳稳卡在几 MB/s、几十 GB 要好几小时。我换更高配机器没用、测磁盘读写飞快、本地内网能跑满千兆,可这条跨国链路单连接就是只能几 MB/s。直到注意到这条链路 RTT 高达两三百毫秒(绕半个地球)才明白:TCP 是发一批数据等对方确认再发下一批,任意时刻已发出但还没收到确认的数据量受窗口大…- 0
- 0
-
我的服务跑着跑着就再也接受不了新连接、报 too many open files,我一查发现成百上千条连接全卡在 CLOSE_WAIT 状态死活不消失,一开始以为是对端没规矩不关连接,最后才搞明白 CLOSE_WAIT 恰恰是对端已经关了、正等着我这边关而我的代码根本就忘了调 close 的深度复盘
我的服务对外提供接口、也作为客户端调下游,运行一段时间后开始变诡异:先偶尔报错,后来直接无法接受任何新连接、日志满屏 too many open files——文件描述符耗尽了,重启能暂时恢复但过一阵又复发,典型的资源泄漏。我用 netstat grep CLOSE_WAIT 一统计倒吸凉气:成百上千条连接处于 CLOSE_WAIT 状态且只增不减。我第一反应是对端怎么用完连接不关,可去查对端它那…- 0
- 0
-
我用一个长连接连着下游服务,平时好好的,可只要一段时间没有数据来往、再发请求就超时失败,两边的连接看着都还在、谁也没断开,排查半天才发现是中间的网络设备早把这个空闲连接悄悄掐了、而两端都被蒙在鼓里的深度复盘
我有个服务用一个长连接连着下游,想复用连接省去反复建连。请求频繁时一切正常,可问题出在空闲之后:只要连接一段时间没数据来往,下次再用它发请求就卡住然后超时;诡异的是连接两端看着都还活着——我这边状态正常、下游也没主动关闭。第一次失败后重建又能用,空闲又失败如此反复。我以为下游不稳定,查半天下游正常。直到抓包又了解链路才恍然:我和下游间隔着 NAT 网关/防火墙/负载均衡这类有状态中间设备,它们为每…- 2
- 0
-
我的服务传输大量数据,带宽明明很充足、网络也不差,可吞吐量就是上不去、尤其每次新建连接的前期慢得明显,排查半天才发现 TCP 有个慢启动机制、新连接的发送窗口是从很小一点点试探着爬上来的深度复盘
我有个服务要在节点间传输大量数据,观察到怪现象:带宽明明充足、延迟也不高,可实际吞吐就是上不去、达不到带宽理论值,尤其每次新建连接前期都慢得肉眼可见、过一会儿才提上速,而我的模式恰恰是频繁建新连接传一小批就关,于是每条连接几乎都在慢吞吞的前期就结束了。我以为是带宽不够、对端慢、缓冲小,排查都不对。直到抓包盯着一条新连接的发送速率曲线:刚建立时速率非常低、然后指数往上爬、爬好一阵才接近带宽上限。查 …- 0
- 0
-
我的服务调用下游一切正常,可一到高峰期就大量报连接失败、报错说没有可用端口了,我的机器明明负载不高、内存也充足,排查半天发现是几万个处于 TIME_WAIT 状态的连接把本地端口耗光了的深度复盘
我有个服务要频繁调用一个下游接口,写法很干净:每次调用都新建连接、发请求、拿响应、然后立刻关掉,用完即走。平时跑得好好的。可一到流量高峰就灾难了:服务大量报 Cannot assign requested address(没有可用端口),新的下游建连接连失败。我以为机器扛不住了,可一看监控傻眼:CPU 不高、内存充足、下游也好好的,机器很闲,凭什么连接就建不出来?直到我 netstat 统计连接状…- 0
- 0
-
我的服务用连接池复用长连接调下游,平时好好的,却总在低峰期之后偶发 connection reset,排查发现是连接被对端的空闲超时悄悄关了、我的连接池却还留着这条已死的连接照样拿来用的深度复盘
我的服务用连接池复用到下游的长连接(避免每次新建,这是对的)。平时高峰期一切正常,可总在低峰期之后(凌晨流量小或一段时间没请求后)出怪事:之后的第一批请求偶发失败、报 Connection reset by peer 或 Broken pipe,而重试一下又成功了。复盘才搞懂:连接池为复用会把用完的长连接留着、放回池里下次直接用;可一条连接空闲太久,对端(下游服务、或中间的 LB/NAT/防火墙)…- 4
- 0
-
我那个请求-响应的小包通信,延迟总是莫名其妙地多出 40 毫秒,抓包才发现是 Nagle 算法和延迟确认这两个好心的优化打起来了:一次 TCP 小包延迟的深度复盘
我有个请求-响应式的小包通信,逻辑上应该很快,可监控显示延迟经常莫名多出约 40 毫秒,而服务端处理只要零点几毫秒。代码翻烂了也没找到哪里慢,最后 tcpdump 抓包看时间戳才明白:这 40ms 不在我的代码里,而消耗在 TCP 协议栈里两个各自合理的优化的相互作用上——发送端的 Nagle 算法(有未 ACK 数据时攒着不发新小包、等 ACK)和接收端的延迟确认(收到数据先不回 ACK、等回程…- 2
- 0
-
一个调用下游接口后忘了关闭连接的服务,在下游主动断开后留下了一大堆 CLOSE_WAIT,把文件描述符耗尽、再也建不了新连接:一次 CLOSE_WAIT 堆积的深度复盘
服务跑一段时间后大量报 too many open files、建不了新连接,netstat 一看成千上万个 CLOSE_WAIT 只增不减、把 fd 耗尽。根因是调下游接口后没正确 Close 响应体/连接:下游处理完主动关闭它那端发来 FIN,我方收到后进入 CLOSE_WAIT(等我方 close),而代码没 close(异常路径漏关、忘了 defer),连接就永远停在 CLOSE_WAIT…- 2
- 0
-
一个以为发一次就收一次的 TCP 通信程序,在高频发送时把多条消息粘成了一坨、又把一条拆成了两半:一次 TCP 粘包拆包的深度复盘
基于 TCP 自研的设备协议,平时好好的,一到高频上报服务端就疯狂报 JSON 解析失败——有时一次收到两三条消息粘在一起、有时只收到半条。抓包看设备发得一条是一条,根因是把 TCP 当成了消息流:TCP 是面向字节流的,只保证字节有序可靠到达、不维护消息边界,会为效率合并小包或按 MSS 拆大包,send 与 recv 次数根本不对应,而协议里没有任何消息边界设计。本文讲透 TCP 为何必然粘包…- 0
- 0
-
我基于 TCP 写了个通信协议,客户端连发两条消息,服务端一次读出来却粘成了一坨,有时一条消息又被拆成两次才收全,我对着 TCP 是字节流没有消息边界这个粘包拆包的坑排查大半天的复盘
一个让我对 TCP 到底传的是什么彻底搞明白的网络坑,它让我意识到我一直以为的我 send 一条消息对方就 recv 到一条消息这个朴素直觉在 TCP 根本不成立,发和收之间根本没有消息这个概念。自己基于 TCP socket 写通信协议,客户端 conn.Write(hello) 再 Write(world),服务端一次 Read 却读到了 helloworld 两条粘在一起(粘包),有时一条消…- 0
- 0
-
我的服务跑着跑着就再也连不上下游了,报 too many open files,netstat 一看几千个 CLOSE_WAIT 堆在那,我对着忘记关闭 HTTP 响应体导致连接泄漏这个坑排查大半天的复盘
一个让我对关闭资源彻底敬畏的网络坑,可怕在它是缓慢累积定时爆发的雷:服务刚启动一切正常,运行几小时甚至几天后突然像被掐住喉咙,再也无法建立任何新连接、整个服务瘫痪。需求很常见:服务频繁调下游 HTTP 接口拿数据,我用 Go 写了个调用函数 resp,err := http.Get(url),用完却忘了 resp.Body.Close()。测试和刚上线跑得好好的,运行一段后告警:dial tcp …- 0
- 0
-
我的服务从连接池取到的长连接其实早就"死"了、发请求全卡到超时,可连接池却以为它还活着,我对着连接假死和心跳保活排查了大半天的复盘
做了个调下游 RPC 的服务,用长连接+连接池复用,平时正常,可每当下游重启、或中间防火墙/LB 抖动后,就冒出一批诡异超时:从连接池取到的某些连接一发请求就卡到超时,连接池却一直认为它们可用、反复借出。盯着监控百思不得其解:连接不是好好在池里吗怎么用起来是死的?排查大半天才理解 TCP 长连接的隐蔽陷阱——连接假死:TCP 连接是虚拟约定,不发数据时网络无信号确认对端在;异常断开(对端宕机没发F…- 0
- 0
-
我的服务高峰期突然报 Cannot assign requested address,明明机器很闲、连接也没泄漏,我对着几万个 TIME_WAIT 排查了大半天的复盘
那天高峰期,我们一个对外服务突然大面积报 connect: cannot assign requested address(errno 99),最迷惑的是机器 CPU、内存全闲着,连接池也没泄漏,可就是建立不了新连接。我从应用层一路查到内核 TCP 状态,直到 netstat 里看到密密麻麻几万个 TIME_WAIT 才恍然大悟:我们这服务作为客户端高并发地用短连接调下游,每次用完主动关闭就进入 …- 0
- 0
-
我的服务调外部接口一到高峰就报"cannot assign requested address"、机器上堆了几万个 TIME_WAIT 连接,我盯着 netstat 排查了大半天才发现连接根本没复用
我的服务频繁调外部 HTTP 接口,一到高峰就大面积报错 cannot assign requested address、延迟还变高。netstat 一看惊呆:机器上堆了几万个 TIME_WAIT。深挖才懂:我每次请求都新建一个 TCP 连接、用完就关、从不复用——后果一是每次都白付三次握手(HTTPS 还有 TLS 握手)的延迟;后果二更致命,主动关闭的连接进入 TIME_WAIT 要停留约 2…- 4
- 0
-
我想当然地以为 TCP 发一次就能收一次,结果客户端发来的消息要么粘成一坨、要么被截成两半,我对着错乱的数据排查了好几天才搞懂粘包半包的深度复盘
我做长连接服务,用 TCP 传自定义消息,设计得"很自然":客户端 send 一条,服务端 recv 一条。本地小数据量一切正常,可一旦快速连续发、或消息体一大,服务端就疯狂解析失败:有时一次 recv 收到几条粘在一起的消息({"a":1}{"b":2}{"c":3}),有时一条消息被截成两半。翻了 TCP 原理才懂…- 0
- 0
-
服务跑着跑着就报"cannot assign requested address",我以为是端口配置错了,真相却是几万个 TIME_WAIT 把端口耗光了的复盘
一个高频调用下游 HTTP 接口的服务,跑一段时间后开始报 dial tcp: cannot assign requested address。我以为是端口配置错,直到 netstat 一统计——近三万个 TIME_WAIT!根因是我为每个请求都新建 TCP 连接、用完就关,主动关闭方的连接进入 TIME_WAIT 停留 60 秒,每秒几百个累积起来,把本机约 2.8 万个临时端口占光了。这篇从 …- 0
- 0
-
我发了两条消息,服务端却收成了一条半:第一次手写 TCP 通信被粘包拆包教做人,才真正理解 TCP 是字节流而非一条条的消息流
第一次抛开 HTTP 框架、用裸 TCP socket 写通信:客户端分两次 send("HELLO")、send("WORLD"),服务端却时而收成粘在一起的 "HELLOWORLD",时而把一条劈成两半。根因是我把 TCP 当成了消息流——可它是字节流,send 之间的边界一进流就消失了。这篇从字节流原理讲到长度前缀/分隔符分帧、re…- 3
- 0
-
端口被 TIME_WAIT 占满:TCP 短连接避坑复盘
这次事故的报错信息第一眼看上去毫无道理:我们一个服务在流量高峰期偶发性地报一个奇怪的错误 Cannot assign requested address 无法分配请求的地址。我盯着这行错误懵了好一会儿:分配地址?我又没在创建什么地址,我只是在调用一个下游的 HTTP 接口而已啊,而且这个错误只在高峰期出现,服务器的 CPU 内存带宽也都不紧张,一个资源充裕的服务器却报无法分配地址,这到底是什么玄学…- 0
- 0
-
偶发 connection reset:连接池复用死连接避坑
有个服务调用下游接口平时好好的,可总会偶发地毫无规律报一个错:Connection reset by peer——连接被对端重置了,频率不高几百次请求一两次、重试又能成功,起初没太当回事,可流量增长后积累的失败量越来越扎眼。这个错最磨人的就是随机性:同样的代码同样的接口绝大多数都好好的偏偏隔一阵冒一个失败。抓了好久包对了好久日志才慢慢拼出真相,藏在一个我从没留意的细节里:这些失败几乎都发生在一段时…- 7
- 0
-
下游没挂自己先崩:TCP 连接 TIME_WAIT 端口耗尽避坑
一个调用下游接口的服务,平时风平浪静,流量一冲高就大面积抽风:日志刷屏般地报 connection refused,更多的是一句陌生的 cannot assign requested address,可被调用的下游监控却一切正常、根本没挂。我顺着"下游扛不住"查了半天一无所获,直到在本机敲下 ss -s,数字一出来就全明白了——几万个连接密密麻麻堆在 TIME_WAIT,本机用…- 7
- 0
-
三万个 CLOSE_WAIT 压垮服务:看懂 TCP 连接状态机
一个风平浪静的上午,核心服务突然刷出满屏 too many open files,接口大面积超时。调大 ulimit 只撑了十几分钟,一条 netstat 揭开真相:三万八千个 CLOSE_WAIT 死死占着句柄只增不减。从这次句柄耗尽事故出发,这篇文章把 TCP 四次挥手状态机、CLOSE_WAIT 与 TIME_WAIT 的本质区别、连接泄漏的定位与修复、长连接复用、超时设置到优雅关闭,一次讲…- 0
- 0
-
TCP 连接的生与死:从一次端口耗尽彻底搞懂 TIME_WAIT
一个调用量很大的网关服务某天开始零星报 connect: cannot assign requested address,下游好好的,网络也通,ss -s 一看竟有六万多个 TIME_WAIT 把本地端口占了个精光。很多人第一反应是把 TIME_WAIT 当 bug 干掉,我差点就去开那个臭名昭著的 tcp_tw_recycle。这篇从端口耗尽讲起,把 TCP 连接怎么生(三次握手为什么是三次)、…- 0
- 0
-
偶发 502 故障复盘:keep-alive 超时不匹配、缺超时、重试风暴与连接池治理
一套日常 QPS 三四千的微服务系统,网关到订单服务这一跳每隔一阵就冒出大约千分之三的 502,监控曲线上是几个对不上流量高峰也对不上发布的孤立尖刺,客户投诉「点一次失败再点一次就好」,而后端订单服务的业务日志却干干净净——请求根本没进到业务逻辑,就在网络层被掐断了。这篇把这次「查无此错」的偶发故障从头复盘:一开始误判为上游 OOM 重启、白白扩容浪费了四十分钟,直到用 ss 看连接状态、tcpd…- 0
- 0
TCP
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!
























