我的服务高峰期突然报 Cannot assign requested address,明明机器很闲、连接也没泄漏,我对着几万个 TIME_WAIT 排查了大半天的复盘

那天高峰期,我们一个对外服务突然大面积报 connect: cannot assign requested address(errno 99),最迷惑的是机器 CPU、内存全闲着,连接池也没泄漏,可就是建立不了新连接。我从应用层一路查到内核 TCP 状态,直到 netstat 里看到密密麻麻几万个 TIME_WAIT 才恍然大悟:我们这服务作为客户端高并发地用短连接调下游,每次用完主动关闭就进入 TIME_WAIT、占用源端口约 60 秒,高峰期堆积近三万个,把本地可用端口范围(约两万八千个)占光,内核分配不出新源端口,于是报"分配不出地址"。这篇从 TCP 四次挥手与 TIME_WAIT 的存在意义(确保末个ACK送达、让旧包消亡)、连接复用根治(长连接+连接池/Session/keep-alive)与内核参数辅助(tcp_tw_reuse 可开、tcp_tw_recycle 绝不开)的正解、TIME_WAIT 与 CLOSE_WAIT 的本质区别(主动关太频繁 vs 该关没关的代码BUG)、TCP连接状态速查、长短连接选型、netstat 排查路径与几条铁律,到附上一段短连接 vs 复用 Session 的对比代码。核心领悟:端口/fd 这些"隐形资源"也会被耗尽、同一写法小流量没事高并发可能致命,写代码要装着量级思维,排查网络先 netstat 看状态分布。

我的服务高峰期突然报 Cannot assign requested address,明明端口没占满、连接也没泄漏,我对着一堆 TIME_WAIT 排查了大半天的复盘

那天下午,我们的一个对外服务在流量高峰时,突然开始大面积报错。日志里刷的全是一行我当时根本没在意、后来却刻骨铭心的报错:connect: cannot assign requested address。最让我懵的是:这台机器内存、CPU 都很闲,我们的连接池也没泄漏(连接数稳定),端口范围看起来也够用,可它就是建立不了新连接了。我对着这个"分配不出地址"的诡异报错,从应用层一路查到内核的 TCP 状态,排查了大半天,最后在 netstat 里看到密密麻麻几万个 TIME_WAIT 时,才终于明白过来。这篇就把这场"TIME_WAIT 耗尽端口"的事故,从头到尾复盘一遍。

故障现场:闲着的机器,却连不出去

先看一眼当时的现场。应用报错、机器很闲,但 TIME_WAIT 多到离谱:

# 1. 应用日志: 高峰期大量这个错(尤其是作为客户端去调下游时)
java.net.BindException: Cannot assign requested address
# 或 Python: OSError: [Errno 99] Cannot assign requested address
# 或 curl: bind failed with errno 99: Cannot assign requested address

# 2. 机器本身很闲: CPU/内存都没满
$ top    # load 不高, 内存充足

# 3. 但是 —— 统计 TCP 连接状态, TIME_WAIT 多到爆炸:
$ netstat -ant | awk '{print $6}' | sort | uniq -c | sort -rn
  28473 TIME_WAIT      # ← 两万八千个! 就是它
    312 ESTABLISHED
     45 LISTEN
      8 SYN_SENT

# 4. 可用的本地端口范围(客户端发起连接时从这里随机选源端口):
$ cat /proc/sys/net/ipv4/ip_local_port_range
32768   60999            # 也就 ~28000 个可用端口

# 现象拼图:
#   - 我们这服务作为"客户端", 高并发地去调下游 (短连接、每次新建)
#   - 每次连接用完关闭, 主动关闭方会进入 TIME_WAIT, 持续 2*MSL (默认 60s)
#   - TIME_WAIT 期间, 那个 (源IP,源端口,目标IP,目标端口) 四元组被占着
#   - 高峰期新建连接太快, TIME_WAIT 堆积 ~28000, 把 ~28000 个可用源端口占光
#   - → 内核分配不出新的源端口 → Cannot assign requested address

看到那两万八千个 TIME_WAIT,再对照可用端口范围只有约两万八千个,我瞬间明白了:不是端口"被别的进程占了",而是被我自己刚关闭的、还处在 TIME_WAIT 状态的连接占着。这个 Cannot assign requested address(errno 99 / EADDRNOTAVAIL),本质是内核作为客户端去 connect 时,要从本地端口范围里挑一个空闲源端口,但所有端口都被 TIME_WAIT 的连接占用了,挑不出来

