LoadRunner压力测试SSLVPN服务器, 服务进程重启了. 用netstat -anp | grep tcp | wc -l查看, TCP连接有几万个之多! 使用
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'查看, 基本都是CLOSE_WAIT状态的TCP连接. 出现CLOSE_WAIT状态的TCP连接, 根本原因是服务器被动断开TCP连接时, 没有执行close(socketfd)操作. 刚开始我希望通过关闭fd来解决问题, 但是由于服务器的代码实现很垃圾, 基本处于不可维护状态, 在异常处理(主要是检查recv()的返回值, 如果是0, 则表明peer断开连接了, 我们可以执行close操作)时, 也不能直接关闭fd, 因为其他地方可能还在使用这个socket.
最后, 决定使用keepalive来限制CLOSE_WAIT状态的TCP个数, 在创建socket时, 作以下设置:
-
opt = 1;
-
opt_len = sizeof(opt);
-
ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &opt, opt_len);
-
if (ret < 0)
-
{
-
ERR("set SO_KEEPALIVE option failed\n");
-
return ;
-
}
-
opt = 5;
-
ret = setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &opt, opt_len);
-
if (ret < 0)
-
{
-
ERR("set TCP_KEEPCNT option failed\n");
-
return ;
-
}
-
opt = 60;
-
ret = setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &opt, opt_len);
-
if (ret < 0)
-
{
-
ERR("set TCP_KEEPIDLE option failed\n");
-
return ;
-
}
-
opt = 10;
-
ret = setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &opt, opt_len);
-
if (ret < 0)
-
{
-
ERR("set TCP_KEEPINTVL option failed\n");
-
return ;
-
}
这样, 每个TCP连接的IDLE时间是1min, 然后每过10s发送一次keepalive, 总共发5次. 这样一个TCP连接最多在IDLE状态2分钟左右.
阅读(3205) | 评论(0) | 转发(0) |