线上服务有一类问题特别隐蔽,不会直接宕机,不会瞬间报错,只会随着运行时间慢慢恶化。刚开始一切正常,跑几天或者一两周后,接口开始随机超时、请求失败、服务日志刷不出来,最后彻底拒绝新连接。
很多人遇到这种情况第一反应就是重启服务,重启完立马恢复,所有人都以为是内存泄漏、资源抖动,真正的根源很少有人查到——文件句柄泄露。
平时开发读写文件、调用脚本、请求socket、操作数据流,很多资源打开之后没有正常关闭。单次执行完全无感,系统资源看似正常归还。但高并发、高频调用场景下,句柄会持续累积,不会自动释放。
服务器对单个进程的最大文件句柄数是有限制的。一旦打满,所有需要新建文件、连接、日志、流操作的行为全部失败,表现出来的症状五花八门,很难直接联想到根源。
最迷惑人的一点是,报错信息非常零散。
有的节点提示无法创建日志文件,有的提示socket创建失败,有的第三方接口请求直接超时,还有的数据库连接获取异常。不同功能爆出完全不相关的错误,很容易让人误以为是多处代码同时出问题,不会统一归因为系统资源耗尽。
我之前遇到过一个真实案例,导出功能、日志打印、消息推送、数据库查询,四个完全不同的模块同时间歇性报错。排查半天看不出关联性,最后查进程句柄数量,早已远超系统阈值,才确认是泄露导致的连锁问题。
日常开发里,句柄泄露的原因大多不是复杂逻辑,而是不起眼的编码习惯。
读取本地临时文件不关闭流、模板解析后不释放资源、压缩解压操作残留数据流、http请求响应不关闭、第三方工具类内部打开资源不回收。这些代码单次执行毫无问题,压测短时间也看不出异常,只有长期运行才会暴露。
更隐蔽的是一些工具类、开源组件自带的资源泄漏问题。
很多人直接引用外部工具包,处理Excel、PDF、压缩包、图片解析,只调用方法获取结果,完全不清楚底层会打开文件流、创建临时资源。组件内部异常时,资源关闭逻辑跳过,句柄悄悄堆积,开发者完全感知不到。
还有一种场景是异常分支跳过关闭逻辑。
正常流程能顺利关闭资源,一旦中途抛出异常,程序直接跳出,关闭代码没有执行。长期累积下来,异常场景越多,句柄泄露越严重。这类问题随机性极强,完全取决于线上报错频次,本地几乎复现不了。
很多团队的排查盲区也在这里。
日常监控大多只看CPU、内存、磁盘、QPS,很少有人监控文件句柄占用数。资源慢慢被耗尽的过程全程无告警,等到问题爆发,服务已经濒临瘫痪。
重启服务能瞬间释放所有句柄,问题临时解决,但根本原因不动,过几天必然复现,陷入反复重启的恶性循环。
实际上这类问题根治并不难,关键在于平时没有建立资源回收的意识。
所有流操作、资源打开、外部调用,不管正常还是异常,都必须保证最终关闭。使用自动关闭的语法、finally兜底、资源池复用,都是很简单有效的手段。定时巡检服务器句柄占用,提前发现溢出苗头,也能避免线上故障。
线上稳定性问题,很多时候不是来自复杂架构缺陷,而是这种日积月累的微小资源泄露。不起眼的代码细节,长期累积,最终就能拖垮一整个服务。
线上问题复盘:不知不觉拖垮服务的文件句柄泄露
张小明
前端开发工程师
Java实现 DWG 转 PDF 服务
手上有个需求,要把 CAD 图纸(DWG)转成 PDF 做归档,要求走接口调用、Docker 部署,端口还得能配。刚拿到需求的时候觉得这活儿不难,真做下来发现坑比想象中多,而且基本都出在 DWG 这个格式本身上。…
【Agent】Agent Harness 综述:从 Orchestration 到 Context Engineering 的工程化落地
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
DEV 实战:ComboBoxEdit 与 barEditItem 配置 TaoToken 的 settings.json 骨架
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
对话百川智能王小川:争取2027年上市,账上30亿完全足够烧——TaoToken统一Key/API通道配置实战
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
大厂JD里反复出现的Agent、RAG、MCP协议——2026届校招生用TaoToken怎么准备?
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
app-ideas 中级实战:基于实时汇率 API 构建 Currency Converter 货币换算器
文档教程 【免费下载链接】app-ideas A Collection of application ideas which can be used to improve your coding skills. 项目地址: https://gitcode.com/GitHub_Trending/ap/app-ideas 点击查看 免费下载 Tier:2-Intermediate(中级&am…