跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java 应用报错 No buffer space available 排查与解决

解决了 Java 应用在 Windows Server 上运行时报错 No buffer space available 的问题。经排查,原因是 Apache HttpClient 未正确关闭响应对象导致大量 CLOSE_WAIT 连接堆积,耗尽系统临时端口。解决方案包括修复代码使用 try-with-resources 确保资源释放、配置连接池复用、调整动态端口范围及优化 TIME_WAIT 设置。通过监控 netstat 状态验证修复效果,并建议建立代码规范与监控告警机制预防此类问题。

晚风叙旧发布于 2026/3/28更新于 2026/9/373 浏览
Java 应用报错 No buffer space available 排查与解决

一、问题现象

某基于 Java 应用在 Windows Server 上运行一段时间后,突然抛出异常:

java.net.SocketException: No buffer space available (maximum connections reached?): connect 或 java.net.BindException: Address already in use: getsockopt 

应用无法处理新请求,重启后短暂恢复,但几小时后再次出现相同错误。初步判断为系统资源耗尽,但具体原因需要深入排查。

二、环境信息

  • 操作系统:Windows Server 2019
  • JDK 版本:Java 17.0.14
  • 应用框架:Spring Boot 2.x
  • 进程 PID:12345(示例)

三、排查过程

1. 检查 TCP 连接总数

以管理员身份打开命令提示符,执行:

netstat -an | find /c "TCP" 

输出结果:

63113 

系统当前存在63,113个 TCP 连接,远超正常水平。

2. 检查动态端口范围
netsh int ipv4 show dynamicport tcp 

输出:

协议 tcp 动态端口范围 ---------------------------------
启动端口 : 9000
端口数 : 56000 

动态端口范围已设置为 9000~64999(共 56000 个),但连接数已超过此范围,端口耗尽。

3. 分析连接状态分布

统计各种状态的连接数量:

netstat -an | find /c "TIME_WAIT"
netstat -an | find /c "ESTABLISHED"
netstat -an | find /c "CLOSE_WAIT" 

输出示例:

TIME_WAIT: 281
ESTABLISHED: 7120
CLOSE_WAIT: 55690 

关键发现:55,690个连接处于 CLOSE_WAIT 状态,占总连接数约 88%,这是典型的连接泄漏。

4. 查看 CLOSE_WAIT 连接的详细信息
netstat -ano | findstr CLOSE_WAIT 

输出片段:

TCP 192.168.1.100:54995 203.0.113.5:8080 CLOSE_WAIT 12345
TCP 192.168.1.100:54996 203.0.113.5:8080 CLOSE_WAIT 12345
TCP 192.168.1.100:54997 203.0.113.5:8080 CLOSE_WAIT 12345
...
  • 本地地址:192.168.1.100(应用服务器)
  • 远程地址:203.0.113.5:8080(固定的目标服务)
  • 状态:CLOSE_WAIT
  • 进程 PID:12345(与 Java 应用 PID 一致)

结论:应用程序作为 TCP 客户端,向 203.0.113.5:8080 发起大量连接,但未正确关闭,导致连接堆积在 CLOSE_WAIT 状态,最终耗尽临时端口。

四、根本原因分析

当 TCP 连接被对端主动关闭后,本地会进入 CLOSE_WAIT 状态,此时应用程序必须调用 close() 释放 socket 资源。如果应用程序未关闭 socket,连接将永远停留在 CLOSE_WAIT,占用端口和句柄。

根据 netstat 信息,本应用频繁连接 203.0.113.5:8080,但代码中未正确释放连接资源。经代码审查,发现应用使用 Apache HttpClient 发送 HTTP 请求,但未关闭 CloseableHttpResponse 对象,导致底层 TCP 连接无法释放。

五、解决方案

1. 修复代码:确保资源正确关闭
错误示例(导致泄漏)
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://203.0.113.5:8080/api");
CloseableHttpResponse response = httpClient.execute(request);
// 处理响应... 但忘记关闭 response
String result = EntityUtils.toString(response.getEntity());
// 没有 response.close()
正确示例(使用 try-with-resources)
// 复用同一个 HttpClient 实例(连接池)
private static final CloseableHttpClient httpClient = HttpClients.custom()
    .setMaxConnTotal(200)
    .setMaxConnPerRoute(50)
    .build();

public String callRemoteApi() {
    HttpGet request = new HttpGet("http://203.0.113.5:8080/api");
    // 自动关闭 response
    try (CloseableHttpResponse response = httpClient.execute(request)) {
        // 必须消费响应体,否则连接无法释放
        return EntityUtils.toString(response.getEntity());
    } catch (IOException e) {
        // 异常处理
    }
}

// 应用关闭时释放连接池
public void destroy() {
    try { httpClient.close(); } catch (IOException e) { /* log error */ }
}

