Connection refused间歇性出现的问题定位
Posted zhengwangzw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Connection refused间歇性出现的问题定位相关的知识,希望对你有一定的参考价值。
出现Connection refused的问题原因一般有三种:
1. 服务器的端口没有打开 这种直接就是一直会Connection refused,不会间歇出现,可以直接排除;
2. 服务器的防火墙没有开白名单 很多跟外部对接的时候,是需要将公司出口ip加到对方防火墙白名单,这种也会直接Connection refused,不会间歇出现,可以直接排除;
3. 服务器上的backlog设置的太小,导致连接队列满了,服务器可能会报Connection refused,或者Connecttion reset by peer,这个看服务器上的连接队列满时的设置;
详细的异常堆栈信息如下:
看保持方法:
是个native方法,毫不意外。因为是跟第三方云服务商对接,只能让他们查服务器配置的backlog大小,这里回顾一下tcp三次握手的过程。
第一步:client 发送syn到server发起握手;
第二步: server收到syn后回复syn + ack 给client;
第三步:client收到syn + ack后,回复server一个ack表示收到server的syn + ack;
Tcp连接是有张如下图的:
1. 服务端调用bind() & listen() 函数后,会监听本地某个端口;
2. 客户端发SYN,服务端收到,连接状态变为SYN_RCVD,将连接放到半连接队列中,同时回复syn+ack给client;
3. 客户端收到syn + ack,客户端连接状态变为ESTABLISHED,回复ack,将连接放到全连接队列。
其中半连接队列的大小看: max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)
上面是我机器上半连接的配置,挺大的,26万。
全连接队列的大小: min(backlog, somaxconn), backlog是在socket创建的时候传入的,somaxconn是一个os级别的系统参数。
代码涉及到Socket这一层的操作时,需要自己传backlog的大小,否则默认值是50.
public ServerSocket(int port, int backlog) throws IOException { this(port, backlog, null); }
所有上面Connection Refused很容易因为backlog设置的太小而发生,例如,nginx的配置就有backlog, 默认是511,Tomcat 默认是100。
一般来说,如果是公司自己的服务器,可以通过TCP建连接的时候全连接队列(accept队列)满了,通过一些命令可以查询队列情况:
netstat -s 命令
通过netstat -s | egrep "listen" 看队列的溢出统计数据,多执行几次,看全连接队列overflow次数有没有增长:
ss 命令
上面看Send-Q的值就是listen端口上全连接队列的最大值,Recv-Q就是当前全连接队列用了多少。
netstat跟ss命令一样也能看到Send-Q、Recv-Q这些状态信息,不过如果这个连接不是Listen状态的话,Recv-Q就是指收到的数据还在缓存中,还没被进程读取,这个值就是还没被进程读取的 bytes;而 Send 则是发送队列中没有被远程主机确认的 bytes 数。
因此如果出现间歇性Connection Refused,检查是否有设置backlog, backlog设置的是否过小。
以上是关于Connection refused间歇性出现的问题定位的主要内容,如果未能解决你的问题,请参考以下文章
使用Jedis出现Connection refused的解决方案
在heroku上部署了我的应用程序但出现错误:加载资源失败:net::ERR_CONNECTION_REFUSED
scp出现ssh port 22: Connection refused 问题解决具体步骤
public class feign.RetryableException feign.RetryableException: Connection refused (Connection refus