Linux端口被占用的场景分析

Posted by Epoch Blog on December 14, 2021

今天定位了一个问题,记录一下

前景

一个Java的Springboot进程,写了一个shell脚本启动,发现启动后,再次重启,怎么都起不来,查看报错是rmi端口被占用

java.rmi.server.ExportException: Port already in use: 0

但是端口被占用的是0啊,这是不可能会被占用的,因此排除被占用的场景。

通过netstat -a查看,大量的mysql的请求处于TIME_WAIT状态,同时也查看到了具体的我们的内部业务的进程,是go业务进程占用的。

此时也刚好得知同时报错,具体是

192.168.51.105:3306: connect cannot assign requested address

bind:An operation and socket counld not be perfirmed because the system I acked sufficient buffer space or because a queue was full。

我分析应该是go内部的连接数据代码大量建立连接导致的,go业务在每1-2秒界面不断的发送查询请求。

刚好也我开发了个监控系统,监控到mysql的状态连接connections不断增加,确实如此。

结果分析:

综合以上得知错误的原因:Linux分配的客户端连接端口用完,导致无法建立socket连接导致。因此虽然socket正常关闭,但是端口不是立即关闭的,而是处于TIME_WAIT状态,需要等待60s才能释放。

事故的原因很明显,go业务代码在不断的建立连接,走读代码发现果然是,同事引用的框架,默认的初始化空闲连接是0,最大连接数竟然是20000。

这简直太疯狂了,截止目前原因已经找到,建议根据业务的规模,配置初始化10个连接,最大连接100个。

引发的思考:

1.如果我们的业务确实需要大量的短暂的连接,我们需要怎么处理?

其实很简单,就是吧linux的socket的等待关闭时间缩减,缩减到我们的正常业务时间。

2.连接池的重要性,这让我们学会,必须配置适当的连接池,否则会造成一些灾难。