第一件事:搞懂 TIME_WAIT 是什么、为什么存在

要解决它,得先搞懂 TIME_WAIT 到底是个什么状态,以及它为什么必须存在。

TCP 四次挥手与 TIME_WAIT

主动关闭方                      被动关闭方
   |------- FIN ------------->|   (我要关了)
   |<------ ACK --------------|
   |<------ FIN --------------|   (我也关了)
   |------- ACK ------------->|
   |                          |
[进入 TIME_WAIT]           [进入 CLOSED]
 等待 2*MSL (Linux 默认 60s)
 然后才 CLOSED

# 关键: "主动关闭连接的一方"(先发 FIN 的) 才会进入 TIME_WAIT。
# 谁主动关, 谁 TIME_WAIT。

# 为什么要有 TIME_WAIT (它不是 bug, 是必要设计):
#   1. 确保最后那个 ACK 能到达对方。
#      若 ACK 丢了, 对方会重发 FIN; 我还在 TIME_WAIT 就能重发 ACK。
#      若立刻 CLOSED, 对方重发的 FIN 来了, 我只能回 RST(对方报错)。
#
#   2. 让本次连接的"迷途旧包"在网络中自然消亡。
#      等 2*MSL(报文最大生存时间的两倍), 确保旧连接的延迟包都死透了,
#      避免它们被"复用了相同四元组的新连接"误收, 造成数据错乱。

# 所以 TIME_WAIT 是为了"可靠地关闭"和"防止旧包串扰"。
# 它的代价: 主动关闭方要占用这个四元组(尤其是源端口) 约 60s。

原来 TIME_WAIT 不是什么异常,而是 TCP 为了"优雅可靠地关闭连接"而精心设计的状态。它的核心规则是:谁主动关闭连接(先发 FIN),谁就进入 TIME_WAIT,并停留约 2*MSL(Linux 默认 60 秒)它存在的两个理由都很硬核:一是确保四次挥手最后那个 ACK 可靠送达(万一丢了,对方重发 FIN,我还能补发 ACK);二是让本次连接遗留在网络里的"迷途旧包"彻底消亡(避免它们窜到复用了相同四元组的新连接里造成数据错乱)。但它有代价:主动关闭方,要把这个四元组(关键是源端口)占用约 60 秒而我的服务,正是那个"高并发、主动关闭大量短连接"的一方——于是 TIME_WAIT 像雪花一样越积越多,最终占光了所有源端口。问题的根源,不是 TIME_WAIT 本身有错,而是我用错了连接的方式——拿短连接去扛高并发

第二件事:正解——根治靠连接复用,而非调内核参数

搞懂了原理,正解的优先级就清晰了:首选"连接复用"从根上消灭海量短连接;内核参数(tcp_tw_reuse 等)是辅助,绝不是首选

# ====== 正解一(根治, 首选): 连接复用, 别用短连接扛高并发 ======
# 问题的根: 每次请求都新建连接、用完关闭 → 海量主动关闭 → 海量 TIME_WAIT。
# 解法: 用"长连接 + 连接池", 复用连接, 不要频繁新建/关闭。

#  HTTP 客户端: 开启 keep-alive + 连接池 (复用 TCP 连接)
#    - Java HttpClient / OkHttp: 默认连接池, 确认 keep-alive 生效
#    - Python requests: 用 requests.Session() (而不是每次 requests.get)
#    - Go: 复用 http.Client(默认有连接池), 别每次 new; 记得读完 Body 并 Close

#  数据库/Redis: 一定用连接池(HikariCP / redis pool), 别每次新建连接

#  RPC: gRPC 等本就是长连接多路复用, 用好它

# 复用后: 连接建好就一直用, 几乎不再频繁关闭 → TIME_WAIT 锐减。

# ====== 正解二(辅助): 让"被动关闭方"承担关闭, 把 TIME_WAIT 转移走 ======
# 谁主动关谁 TIME_WAIT。若能让"对端"主动关闭(如让下游/服务端关),
#   TIME_WAIT 就堆在对端而非自己这台高并发客户端上。(需双方协商, 不总可行)

