其实这个keepalive是tcp一种探活机制,可不是http1.1当中的keeplive。
测试环境centos6.8 64位系统。
输入命令,查看linux系统内核的默认参数设置。
[root@nd1 bin]# sysctl -a|grep tcp_keepalive
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
当客户端与服务器端三次握手正式建立tcp以后,默认情况下,除非客户端或服务器端关闭上层socket,否则tcp会始终保持连接,如果这个时候网络断掉,这个链接就会变成一个死链接,会占用服务器资源。
那如何解决这种问题呢?
1、大多数的上游应用会通过心跳机制来检测对方是否存活,不存会则由上游应用程序关闭socket释放链接。
2、通过tcp带的keeplive机制来检测,已Java为例,在socket编程中需要显示开启tcp的keeplive 。
socket.setKeepAlive(true);
参数解释:
tcp_keepalive_time 7200 秒 (2小时),当tcp建立链接后2小时如果无数据传输,则会发出探活数据包。
tcp_keepalive_probes 9 (次), 一共发送9次。
tcp_keepalive_intvl 75 秒,一共发送9次,每次间隔75秒。
如果对方没有回复包,则认为对方已掉线,系统会关闭tcp链接。
Java测试:
server端代码,一个简单的socket server,啥也不干,拿到socket就一直等着客户端发送数据。
ServerSocket serverSocket = new ServerSocket(9999);
while (true) {
final Socket socket = serverSocket.accept();
socket.setKeepAlive(true);
System.out.println("a client connect");
final InputStream in = socket.getInputStream();
while (in.read() != -1) {
System.out.println("read");
}
}
client端代码,与服务器端建立连接后,把线程挂起,不发数据,观察tcp keeplive探活请客。
Socket socket = new Socket("192.168.80.110", 9999);
System.out.println(socket.getKeepAlive());
socket.setKeepAlive(true);
OutputStream out = socket.getOutputStream();
Thread.sleep(2000000);
为了测试出效果,我们需要修改linxu内核参数
编辑 vim /etc/sysctl.conf
添加 net.ipv4.tcp_keepalive_time = 30
生效 sysctl -p
可以看到,tcp已经发送探活数据包,如果对方没有回应则认为对方掉线,系统会关闭tcp连接。
下面配置nginx的 so_keepalive
=on
|off
|[keepidle
]:[keepintvl
]:[keepcnt
] 配置
so_keepalive
=on 表示开启tcp探活,并且使用系统内核的参数。
so_keepalive=30m::10 表示开启tcp探活,30分钟后伍数据会发送探活包,时间间隔使用系统默认的,发送10次探活包。
will set the idle timeout (TCP_KEEPIDLE
) to 30 minutes, leave the probe interval (TCP_KEEPINTVL
) at its system default, and set the probes count (TCP_KEEPCNT
) to 10 probes.
server {
listen 80 so_keepalive=on;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
#access_log "pipe:rollback logs/host.access_log interval=1d baknum=7 maxsize=2G" main;
location / {
proxy_pass http://favtomcat;
proxy_http_version 1.1;
proxy_set_header Connection "";
#root html;
#index index.html index.htm;
}
xxx
xxx
...
}