关键点:

  • 每次 execute() 返回的 CloseableHttpResponse 必须关闭。
  • 使用连接池(复用 CloseableHttpClient)减少连接创建开销。
  • 确保消费响应体(如 EntityUtils.toString()),否则连接可能无法释放。
2. 调整 Windows 动态端口范围(临时缓解)

在代码修复上线前,可扩大端口范围以延缓耗尽:

netsh int ipv4 set dynamicport tcp start=1024 num=64512 

此命令将动态端口范围设为 1024~65535(共 64512 个),修改后立即生效,无需重启。

3. 缩短 TIME_WAIT 延迟(非必需,但可优化)

如果存在大量短连接,可缩短 TIME_WAIT 时长(默认 240 秒),加速端口回收。通过注册表调整:

  • 打开注册表编辑器:regedit
  • 定位到:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
  • 新建 DWORD(32 位)值,名称为 TcpTimedWaitDelay,数值数据输入 30(十进制),表示 30 秒。
  • 重启生效。

六、验证修复效果

  1. 重启应用。
  2. 监控 CLOSE_WAIT 数量:
netstat -an | find /c "CLOSE_WAIT" 

应保持稳定且较低(例如几十到几百,取决于并发请求数)。 3. 监控总连接数,不应持续增长。

七、预防措施

  1. 代码规范:所有网络资源(Socket、HttpResponse、数据库连接等)必须在 finally 块或 try-with-resources 中关闭。
  2. 连接池化:使用连接池管理 HTTP 连接、数据库连接,避免为每个请求创建新连接。
  3. 监控告警:定期检查系统 CLOSE_WAIT 数量,设置阈值告警(例如超过 1000 触发报警)。
  4. 压力测试:上线前进行压力测试,观察连接数是否稳定。
  5. 日志记录:在关键网络操作处添加日志,便于追踪未关闭的连接。

八、总结

本次故障源于应用程序作为 HTTP 客户端未正确关闭连接,导致海量 CLOSE_WAIT 连接堆积,最终耗尽系统临时端口。通过代码修复(确保资源释放)和连接池优化,彻底解决了问题。Windows 环境下 netstat 是排查网络问题的利器,结合进程 PID 可快速定位泄漏源。希望本文能帮助读者避免类似问题,提升应用稳定性。


附:一键复制命令 以下命令可直接复制使用:

:: 查看 TCP 连接总数
netstat -an | find /c "TCP"
:: 查看 CLOSE_WAIT 数量
netstat -an | find /c "CLOSE_WAIT"
:: 查看 CLOSE_WAIT 详细信息
netstat -ano | findstr CLOSE_WAIT
:: 扩大动态端口范围
netsh int ipv4 set dynamicport tcp start=1024 num=64512
:: 查看动态端口范围
netsh int ipv4 show dynamicport tcp 

目录

  1. 一、问题现象
  2. 二、环境信息
  3. 三、排查过程
  4. 1. 检查 TCP 连接总数
  5. 2. 检查动态端口范围
  6. 3. 分析连接状态分布
  7. 4. 查看 CLOSE_WAIT 连接的详细信息
  8. 四、根本原因分析
  9. 五、解决方案
  10. 1. 修复代码:确保资源正确关闭
  11. 错误示例(导致泄漏)
  12. 正确示例(使用 try-with-resources)
  13. 2. 调整 Windows 动态端口范围(临时缓解)
  14. 3. 缩短 TIME_WAIT 延迟(非必需,但可优化)
  15. 六、验证修复效果
  16. 七、预防措施
  17. 八、总结

更多推荐文章

查看全部
  • AI 与存储的结合:智能存储的实践与挑战
  • Docker 部署 OpenClaw 踩坑实录:Web UI 访问、飞书配对及自定义模型配置
  • WebSite-Downloader 网站整站下载工具使用指南
  • Java 生成 1 到 1000 范围内的 900 个不重复随机数
  • 网络安全入门教程:从零基础到精通的详细指南
  • 深度学习实战:卷积神经网络(CNN)原理与 LeNet-5 搭建
  • QClaw 本地化 AI 个人助手平台使用指南
  • Dify AI 智能体部署与使用指南
  • HDFS 核心组件深度解析:分布式文件系统架构基石
  • Spring Boot 快速构建基于 Spring AI 的智能助手
  • C++ 手搓 AVL 平衡二叉搜索树
  • 通义万相 2.1 多模态生成能力解析与落地实践
  • Flutter 三方库 web_ffi 的鸿蒙化适配指南
  • 大模型在大数据平台的应用场景与开发落地实践
  • AIGC 与现代教育技术
  • Java 智能仿真无人机项目 4.0 核心实现
  • 7 款热门 Claude Skills 开源工具:GitHub 精选技能库
  • 前端监控实战:错误、性能与用户行为追踪
  • 小米手机端 Agent 落地,撬开智能家居十年困局
  • Llama.cpp 整体架构分析

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online