# ====== 正解三(辅助/谨慎): 内核参数调优 ======
$ sysctl net.ipv4.tcp_tw_reuse=1
#   允许"作为客户端"复用处于 TIME_WAIT 的端口去建新连接(需配合 tcp_timestamps)。
#   ✓ 这是对客户端侧最有效的安全开关。

$ sysctl net.ipv4.ip_local_port_range="1024 65000"
#   扩大本地端口范围, 缓解(治标), 让能撑的连接数多一些。

$ sysctl net.ipv4.tcp_max_tw_buckets=20000
#   限制 TIME_WAIT 总数上限(超了直接清理, 治标且有风险)。

# ⚠️ 千万别开 net.ipv4.tcp_tw_recycle !
#   它在 NAT 环境下会丢弃乱序时间戳的包, 导致诡异的连接失败,
#   高版本内核(4.12+)已直接移除。别用!

# ====== 核心 ======
# 根治 = 连接复用(长连接+连接池)消灭海量短连接;
# tcp_tw_reuse=1 是有效辅助; 扩端口范围是治标; 永远别开 tcp_tw_recycle。

修复的核心思路,是"从根上不要制造那么多 TIME_WAIT",而不是"想办法容纳更多 TIME_WAIT"。正解一(根治、首选):连接复用。问题的根,是"每次请求都新建连接、用完就关"——所以解法就是用长连接 + 连接池复用连接:HTTP 开 keep-alive(Python 用 requests.Session() 而非每次 requests.get、Go 复用 http.Client 并记得读完 BodyClose);数据库/Redis 用连接池;RPC 用 gRPC 这种长连接多路复用。复用后连接建好就一直用,几乎不再频繁关闭,TIME_WAIT 锐减。正解二(辅助):把关闭转移给被动方——谁主动关谁 TIME_WAIT,若能让对端主动关,TIME_WAIT 就堆在对端而非自己。正解三(辅助、谨慎):内核参数——tcp_tw_reuse=1 是对客户端侧最有效的安全开关、扩大端口范围是治标。而最大的一个坑提醒:千万别开 tcp_tw_recycle——它在 NAT 环境下会丢包导致诡异连接失败,高版本内核已直接移除。归根结底:根治靠连接复用消灭海量短连接;tcp_tw_reuse 是有效辅助;扩端口是治标;永远别碰 tcp_tw_recycle

第三件事:TIME_WAIT 与它的"反面"CLOSE_WAIT

排查时我还顺带搞清了一个常被混淆的状态:CLOSE_WAIT。它和 TIME_WAIT 听着像,成因和处理却截然相反。

TIME_WAIT vs CLOSE_WAIT —— 别搞混

# TIME_WAIT (出现在"主动关闭方")
#   - 正常状态! 主动关连接的一方在四次挥手后等 60s。
#   - 大量 TIME_WAIT = 你在高并发地"主动关"很多短连接(本文场景)。
#   - 会自己消失(60s 后), 危害是占源端口。
#   - 解法: 连接复用、tcp_tw_reuse。

# CLOSE_WAIT (出现在"被动关闭方")
#   - 危险信号! 对方已发 FIN(要关), 我收到了, 但我的程序
#     "迟迟没有调用 close()" → 卡在 CLOSE_WAIT, 不会自己消失。
#   - 大量 CLOSE_WAIT = 你的代码有 BUG: 连接对方关了, 你没关。
#     (常见: 没在 finally 里 close、异常路径漏 close、连接池配置错)
#   - 不会自动消失, 会一直堆积直到耗尽文件描述符(fd)。
#   - 解法: 改代码! 确保每个连接最终都被 close(用 try-with-resources /
#     with / defer Close)。

# 一句话区分:
#   TIME_WAIT 多 → 你"主动关"得太频繁(架构/用法问题, 可调优)。
#   CLOSE_WAIT 多 → 你"该关没关"(代码 BUG, 必须改码)。

