参考截取一部分:
在linux下可以修改协议栈改变tcp缓冲相关参数:
修改系统套接字缓冲区
echo 65536 > /proc/sys/net/core/rmem_max
echo 256960 > /proc/sys/net/core/wmem_max
echo 65536 > /proc/sys/net/core/wmen_default
修改tcp接收/发送缓冲区
echo "4096 32768 65536" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 65536 256960" > /proc/sys/net/ipv4/tcp_wmem
修改网络设备接收队列
echo 500 > /proc/sys/net/core/netdev_max_backlog
重传次数
echo 5 > /proc/sys/net/ipv4/tcp_retries2
发现上面的参数都是改小了,既然大的时候视频比较卡,改小了会好么?首先一个问题是缓冲区越大越好么?如果机器处理不过来tcp流量,那么不管缓冲区有多大,早晚会溢出,这就导致,应用层知道的tcp未收到比较晚,因为在缓冲区里面呆了一段时间,而且重传的数据也较大,会早成网络负担比较大,其实看来并不利于整个网络。那么缓冲区改大有什么好去呢?缓冲区改大可以处理突发的大流量数据,不至于画面变化的时候,也就是流量突然增大的时候缓冲区满。那回来看这个问题,既然大的时候视频会卡,那么改小了,让应用层早点知道tcp没有收到而已,对整个网络也就是省了点流量,对实时视频是否卡影响不大,自己的分析,待验证。
如果怀疑是机器问题,或者是tcp配置问题,可以换一个机器(配置更好的)看看是不是处理不过来请求而造成的延迟,或者用wireshark抓包来统计流量。
以下来自网络,原始出处已经找不到。。
计算机需要多大内存?当然是越大越好了,这是用户的想法。但是计算机的设计者则必须在成本、实现难度、和取悦客户等几个因素之间进行折中,选取一个最佳平衡点。对计算机来说,其主要依据是产品的市场定位,高端商务PC至少配2G内存,低端学生机配256M就够了。如果用256M RAM的学生机来作复杂的大规模FPGA仿真,可能会发现硬盘的灯一直是亮的,这说明内存已经不够用了,操作系统正在不停的在内存和硬盘之间兑换数据,用大容量的低速硬盘来弥补内存太小的不足,但是代价是计算时间延长了很多倍。路由器是不是也向PC一样,主要依据售价来决定内存配置的大小呢?会不会也是内存越大越好呢?路由器的设计者依据哪些因素来决定内存配置的大小?一般来说,路由器的内存主要用于一下这些方面:
(1)用于存储路由器软件指令和静态数据,路由器跟PC不同,PC是只把当前运行的程序装到RAM中,但多数路由器都是一开机就把全部程序都装到 RAM中,一般来说,路由器的程序也不大(几兆到几十兆);(注:此处主要指控制平面的程序,也就是Cisco和Juniper的路由引擎)
(2)用于存储动态数据,例如:路由表、OSPF的链路状态数据库等。假如某路由器需要支持最多10万条路由,按照每条路由256字节计算,那么大约需要200M左右内存。
(3)用于缓冲数据报文,路由器的工作原理是存储转发。极端情况下,路由器的每个接口,至少需要缓冲一个报文,否则路由器根本不能工作。下面重点讨论这个问题。
一般来说,路由器配置的报文缓冲区都不止一个报文。因为这样也就意味着当有新报文到达的时候,如果前面一个报文正在发送,这个报文缓冲区尚未处于空闲状态,那么新的报文势必将会被丢掉。等前面一个报文发送完了,链路处于空闲状态,但是由于刚才报文已经被丢掉了,也无法利用链路空闲状态。如果被丢掉的报文是TCP报文,那么主机势必将重传这个报文(在该路由器前面的一段线路上传输两次同样的报文),并缩小自己的发送窗口,降低了TCP连接的速率。
也就是说,如果接口的报文缓冲区太小,将导致丢包率高,数据链路利用率低,TCP传输效率低。那么是不是报文缓冲区越大越好呢?也不是,因为报文缓冲区大到一定程度,就不能继续提高数据链路利用率和降低丢包率了。如果这台路由器处于拥塞状态,接收报文的速率远远大于接口的发送带宽,无论多大的报文缓冲区都会被填满,而报文缓冲区大了,那么也就意味着拥塞状态的时候,报文的转发延迟时间会很长。延迟时间太长的报文,对于接收方来说,已经没有意义了。以 TCP连接为例,当报文大于发送方的重传时间的时候,发送方就会重传该报文,也就是说,大于TCP的重传时间的到达的报文,是没有意义的。对VoIP等应用来说,对网络延时更加敏感。
一般来说,路由器的接口缓冲区的大小有一个经验法则(rule-of-thumb):B = C * RTT,C是链路速率,RTT是平均报文往返之间。至于这个经验法则源自哪里,我没有认真考证。但这个经验法则的主要依据是最大化TCP效率,最大化网络接口带宽利用率。如果依据这个法则来设计路由器,对中低端路由器来说,问题不大。但是对于高端路由器,是有挑战的。一般中高端Internet骨干路由器上会假设RTT为250ms,那么对于个 10GE接口,需要的内存是(10G bit/s * 0.25 s) / 8 约为300MB。也许大家会说,300M不大么,但是可以预见,最近两年核心路由器的容量必将发展到单槽位80 - 160G,也就是说单大约需要2.5G - 5G内存。虽然不是完全不可实现,但还是有一定难度。从 Juniper的一个白皮书(Characteristics of Switches and Routers)可以看出,Juniper也是按照这个经验法则设计的。
但是最近的一些研究认为(sizing router buffers, Guido Appenzler, Isaac Keslassy, Nick McKeown),其实路由器不需要那么大的内存,每个端口只需要缓冲几十个报文就足够了,这样用NP或ASIC内嵌的RAM就够了,不用配置外部RAM。他主要依据是以前的经验法则是根据单TCP流来推算的,作者认为这个模型不对,实际的骨干路由器上是有很多TCP流的,因此应该按照 B = C * RTT / sqrt(N)来计算,N是TCP流数量。但是另外一些研究则认为这个结论不对,路由器上不能只考虑TCP,还有很多急于 UDP的语音和视频应用。反正在教授们之间,这个问题至今仍然没有一致的意见。工程师已经不再争论这个问题了,就按照B = C * RTT来设计,成本可以接受,而且也比较安全。
为了纠正网络问题,有时候需要重新配置网卡的默认IP包大小。经常会发生路由的最大IP包大小比网卡的小。TCP协议可以自适应,但是UDP协议不行(会导致分片丢包,然后重传)。所以NFS over UDP特别要注意设置MTU的大小。可以用命令*tracepath*来看网络上的MTU值,用ifconfig命令来看网卡的MTU值,要使两者匹配。(大部分网络都是1500,除非设置了支持大包)时,IP包在用UDP协议传输时会分片。大量IP包分片会消耗网络两端大量的CPU资源,而且还会导致网络通信更不稳定(因为完整的RPC在UDP分片的任何一个包丢失时都得整个RPC重传)。在2.2和2.4内核中,默认的socket读缓存rmem_default是64k,写缓冲wmem_default是8k。这两个值对有大量读写负载的情况很重要。