Tomcat修改文件句柄限制后报Failed to register socket错误如何解决
问题根因分析
- limits.conf配置不生效:Ubuntu默认使用systemd管理服务,
/etc/security/limits.conf仅对PAM登录的用户会话生效,systemd托管的Tomcat服务不会读取该配置,因此重启后仍保留默认的4096文件打开数限制。 - 后续EPoll空指针报错:该异常是JDK EPoll实现的已知bug,触发的核心原因还是文件句柄耗尽。你通过prlimit临时修改的限制要么不足以覆盖业务实际的并发连接需求,要么应用本身存在socket、文件流等资源泄漏,长期运行后句柄被占满,触发了JDK底层的空指针逻辑。
可行解决方案
1. 永久生效文件打开数限制
修改Tomcat的systemd服务配置,路径通常为/etc/systemd/system/tomcat.service或/usr/lib/systemd/system/tomcat.service,在[Service]配置段添加如下参数:
LimitNOFILE=10000:30000
修改完成后执行systemctl daemon-reload重载systemd配置,再重启Tomcat服务,通过cat /proc/<Tomcat进程PID>/limits验证即可看到配置生效。
2. 修复EPoll空指针异常
- 优先升级JDK版本:该
EPollArrayWrapper空指针bug已在JDK 8u282、JDK 11.0.10及以上版本修复,升级对应版本JDK即可从底层避免该异常。 - 临时应急方案:如果暂时无法升级JDK,可在
catalina.sh的JAVA_OPTS中添加启动参数-Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.PollSelectorProvider,切换PollSelector实现避开EPoll的bug,也可临时将Tomcat连接器从NIO模式切换为BIO模式(性能会下降,不建议长期使用)。
3. 排查资源泄漏风险
- 定期统计Tomcat进程的打开句柄数,执行命令
lsof -p <Tomcat进程PID> | wc -l即可查看,如果句柄数长期持续上涨不回落,说明存在资源泄漏,需检查应用代码中的socket连接、文件流、数据库连接等资源是否在finally块中正常关闭。 - 如果业务并发量确实较高,可适当调高文件打开数限制,比如将软限制调整为65535、硬限制调整为100000,同步更新systemd服务的LimitNOFILE配置即可。
内容的提问来源于stack exchange,提问作者Shailendra Garg
相关产品推荐
相关产品推荐