这一对状态的对比,帮我彻底理清了 TCP 连接关闭的两面。TIME_WAIT 出现在主动关闭方,是正常状态(会在 60s 后自己消失),大量出现说明你在高并发地主动关短连接(本文场景),解法是连接复用。CLOSE_WAIT 出现在被动关闭方,是危险信号:对方已发 FIN 要关、你收到了,但你的程序迟迟没调 close(),于是卡在 CLOSE_WAIT不会自己消失,一直堆积到耗尽文件描述符。它俩的根因和解法截然不同:TIME_WAIT 多是"主动关得太频繁"(架构/用法问题,可调优);CLOSE_WAIT 多是"该关没关"(代码 BUG,必须改码——确保每个连接都被 close,用 try-with-resources / with / defer Close)搞混这两个,排查方向就会完全跑偏。下面这张图,是这次 TIME_WAIT 耗尽端口的成因与解法:

第四件事:TCP 连接状态速查

这次踩坑逼我把 TCP 的几个关键连接状态认认真真梳理了一遍,排查网络问题时对照着看,事半功倍。

状态 含义 大量出现意味着 会自己消失吗
ESTABLISHED 连接已建立、正常通信中 正常(活跃连接多) 用完关闭后转走
TIME_WAIT 主动关闭方,挥手后等 2*MSL 你高并发主动关短连接 会(约 60s)
CLOSE_WAIT 被动关闭方,收到FIN但没close 代码 BUG:该关没关 不会(必须改码)
SYN_SENT 已发SYN,等对方回应 连不上对方/对方慢 超时后
SYN_RECV 收到SYN,半连接 可能 SYN Flood 攻击 超时后
FIN_WAIT_1/2 主动关闭过程的中间态 对方没及时回ACK/FIN 会(超时)
LAST_ACK 被动关闭方发完FIN等ACK 正常关闭中间态

这张表,把 TCP 连接的"生老病死"摊开了看。排查时最该盯的两个"病态"是:TIME_WAIT 巨多(你主动关得太频繁,本文场景,可调优)和 CLOSE_WAIT 巨多(你该关没关,是代码 BUG,必须改码)其余的:SYN_SENT 多说明连不上对方;SYN_RECV 多警惕 SYN Flood 攻击;FIN_WAIT 卡住说明对方没及时响应你的关闭它给我的启发是:netstat -ant | awk '{print $6}' | sort | uniq -c 这条命令,应该是每个后端/运维排查网络问题的第一反应——连接状态的分布,本身就是一份信息量极大的"体检报告":它能在你还没头绪时,直接告诉你"问题大概在哪一类"(是主动关太多?该关没关?连不上对方?被攻击?)。看懂连接状态,网络排查就有了方向感。

第五件事:长连接 vs 短连接怎么选

这次的根因是"用短连接扛高并发",但短连接也不是一无是处。我把两者的取舍整理了一下。

维度 短连接(每次新建关闭) 长连接(复用)
建连开销 每次三次握手+四次挥手(慢) 建一次反复用(快)
TIME_WAIT 大量(本文事故根源) 极少
资源占用 瞬时端口/fd 压力大 常驻连接占fd但稳定
实现复杂度 简单(用完就扔) 需连接池/保活/健康检查
适用场景 低频、偶发请求 高频、高并发调用
典型代表 简单脚本、一次性请求 连接池、HTTP keep-alive、gRPC

这张表,让我对"连接方式的选择"有了清晰的判断标准。核心结论是:高频、高并发的调用,必须用长连接 + 连接池(否则就是我这次踩的坑——建连开销大、TIME_WAIT 爆炸);低频、偶发的一次性请求,用短连接更简单也无妨它给我的最大启发是:选短连接还是长连接,本质是看"调用频率"——频率越高,建连/关连的固定开销就越被放大,复用连接的收益就越大而我犯的错,正是在一个"高频高并发"的场景里,图省事用了"低频偶发"才适合的短连接——把简单脚本的写法,带到了生产级高并发服务里。这让我明白:很多技术选型,没有绝对的好坏,只有"适不适合当前的量级和场景";同一种写法,在小流量下毫无问题,到了高并发下就可能是致命的写生产代码,心里要始终装着"这段代码会在多大的量级下运行"这个问题

第六件事:遇到连接建立失败,我现在的排查路径

现在再遇到 Cannot assign requested address 这类连接问题,我不再瞎猜,而是按这张图一步步定位:

