linux上TCP connection timeout问题解决办法
发布时间 - 2026-01-11 00:39:21 点击率:次linux上TCP connection timeout问题解决办法

最近在产线上经常出现connection timeout的问题,先看看Java 中关于connection timeout 的异常如何产生
JAVA中的timeout
java.net.SocketTimeoutException: connect timed out 客户端异常:connect timed out at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589)
我们能经常看到的connect timed out异常产生,看一下java 是如何生成这个异常
plainsocketimpl.c 中
while (1) {
jlong newTime;
#ifndef USE_SELECT
{
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT;
errno = 0;
connect_rv = NET_Poll(&pfd, 1, timeout);
}
#else
{
fd_set wr, ex;
struct timeval t;
t.tv_sec = timeout / 1000;
t.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&wr);
FD_SET(fd, &wr);
FD_ZERO(&ex);
FD_SET(fd, &ex);
errno = 0;
connect_rv = NET_Select(fd+1, 0, &wr, &ex, &t);
}
#endif
if (connect_rv >= 0) {
break;
}
if (errno != EINTR) {
break;
}
/*
* The poll was interrupted so adjust timeout and
* restart
*/
newTime = JVM_CurrentTimeMillis(env, 0);
timeout -= (newTime - prevTime);
if (timeout <= 0) {
connect_rv = 0;
break;
}
prevTime = newTime;
} /* while */
if (connect_rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"connect timed out");
/*
* Timeout out but connection may still be established.
* At the high level it should be closed immediately but
* just in case we make the socket blocking again and
* shutdown input & output.
*/
SET_BLOCKING(fd);
JVM_SocketShutdown(fd, 2);
return;
}
这里可以看到在做connect的时候,是调用 NET_Poll 或者 NET_Select, 在linux 上就是使用 poll/select
当发生timeout的时候connect_rv=0 ,这里有个注意点虽然在poll/select 是传入timeout的时间,但是这是会被打断的,connect_rv返回的值为-1 ,所以jvm里面重新计算了timeout , 确保timeout 的时间片已经运行完了,才推出循环。
newTime = JVM_CurrentTimeMillis(env, 0);
timeout -= (newTime - prevTime);
if (timeout <= 0) {
connect_rv = 0;
break;
}
同时设置connect_rv 为0, 也是下面只有当connect_rv为0的时候才抛出connect timeout
什么是connect timeout ?
也就是client 发出 syn 包,server端在你指定的时间内没有回复ack,poll/select 返回0
server 端为什么没有回复ack, 因为syn包的回复是内核层的,要么网络层丢包,要么就是内核层back_log的queue满了,关于backlog在本片中就不详细描述了。
当时查看产线上的连接最高能到1000多,同时查看了backlog 的queue的大小
cat /proc/sys/net/ipv4/tcp_max_syn_backlog
有8192 在产线上没有这么多的客户端的连接,不可能backlog queue会满,虽然syn_backlog 的设置是8192 但并不代表服务器启动的时候设置成了8192,所以必须查这个端口所设置的backlog大小
ss -lt
看到Send-Q在8080端口是128 ,原来在服务器端启动listen 的时候设置了128的backlog
查看tomcat 的配置,默认bio的设置
<Connector executor="tomcatThreadPool"
port="8080"
protocol="HTTP/1.1"
acceptCount="5000"
connectionTimeout="25000"
maxHttpHeaderSize="8192"
useBodyEncodingForURI="true"
enableLookups="false"
redirectPort="8443"
URIEncoding="UTF-8"
maxThreads="500"
maxKeepAliveRequests="1000"
keepAliveTimeout="30000"
/>
产线上已经设置了acceptCount, 默认是100 但是这里设置了是5000 ,这与通过ss看到的send-q的结果严重不符合
通过内核代码分析,发现原来内核参数不仅仅是通过tcp_max_syn_backlog控制,同时也受somaxconn控制
查看
cat /proc/sys/net/core/somaxconn
发现值是128, OK 原因找到了,修改/etc/sysctl.conf 添加
net.core.somaxconn = 8192
sysctl -f /etc/sysctl.conf 重新加载一下,这样就能改变全局了
问题:是1000多个连接,500个工作线程,因为backlog的大小是受socket.accept控制的,我们通常境况下会单独起一个线程去serversocket.accept(),而当前server的load并不高,不因该会出现back_log queue出现满的情况,更何况只有1000多个连接,代码就是真相,查看tomcat的源码。
原来accptor 线程在accept 之前,会去countUpOrWaitConnection 发现接受到的的socket数目大于设置的work线程数目的时候,会停止accept.
<strong>countUpOrAwaitConnection</strong>();
Socket socket = null;
try {
// Accept the next incoming connection from the server
// socket
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
countDownConnection();
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
}
也就是说当并发超过628个连接以上,就有可能出现backlog queue满的情况,而出现connect timeout的情况,一切皆清楚了。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# linux上TCP
# connection
# timeout的原因查找
# TCP
# timeout
# 详解Linux使用shell+expect远程登录主机
# Linux主机登录abrt-cli status timed out的
# 线上
# 多个
# 客户端
# 这是
# 成了
# 不可能
# 看了
# 有个
# 就能
# 就有
# 就不
# 这么多
# 时间内
# 希望能
# 不高
# 可以看到
# 仅是
# 不符合
# 满了
# 并不代表
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
Laravel如何与Inertia.js和Vue/React构建现代单页应用
北京企业网站设计制作公司,北京铁路集团官方网站?
Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】
如何快速建站并高效导出源代码?
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
Laravel怎么调用外部API_Laravel Http Client客户端使用
如何用AWS免费套餐快速搭建高效网站?
免费视频制作网站,更新又快又好的免费电影网站?
如何用腾讯建站主机快速创建免费网站?
javascript事件捕获机制【深入分析IE和DOM中的事件模型】
香港服务器网站推广:SEO优化与外贸独立站搭建策略
详解jQuery停止动画——stop()方法的使用
iOS发送验证码倒计时应用
Laravel如何实现文件上传和存储?(本地与S3配置)
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
如何在景安服务器上快速搭建个人网站?
网站建设整体流程解析,建站其实很容易!
佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】
如何正确下载安装西数主机建站助手?
BootStrap整体框架之基础布局组件
Laravel如何实现数据库事务?(DB Facade示例)
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
无锡营销型网站制作公司,无锡网选车牌流程?
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
百度浏览器网页无法复制文字怎么办 百度浏览器复制修复
Laravel怎么连接多个数据库_Laravel多数据库连接配置
SQL查询语句优化的实用方法总结
如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】
LinuxShell函数封装方法_脚本复用设计思路【教程】
详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)
利用vue写todolist单页应用
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
如何在景安云服务器上绑定域名并配置虚拟主机?
jQuery 常见小例汇总
Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法
Swift开发中switch语句值绑定模式
,南京靠谱的征婚网站?
INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】
html5怎么画眼睛_HT5用Canvas或SVG画眼球瞳孔加JS控制动态【绘制】
Laravel怎么使用artisan命令缓存配置和视图
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
Laravel如何与Pusher实现实时通信?(WebSocket示例)
Laravel如何使用Service Provider服务提供者_Laravel依赖注入与容器绑定【深度】
上一篇:任嘉伦专辑36启在哪买
上一篇:任嘉伦专辑36启在哪买

