昨天和同事奋战几个小时,解决了一个linger造成的bug。

现象是这样的,这是一个我从原型接手,扩充了各种功能成为可用代码的epoll实现的非阻塞socket server程序,接收大量的短连接,测试发现性能有问题,用gperftools的cpu profiler也没看出问题。就在一些可疑调用的地方前后加时间,耗时较长的就打出来。一开始发现是epoll处理某些fd的时间有时很长,最后发现是close(fd)耗时达一秒。我才想起来,上周为了解决短连接丢数据问题,把原来linger的超时从0改为了1,改回去现象就消失了,最后彻底去掉就解决了。

原来,在linux下,只要开启了linger并设置了非0的超时,那么close时,如果有数据待发送,就会阻塞最多达指定的时间,不管socket是不是阻塞的。看了一下内核代码,也确认是这样处理的,有点出乎意料。

// net/ipv4/tcp.c

void tcp_close(struct sock *sk, long timeout)
{
// ...
sk_stream_wait_close(sk, timeout);
// ...
}
// net/ipv4/af_inet.c

int inet_release(struct socket *sock)
{
struct sock *sk = sock->sk; if (sk) {
long timeout;
// ...
timeout = 0;
if (sock_flag(sk, SOCK_LINGER) &&
!(current->flags & PF_EXITING))
timeout = sk->sk_lingertime;
sock->sk = NULL;
sk->sk_prot->close(sk, timeout);
}
return 0;
}

回想当初是这个错误的原因是,因为manpage里没找到,我查一些文章却说close一个这样的socket时,会返回EWOULDBLOCK,大意了。至于代码当初为什么会开启linger,估计是为了消除TIME_WAIT,但是这种做法是得不偿失的。

查阅MSDN closesocket的文档,发现winsock下的行为不一样,会返回EWOULDBLOCK,这可能就是误导我的文章的说法的出处吧。

结论:对于使用非阻塞socket的程序,linger基本就是个无用且有害的选项,开启并设置0超时会丢数据,设置非0超时又会阻塞,因此千万不要用它。

TCP Linger的坑的更多相关文章

  1. Redis 高可用集群

    Redis 高可用集群 Redis 的集群主从模型是一种高可用的集群架构.本章主要内容有:高可用集群的搭建,Jedis连接集群,新增集群节点,删除集群节点,其他配置补充说明. 高可用集群搭建 集群(c ...

  2. OpenShift应用镜像构建(4) - fabric8-maven-plugin

    适合开发的构建fabric8-maven-plugin 在项目过程中越来越多的出现在开发阶段就需要把部分微服务直接做容器化发布,然后自己的代码还需要和这些发布后的微服务进行调用的开发过程,这个阶段基本 ...

  3. tcp.validnode_checking踩过的坑

    对Oracle 检查ip合法性,就必须在服务器端的sqlnet.ora文件中设置如下参数 TCP.INVITED_NODES=(10.0.0.36,10.0.0.1,10.0.0.35) TCP.EX ...

  4. tcp状态-TIME_WAIT与CLOSE_WAIT带来的坑

    tcp状态: http://www.cnblogs.com/DengGao/p/tcp_state.html 1. tcp连接会占用系统资源(文件描述符), 有时候甚至会导致系统假死(不能发起或者处理 ...

  5. 【服务器踩坑】SSMS链接Ubuntu上的SQL Server 2019 报错 TCP Provider: Error code 0x2746

    昨天在一台Ubuntu18.04.2 上安装了SQL Server 2019 for Linux 服务正常启动了,但是却无法通过命令行工具或者远程Windows机器上的SSMS链接. SSMS错误是 ...

  6. Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新Client API的使用要点,高可用性测试,以及各种坑 (转载)

    Kafka 0.9版本对java client的api做出了较大调整,本文主要总结了Kafka 0.9在集群搭建.高可用性.新API方面的相关过程和细节,以及本人在安装调试过程中踩出的各种坑. 关于K ...

  7. HttpClient在多线程环境下踩坑总结

    问题现场 在多线程环境下使用HttpClient组件对某个HTTP服务发起请求,运行一段时间之后发现客户端主机CPU利用率呈现出下降趋势,而不是一个稳定的状态. 而且,从程序日志中判断有线程处于han ...

  8. 一次flume exec source采集日志到kafka因为单条日志数据非常大同步失败的踩坑带来的思考

    本次遇到的问题描述,日志采集同步时,当单条日志(日志文件中一行日志)超过2M大小,数据无法采集同步到kafka,分析后,共踩到如下几个坑.1.flume采集时,通过shell+EXEC(tail -F ...

  9. TCP随笔

    目录 前言 正文 time_wait和rst fin与连接关闭 nagel和ack延迟算法 滑动窗口与拥塞控制 文末 总结 测试代码 前言 网上已经有大量关于tcp的文章,感觉作为一名技术人员,不写一 ...

随机推荐

  1. jQuery toggle() 方法与实例以及代替方法。

    看<jQeury 权威指南>时看到这个toggle()方法.因为之前在慕课网学习接触过.发现两者讲的有细微的不同 以隐藏/显示目标元素效果为例,慕课网是这样讲解的 $("#cli ...

  2. Oauth支持的5类 grant_type 及说明

    authorization_code 授权码模式(即先登录获取code,再获取token) password 密码模式(将用户名,密码传过去,直接获取token) client_credentials ...

  3. exit() die return 的区别

    rutrun 会返回一个值,或不返回值 只是当前函数内return后面的语句将不会执行,后面的其它语句继续执行exit()可以返回值,也可以不返回值直接终止程序 函数输出一条消息,并退出当前脚本. 会 ...

  4. Google Protocal Buffer

    Google Protocal Buffer 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化或者说序列化.它很适合做数据存储或RPC数据交换格式. 串行化(序列化):将对象存储到解释中式 ...

  5. TCP回射服务器程序:main函数

    TCP回射并发服务器 1.创建套接字,绑定服务器的众所周知端口 创建一个TCP套接字,在待绑定到该TCP套接字的网际网套接字地址结构中填入通配地址(INADDR_ANY) 和服务器的众所知周(SERV ...

  6. android.os.NetworkOnMainThreadException 在4.0之后谷歌强制要求连接网络不能在主线程进行访问

    谷歌在4.0系统以后就禁止在主线程中进行网络访问了,原因是: 主线程是负责UI的响应,如果在主线程进行网络访问,超过5秒的话就会引发强制关闭, 所以这种耗时的操作不能放在主线程里.放在子线程里,而子线 ...

  7. codevs 3269 混合背包

    题目描述 Description 背包体积为V ,给出N个物品,每个物品占用体积为Vi,价值为Wi,每个物品要么至多取1件,要么至多取mi件(mi > 1) , 要么数量无限 , 在所装物品总体 ...

  8. mysql的mvcc(多版本并发控制)

    mysql的mvcc(多版本并发控制) 我们知道,mysql的innodb采用的是行锁,而且采用了多版本并发控制来提高读操作的性能. 什么是多版本并发控制呢 ?其实就是在每一行记录的后面增加两个隐藏列 ...

  9. DZY Loves Colors

    CF #446C:http://codeforces.com/problemset/problem/444/C 题意:给你n个数,大小从1到n,然后又两种操作,1 a b c表示把区间a b 更新为c ...

  10. 2015第35周五JavaScript变量

    java语言里有一句很经典的话:在java的世界里,一切皆是对象. Javascript虽然跟java没有半点毛关系,但是很多会使用javascript的朋友同样认为:在javascript的世界里, ...