这张图的精髓,是"先用 netstat 看连接状态分布、再据此定位根因"第一步永远是统计连接状态(netstat -ant | awk '{print $6}' | sort | uniq -c),让数据告诉你问题在哪一类。然后分情况:TIME_WAIT 巨多 → 你高并发主动关短连接 → 根治靠连接复用、辅助 tcp_tw_reuse;CLOSE_WAIT 巨多 → 代码该关没关的 BUG → 改码确保每连接都 close;ESTABLISHED 暴涨 → 连接泄漏(借了没还)→ 检查连接池归还逻辑最后一定要复测验证(再看一眼 netstat,确认异常状态确实降下来了)。这套路径,让我面对网络连接问题时,从"凭感觉乱试"变成了"看数据定位"——核心始终是:连接状态分布是网络问题的第一手诊断依据,先看清状态、再对症下药。

我立下的几条规矩

这场"TIME_WAIT 耗尽端口"的事故,换来了我做网络相关开发时,刻进骨子里的几条铁律:

  1. 高并发调用必须连接复用。长连接 + 连接池,别用短连接频繁新建/关闭去扛高并发。
  2. HTTP 客户端确认 keep-alive 与连接池生效。Python 用 Session、Go 复用 http.Client 并读完 Body 再 Close。
  3. 排查网络问题先 netstat 看状态分布。连接状态的分布本身就是一份高信息量的体检报告。
  4. 分清 TIME_WAIT 与 CLOSE_WAIT。前者是主动关太频繁(可调优),后者是该关没关(必须改码)。
  5. tcp_tw_reuse 可开,tcp_tw_recycle 绝不开。后者在 NAT 下会丢包,高版本内核已移除。
  6. 每个连接都要确保被关闭。用 try-with-resources / with / defer Close,堵死 CLOSE_WAIT 泄漏。
  7. 写代码时心里装着量级。同一写法小流量没事、高并发可能致命;按场景的量级做选型。

附:一段"短连接 vs 复用连接"的对比代码

口说无凭。下面用 Python 展示同样调下游 1000 次,"每次新建连接"和"复用 Session"在 TIME_WAIT 上的天壤之别——前者制造一堆,后者几乎为零:

import requests

# ====== ✗ 错误示范: 每次都新建连接(制造海量 TIME_WAIT)======
def call_downstream_bad(n):
    for i in range(n):
        # 每次 requests.get 都新建一个 TCP 连接, 用完关闭
        # → 你作为主动关闭方, 每次都产生一个 TIME_WAIT
        resp = requests.get("http://downstream/api")
        _ = resp.json()
    # 调用 1000 次 → 产生约 1000 个 TIME_WAIT
    # 高并发下迅速堆积, 占光源端口 → Cannot assign requested address

# ====== ✓ 正确示范: 复用 Session(连接池, 几乎无 TIME_WAIT)======
def call_downstream_good(n):
    # Session 内部维护连接池, 自动复用 TCP 连接 + keep-alive
    with requests.Session() as session:
        # (可选)调大连接池, 适配并发
        adapter = requests.adapters.HTTPAdapter(
            pool_connections=100, pool_maxsize=100)
        session.mount("http://", adapter)
        for i in range(n):
            # 复用同一批底层连接, 不频繁新建/关闭
            resp = session.get("http://downstream/api")
            _ = resp.json()
    # 调用 1000 次, 底层可能只用了几个连接 → TIME_WAIT 几乎为 0

# ====== 验证(在 Linux 上跑完后看连接状态)======
# call_downstream_bad(1000)
#   $ netstat -ant | grep TIME_WAIT | wc -l   → 一大堆
# call_downstream_good(1000)
#   $ netstat -ant | grep TIME_WAIT | wc -l   → 寥寥无几

# 对比要点:
#   - bad:  每次 requests.get = 新连接, 用完关 = 一个 TIME_WAIT。
#   - good: Session 复用连接池, 连接建好反复用, 不频繁关 = 极少 TIME_WAIT。

# 核心: 同样的调用次数, "复用连接"几乎不产生 TIME_WAIT,
#   "每次新建"则制造海量 TIME_WAIT。高并发场景务必复用。

