标签 tcp/ip 下的文章
标签 tcp/ip 下的文章
主要是想跟大家分享一下对 Linux 内核报 Out of Socket memory 错误的相关研究,涉及几个内核参数的讲解:
cat /proc/net/sockstat
net.ipv4.tcp_mem = 4631232 6174976 9262464
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_orphan_retries = 0
------- 正文开始:------------------
举一个网上看到的例子:
一台 Nginx server,到晚上高峰 messages 出现大量的如下信息:
Apr 23 22:43:21 rs1 kernel: […] Out of socket memory
两种情况内核会出发 "Out of socket memory" 的信息:
有很多的孤儿套接字(orphan sockets) net.ipv4.tcp_max_orphans(常见)
tcp socket 用尽了内核所定义的内存限制 net.ipv4.tcp_mem(不常见)
在数据中心网络内,机器之间数据传输的往返时间(rtt)一般在10ms以内,为此调内部服务的超时时间一般会设置成50ms、200ms、500ms等,如果在传输过程中出现丢包,这样的服务超时时间,tcp层有机会发现并重传一次数据么?如果设置成200ms以内,答案是没有机会,原因是linux系统下第一次重传时间等于传输的往返时间上至少加上200ms的预测偏差值,即如果rtt值是7ms,第一次重传超时时间至少是207ms,这样如果对某个接口的超时时间设置成200ms以内, 即便是rtt时间很小,仍然无法容忍一次丢包,因为在tcp发现丢包之前,该接口已经超时了。
本文针对linux系统tcp数据包第一次重传时间的计算进行探究,结果会让人大吃一惊。提出的优化方法,理论上能够降低内部服务调用时延和出错量。
tcp发送数据包后,会设置一个定时器,到期后如果还没有收到对方的回复(ack),就会重传数据包。从发出数据包到第一次重传之间的间隔时间称为retransmission timeout(RTO),rto由数据包的往返时间(rtt)加上rtt的预测偏差(波动值)计算出来。
即 rto = srtt + rttvar,其中srtt是rtt的平滑值,而rttvar是波动值,代表可能的预测偏差。
接下来我们做一个试验。
先ping一下www.weibo.com,看一下数据包的往返时间,如下:
[xiaohong@localhost ~]$ ping www.weibo.com PING www.weibo.com (123.125.104.197) 56(84) bytes of data. 64 bytes from 123.125.104.197: icmp_seq=1 ttl=55 time=3.65 ms 64 bytes from 123.125.104.197: icmp_seq=2 ttl=55 time=3.38 ms 64 bytes from 123.125.104.197: icmp_seq=3 ttl=55 time=4.34 ms 64 bytes from 123.125.104.197: icmp_seq=4 ttl=55 time=7.82 ms
再看一下tcp对到www.weibo.com的rtt相关数据,下面的命令是针对centos7(如果是以下的版本,运行的命令是ip route list tab cache)如下:
[xiaohong@localhost ~]$ sudo ip tcp_metrics 123.125.104.197 age 22.255sec rtt 7375us rttvar 7250us cwnd 10
由上面看出,平滑后的rtt值约为7ms,rttvar约为7ms,那按理说rto值应该是14ms左右,也就是等14ms后,如果没有收到对方的响应,就会重传数据。实际的情况会是这样么?
在一个命令窗口里,运行下面的命令:
[xiaohong@localhost ~]$ nc www.weibo.com 80 GET / HTTP/1.1 Host: www.weibo.com Connection:
同时再开一个命令行窗口里,运行下面的命令:
[xiaohong@localhost iproute2-3.19.0]$ ss -eipn '( dport = :www )' tcp ESTAB 0 0 10.209.80.111:56486 123.125.104.197:80 users:(("nc",1713,3)) uid:1000 ino:14243 sk:ffff88002c992d00 <-> ts sack cubic wscale:0,7 rto:207 rtt:7.375/7.25 mss:1448 cwnd:10 send 15.7Mbps rcv_space:14600
从上面的结果可以看出,实际的rto值是207ms,相当于rtt值加上200ms,为什么呢?