Linux内核参数详解


内核参数详解

长期更新


SYN_RECV

服务端收到sys,还未发出syn+ack
1.net.ipv4.tcp_synack_retries
默认值5,linux对应1+2+4+..32=2^6-1=63s

2.net.ipv4.tcp_syncookies
应该设置为1,防止SYN Flood。
处在SYN_RECV的TCP连接称为半连接,存储在SYN队列。大量SYN_RECV会导致队列溢出,后续请求将被内核直接丢弃,也就是SYN Flood攻击。
开启syncookies后,当SYN队列满了后,TCP会通过原地址端口,目的地址端口和时间戳打造一个特别的Sequence Number(又叫cookie)发回去,如果是攻击者则不会有响应,如果是正常连接则把这个SYNCookie发回来,然后服务器端可以通过cookie建立连接(即使不在SYN队列)。
别用tcp_syncookies来处理正常大负载连接,因为syncookies是妥协版的TCP协议,不严谨。对于正常的请求可调整三个TCP参数。
1.tcp_max_syn_backlog 减少重试次数
2.tcp_max_syn_backlog 增大syn连接数
3.tcp_abort_on_overflow 处理不过来拒绝连接

CLOSE_WAIT

被动关闭的一方收到FIN后发送ACK处于CLOSE_WAIT状态。出现这种状态比较多时,一般都是没有及时close()导致的,默认将持续2小时。

TIME_WAIT

主动关闭一方,socket将在TIME_WAIT等待2msl时间。
1.net.ipv4.tcp_fin_timeout
默认值60,TCP保持在FIN_WAIT2状态的时间,超时后直接处于CLOSED,所以降低tcp_fin_timeout有助于减少TIME_WAIT数量。注意:虽然shutdown(SHUD_WR)也会处于FIN_WAIT2状态,但超时并不起作用。

2.net.ipv4.tcp_tw_recycle
默认值0,打开快速TIME_WAIT socket回收。
如果tcp_timestamps开启的话,会缓存每个连接的最新时间戳,如果后续请求时间戳小于缓存的时间戳,即视为无效,相应的包被丢弃。所以如果是nat或负载均衡环境下,就可能出现数据包丢弃的现象。

3.net.ipv4.tcp_tw_resue
默认值0,是否重用TIME_WAIT状态的socket用于新的连接
这个选项要比tcp_tw_recycle安全,从协议的角度看,复用是安全的。
网上查找的复用条件:

1.tcp_timestamps选项必须打开(客户端也必须打开)
2.重用TIME_WAIT的条件是收到最后一个包后超过1s

4.net.ipv4.tcp_timestamps
默认值1,tcp增加时间戳,可避免序列号的环绕,更精确的RTT计算,为了更好的性能应该启用这个选项。

5.net.ipv4.tcp_max_tw_buckets
默认值180000,TIME_WAIT的上限。

TCP优化

1.net.ipv4.tcp_moderate_rcvbuf
默认值1,是否自动调节TCP接收缓冲区大小,当编程中设置了SO_SNDBUF,SO_RCVBUF将会使内核不对这些连接执行自动调节。
2. net.ipv4.tcp_adv_win_scale
默认值2,将拿出1/(2^tcp_adv_win_scale)缓存做应用读缓存,那么最大的接受滑动窗口只能到达读缓存的3/4。

3.net.ipv4.tcp_rmem
4096 87380 6291456
第一个是接受缓冲区最小字节
第二个是接受缓冲区长度初始值,用来初始化sock的sk_rcvbuf,将取代rmem_default
第三个是接受缓冲区长度最大值,用来调整sock的sk_rcvbuf

4.net.core.rmem_default
适用所有协议的默认接受窗口大小(字节)
接受窗口(rwnd)合理值取决于BDP(带宽和延迟的乘积),假设带宽100Mbps,延迟100ms
BDP= (100Mbps/8) * (100/1000) = 1.25M
由于有tcp_adv_win_scale额外开销,所以缓存的合理值为:
BDP/(1-1/(2^tcp_adv_win_scale))

5.net.ipv4.tcp_window_scaling
默认值1,是否启用windows scaling,若要支持超过64KB的窗口,必须启用。

6.net.ipv4.tcp_sack
默认值1,是否开启sack(selective ack),报告收到的数据碎片,解决快速重传不知道后续数据是否重传的问题。

拥塞窗口

拥塞窗口(cwnd)是发送端一个内部参数,用来避免网络拥塞,
通过慢启动快速增加cwnd,Linux2.6内核初始为3*MSS,为了提高传输效率,Linux3.0以后为10*MSS,可通过以下命令修改

[root@10-9-22-239 ~]# ip route show
default via 10.9.0.1 dev eth0 
10.9.0.0/16 dev eth0  proto kernel  scope link  src 10.9.22.239 
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1 
[root@10-9-22-239 ~]# ip route change default via 10.9.0.1 dev eth0 initcwnd 10
[root@10-9-22-239 ~]# ip route show
default via 10.9.0.1 dev eth0  initcwnd 10
10.9.0.0/16 dev eth0  proto kernel  scope link  src 10.9.22.239 
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1

Out of socket memory

原因

1.有很多孤儿(orphan)socket
2.tcp socket用尽了分配的内存
tcp socket使用page计数,linux默认4096bytes

getconf PAGESIZE

1./proc/net/ipv4/tcp_mem
365664 487552 731328
当使用小于365664 page时,kernel不对其进行干预
当使用超过487552 page时,kernel进入”memory pressure”
当tcp使用超过731328时,会报:Out of socket memory

2./proc/net/sockstat

sockets: used 307
TCP: inuse 13 orphan 0 tw 0 alloc 34 mem 6
UDP: inuse 6 mem 2
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

可通过对比tcp_mem查看当前socket内存状态。

孤儿(orphan)socket

1.FIN_WAIT1和LAST_ACK状态连接就是孤儿socket
2.FIN_WAIT2加入tw状态统计,而不是orphan socket
3.CLOSE_WAIT既不假如orphan统计也不加入tw统计

fs

1.fs.file-max
系统所能打开的最大文件数
fs.file-max代表系统级别能够打开的文件句柄,ulimit -n控制用户进程所能打开的数量
设置多少比较合适,建议:内存/10k

grep -r MemTotal /proc/meminfo | awk '{printf("%d",$2/10)}'

2.fs.file-nr 只读文件
1984 0 65535
第一个代表了目前分配的文件句柄数,第三个代表了系统分配的最大文件句柄数(同file-max)
file-nr一般会小于lsof | wc -l,但数量级是一致的。

vm

1.vm.dirty_background_ratio
默认值10
kdmflush守护进程负责同步所有与文件系统相关的页面至磁盘,当内存中的脏页面数量超过10%时kdmflush开始回写。

kswapd

kswapd守护进程负责确保内存保持可用空闲空间,它监控内核中pages_high和page_low标准,如果空闲内存空间小于pages_low,kswapd开始扫描并尝试每次回收32个页面,直到空闲内存大于pages_high。
kswapd执行以下操作:

1.假如页面未改变,它将该页面放入free list
2.假如页面改变且被文件系统回写,它将页面写入磁盘
2.假如页面改变且未被文件系统回写,它将页面写入swap设备

buff:供read()和write()使用的物理内存缓冲大小
cache:映射到进程地址空间的物理内存数

1.当大量的数据从磁盘读入内存(bi),cache值将不断增加
2.vmstat中swapd值不断增大,说明kswapd正将脏页面写入交换空间(so)
3.buff值不断减少,说明kswapd正不断回收内存

相关内容