这段对比代码,把"连接复用"的威力,变成了肉眼可见的数字差异。同样是调下游 1000 次:call_downstream_bad每次 requests.get 都新建一个连接、用完就关,于是你作为主动关闭方,每次都产生一个 TIME_WAIT,1000 次就是约 1000 个;而 call_downstream_goodrequests.Session() 维护连接池、自动复用连接 + keep-alive,底层可能只用了几个连接反复使用,TIME_WAIT 几乎为 0。跑完用 netstat -ant | grep TIME_WAIT | wc -l 一对比,差距一目了然。这,正是我想用这段代码,留给每个写"调下游"代码的人的最后一课:"每次新建连接"和"复用连接",在功能上看起来完全一样(都成功拿到了响应),但在高并发下的资源代价上,天差地别这也再次印证了那个道理:很多"看不出区别"的写法差异,正是在量级上来之后,才暴露出致命的不同;而把这种差异提前想清楚、在小流量时就用对的写法,正是工程师"量级思维"的体现从今天起,但凡是高频调用,我的第一反应都是:这连接,复用了吗?

延伸:为什么"机器很闲却连不出去"最迷惑人

这次事故里,最让我一开始抓不到头脑的,不是 TIME_WAIT 本身,而是那个巨大的认知反差:机器明明那么闲(CPU、内存、负载全都很低),却建立不了新连接。我们排查问题时,有一个根深蒂固的直觉——"系统出问题,一定是某种资源被用满了";而我们脑子里第一时间想到的"资源",几乎总是 CPU、内存、磁盘、带宽这"四大件"。可这次,这四样全都富余,于是我一开始完全懵了:既然啥都不缺,凭什么连不出去?直到看见那几万个 TIME_WAIT,我才恍然大悟:原来"可用源端口",也是一种会被耗尽的、有限的资源——而它,恰恰不在我们日常监控的"四大件"视野里。这给我的启发特别深:系统里"会被耗尽的资源",远比我们直觉里的那几样要多——除了 CPU/内存/磁盘/带宽,还有文件描述符(fd)、端口号、线程数、连接池大小、inode、各种队列长度……任何一种被用光,都会让系统在"其他资源明明很闲"的情况下,突然罢工所以我现在排查"资源类"问题时,会刻意提醒自己:别只盯着 CPU 和内存——当四大件都正常、系统却出问题时,要立刻想到那些"隐形的、易被忽略的有限资源"(端口、fd、连接数、句柄……),它们才是这类"诡异故障"最常见的元凶看不见的资源,往往是最先被耗尽、也最难排查的资源;心里装着一张更完整的"系统资源清单",排查这类问题时才不会一上来就钻进死胡同。

写在最后

回头看,这场由 TIME_WAIT 引发的、把端口耗尽的事故,真正教给我的,远不止"TIME_WAIT 是什么"这个知识点。它让我深刻地意识到:很多看似"诡异"的生产问题,根源往往是"把一种在小规模下完全没问题的做法,直接搬到了大规模的场景里"我用短连接去调下游,这件事在开发、测试、小流量时,一点问题都没有——连接建了、用了、关了,干净利落;可一旦到了生产高峰、高并发,这个"每次都主动关闭连接"的动作,就被放大了成千上万倍,堆出几万个 TIME_WAIT,把端口活活占光。量变,引发了质变这让我领悟到一个朴素却深刻的工程道理:评判一段代码/一个设计的好坏,不能脱离它的"运行量级";一个在 QPS=10 下优雅的方案,到了 QPS=10000 下,可能就是一场灾难;真正的生产级思维,是写每一行代码时,都去想象它在最大流量、最坏情况下的样子而具体到网络,这次事故还给了我一件趁手的兵器:遇到连接问题,先用 netstat 看连接状态分布——让数据,而不是猜测,来给你指方向这,是我用一次"机器很闲却连不出去"的诡异事故,换来的、关于网络、也关于"量级思维"的、最朴素也最深刻的领悟。如果这篇复盘,能让你在下次写"调下游"的代码时,顺手确认一下连接有没有复用,那我对着那几万个 TIME_WAIT 熬的这大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我给表建了 a、b、c 的联合索引,以为查这三列里哪一个都能走索引,结果按 b 单独查时全表扫描慢成狗,我对着最左前缀排查了大半天的复盘

2026-6-2 5:28:30

技术教程

我的 Java 容器上线后总是莫名其妙被杀、日志没有任何异常就直接退出 137,我对着 OOMKilled 和容器内存限制排查了大半天的复盘

2026-6-2 5:39:17

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索