精华内容
下载资源
问答
  • 内核参数
    千次阅读
    2022-04-24 19:46:31

    Linux优化内核参数
    修改/etc/sysctl.con

    fs.file-max = 1000000
    #表示单个进程较大可以打开的句柄数
    net.ipv4.tcp_tw_reuse = 1
    #参数设置为 1 ,表示允许将TIME_WAIT状态的socket重新用于新的TCP链接,这对于服务器来说意义重
    大,因为总有大量TIME_WAIT状态的链接存在
    net.ipv4.tcp_keepalive_time = 600
    #当keepalive启动时,TCP发送keepalive消息的频度;默认是2小时,将其设置为10分钟,可更快的清理无效链接
    net.ipv4.tcp_fin_timeout = 30
    #当服务器主动关闭链接时,socket保持在FIN_WAIT_2状态的较大时间
    net.ipv4.tcp_max_tw_buckets = 5000
    #表示操作系统允许TIME_WAIT套接字数量的较大值,如超过此值,TIME_WAIT套接字将立刻被清除并打印警告信息,默认为8000,过多的TIME_WAIT套接字会使Web服务器变慢
    net.ipv4.ip_local_port_range = 1024 65000
    #定义UDP和TCP链接的本地端口的取值范围
    net.ipv4.tcp_rmem = 10240 87380 12582912
    #定义了TCP接受缓存的最小值、默认值、较大值
    net.ipv4.tcp_wmem = 10240 87380 12582912
    #定义TCP发送缓存的最小值、默认值、较大值
    net.core.netdev_max_backlog = 8096
    #当网卡接收数据包的速度大于内核处理速度时,会有一个列队保存这些数据包。这个参数表示该列队的较大值
    net.core.rmem_default = 6291456
    #表示内核套接字接受缓存区默认大小
    net.core.wmem_default = 6291456
    #表示内核套接字发送缓存区默认大小
    net.core.rmem_max = 12582912
    #表示内核套接字接受缓存区较大大小
    net.core.wmem_max = 12582912
    #表示内核套接字发送缓存区较大大小
    注意:以上的四个参数,需要根据业务逻辑和实际的硬件成本来综合考虑
    net.ipv4.tcp_syncookies = 1
    #与性能无关。用于解决TCP的SYN攻击
    net.ipv4.tcp_max_syn_backlog = 8192
    #这个参数表示TCP三次握手建立阶段接受SYN请求列队的较大长度,默认1024,将其设置的大一些可使出现Nginx繁忙来不及accept新连接时,Linux不至于丢失客户端发起的链接请求
    net.ipv4.tcp_tw_recycle = 1
    #这个参数用于设置启用timewait快速回收
    net.core.somaxconn=262114
    #选项默认值是128,这个参数用于调节系统同时发起的TCP连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此需要结合高并发请求数来调节此值。
    net.ipv4.tcp_max_orphans=262114
    #选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤立链接将立即被复位并输出警告信息。这个限制指示为了防止简单的DOS攻击,不用过分依靠这个限制甚至认为的减小这个值,更多的情况是增加这个值。

    f

    更多相关内容
  • 1 内核参数的查看方法  使用“sysctl -a”命令可以查看所有正在使用的内核参数内核参数比较多(一般多达500项),按照前缀主要分为以下几大类:net.ipv4、net.ipv6、net.core、vm、fs、dev.parport、dev.cdrom ...
  • 通常一个配置文件对应一个内核参数,文件名是参数的名字,文件的内容是参数的值。 我们可以通过命令sysctl -a 查看所有这些内核参数。下面说明与网络编程关系较为紧密的部分内核参数。  一、 / proc/sys/fs 目录下...
  • linux内核参数.pdf

    2021-09-27 13:02:30
    linux内核参数.pdf
  • 2.1 设置主机名和hosts文件解析 2.2 安装依赖包 ...2.5 调整内核参数,对于 K8S 2.6 调整系统时区 2.7 关闭系统不需要服务 2.8 设置 rsyslogd 和 systemd journald 2.9 升级系统内核为 4.44 一键shell脚本
  • 关于cache怎么设置,linux系统内核设置优化tcp网络,另外可以参考优化内核配置
  • 由于Linux的内核参数信息都存在内存中,因此可以通过命令直接修改,并且修改后直接生效。但是,当系统重新启动后,原来设置的参数值就会丢失,而系统每次启动时都会自动去/etc/sysctl.conf文件中读取内核参数,因此...
  • 查看网络上大部分内核参数文档,整理出如下内容,如有错误请指正,过程很辛苦,转载请附上原地址。 前言 常用的Linux内核参数,具体优化值要参考应用场景。 通过/var/log/message查看系统日志或dmesg命令查看开机...

    查看网络上大部分内核参数文档,整理出如下内容,如有错误请指正,过程很辛苦,转载请附上原地址。

    前言

    常用的Linux内核参数,具体优化值要参考应用场景。

    通过/var/log/message查看系统日志或dmesg命令查看开机信息,对相应信息做系统参数调优;还可根据TCP状态进行TCP相关参数调优。

    以CentOS7,内核版本3.10的服务器为例。

    针对系统

    配置在/etc/sysctl.conf中,可通过命令sysctl -a查看内核参数。

    全局参数

    文件句柄

    fs.file-max

    表示系统级别的能够打开的文件句柄的数量,直接限制最大并发连接数。是对整个系统的限制,并不是针对用户的。

    系统当前打开的文件描述符个数:cat /proc/sys/fs/file-nr。

    file-nr中的三个值表示已分配的文件句柄数、已分配但未使用的文件句柄数(Linux 2.6总是将0报告为可用文件句柄数)以及最大文件句柄数(等于file-max)。

    默认值:在系统启动时,根据内存计算得出。

    参考值:一般为内存大小(KB)的10%来计算:grep -r MemTotal /proc/meminfo | awk  '{printf("%d",$2/10)}'

    fs.nr_open

    单进程能够打开的最大文件句柄数。

    使用cat /proc/sys/fs/nr_open查看。

    默认值:1048576(1024*1024)

    参考值:默认值足够使用,根据实际高并发连接数修改。

    net.core.somaxconn

    调节系统同时发起的TCP连接数。高并发情况下,该值越小,越容易出现超时情况。

    TCP 建立连接时要经过3次握手。对于服务器而言,一个完整的连接建立过程,服务器会经历2种 TCP 状态:SYN_REVD,ESTABELLISHED。

    一个存放SYN_REVD状态的队列(半连接队列);一个存放ESTABELLISHED状态的队列(全连接队列)。后端应用程序会从全连接队列获取请求。

    如果服务器需要处理高并发,需要修改这2个队列大小,也就是需要同时设置应用层的backlog及内核参数somaxconntcp_max_syn_backlog来满足高并发要求。

    半连接队列长度 = min(backlog, net.core.somaxconn, tcp_max_syn_backlog)

    全连接队列长度 = min(backlog, net.core.somaxconn)

    backlog

    服务器端TCP的ESTABELLISHED状态对应的全连接队列长度。

    在Tomcat里是Connector中的acceptCount(默认值为128)。

    在Nginx(默认值为511)里是

    server{

        listen  8080  default_server  backlog=1024;

    }

    backlog <= somaxconn

    查看一个程序最终生效的accept队列的大小:ss -tnl输出结果中当处于listen状态时Send-Q的值即为accept队列大小。

    somaxconn和tcp_max_syn_backlog区别:

    tcp_max_syn_backlog是半连接上限,例如场地容纳多少人,net.ipv4.tcp_syncookies = 1时该参数无效;

    somaxconn是全连接上限,例如场地仅有多少个座位。

    默认值:128

    参考值:262144

    相关技术参考:

    https://www.cnblogs.com/grey-wolf/p/10999342.html

    https://jaminzhang.github.io/linux/understand-Linux-backlog-and-somaxconn-kernel-arguments/

    https://blog.51cto.com/wujianwei/2104779

    套接字缓存

    net.core.netdev_max_backlog

    当每个网络接口接受数据包的速率比内核处理速率快时,允许发送到队列的数据包的最大数。

    内核从网卡收到数据包后,交由协议栈(如IP、TCP)处理之前的缓冲队列。每个CPU核都有一个backlog队列,当协议栈处理速度满足不了接收包速率时会发生丢包。

    查看数据处理情况:cat /proc/net/softnet_stat

    每一行代表一个CPU。

    第一列为该CPU所接收到的所有数据包。

    第二列为该CPU缺省queue满的时候,所删除的包的个数。如果该列有数据,则通过net.core.netdev_max_backlog调整。

    第三列表示time_squeeze,一次的软中断的触发还不能处理完目前已经接收的数据,因而要设置下轮软中断,time_squeeze 就表示设置的次数。

    第四至八列固定为0,没有意义。

    第九列表示发送数据包时,对应的队列被锁住的次数。

    最后一列,该CPU向其它CPU发送的ipi中断个数。

    默认值:1000

    参考值:262144

    相关技术参考:

    https://blog.csdn.net/zgy666/article/details/104391160

    https://www.lmlphp.com/user/57878/article/item/707848/

    net.core.rmem_default

    内核接收套接字缓冲区大小的缺省值(以字节为单位),包括TCP、UDP等。

    应用程序通过socket系统调用和远程主机进行通讯,每一个socket都有一个读写缓冲区。

    读缓冲区保存了远程主机发送过来的数据,如果读缓冲区已满,则数据会被丢弃。

    查看socket状态:cat /proc/net/sockstat,根据所有套接字使用量配置。

    sockets: used:已使用的所有协议套接字总量

    TCP: inuse:正在使用(正在侦听)的TCP套接字数量。其值 <= netstat -lnt | grep ^tcp | wc -l

    TCP: orphan:无主(不属于任何进程)的TCP连接数(无用、待销毁的TCP socket数)

    TCP: tw:等待关闭的TCP连接数。其值等于netstat -ant | grep TIME_WAIT | wc -l

    TCP: alloc:已分配的TCP套接字数量。其值等于netstat -ant | grep ^tcp | wc -l

    TCP: mem:套接字缓冲区使用量,单位未查到。

    UDP: inuse:正在使用的UDP套接字数量

    FRAG:使用的IP段数量

    默认值:212992

    参考值:需要根据业务逻辑和实际的硬件成本来综合考虑。

    相关技术参考:

    https://zhuanlan.zhihu.com/p/426388054

    https://www.cnblogs.com/zengkefu/p/5749009.html

    http://www.2cto.com/os/201307/230154.html

    https://www.sudops.com/linux-kernel-tcp-ip-sysctl-optimize.html

    net.core.wmem_default

    内核发送套接字缓冲区大小的缺省值(以字节为单位)。

    写缓冲期保存了要发送到远程主机的数据,如果写缓冲区已满,则应用程序在写入数据时会阻塞。

    wmem_default高于tcp_wmem。

    默认值:212992

    参考值:同rmem_default

    net.core.rmem_max

    内核接收套接字缓冲区大小的最大值(以字节为单位)。

    通过dmesg命令查看,发现大量TCP: too many of orphaned sockets或out of socket memory错误或提示consider tuning tcp_mem时,需要调优。

    cat /proc/net/sockstat 查看套接字使用情况,根据所有套接字使用量配置。

    默认值:212992

    参考值:需要根据业务逻辑和实际的硬件成本来综合考虑。

    net.core.wmem_max

    内核发送套接字缓冲区大小的最大值(以字节为单位)。用来限制监听(LISTEN)队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制。

    默认值:212992

    参考值:同rmem_max。

    TCP参数

    TCP套接字缓存

    net.ipv4.tcp_mem

    系统全局参数,所有TCP socket的buffer配置(以内存页为单位,页大小:getconf PAGE_SIZE)。

    假设一个page大小是4K,设置的page数 * 4k即是内存数值。

    如net.ipv4.tcp_mem = 378864 505153 757728,那么对应的内存分配就是:1480M 1973M 2960M。

    通过dmesg命令查看,发现大量TCP: too many of orphaned sockets或out of socket memory错误或提示consider tuning tcp_mem时,需要调优。

    根据cat /proc/net/sockstat(套接字状态)和netstat -an|awk '{print $NF}' | sort | uniq -c | sort -nr | head -10TCP连接状态)结果,调整相应的值。

    调整tcp前,必须调整core,不能超出core的限制

    low:内存使用的下限。当TCP使用了低于该值时,TCP不会考虑释放内存。

    pressure:内存压力模式开始对缓冲区使用应用压力的上限。当TCP使用了超过该值时,TCP试图稳定内存使用。

    high:内存上限。如果超过该值,系统拒绝分配socket,抛出“out of socket memory”。

    默认值:根据机器自身内存情况进行分配。

    参考值:

    pressure = 每个连接占用大小 * 最大并发量 / 页大小

    high = pressure * 1.5

    相关技术参考:

    https://www.cnblogs.com/51core/articles/13683820.html

    https://www.cnblogs.com/huanxiyun/articles/7521694.html

    net.ipv4.tcp_wmem

    TCP发送套接字缓存的内存最小值、默认值、最大值(以字节为单位),缓存应用程序的数据,被确认的数据会从发送缓冲区删除掉。

    最小值:为TCP socket预留用于发送缓冲的内存最小值。

    默认值:为TCP socket预留用于发送缓冲的内存数量,该值会覆盖net.core.wmem_default,一般要低于net.core.wmem_default。

    最大值:用于TCP socket发送缓冲的内存最大值,不会覆盖net.core.wmem_max

    默认值:4096 16384 [介于64K和4MB之间,具体取决于RAM大小]

    参考值:

    默认值 = 最大页面大小 * 最大并发量

    最大值(字节) = 带宽(Mebibites) * 延时(s) / 8 * 2^20,如带宽为1.5M,延时500ms,则tcp_wmem = 1.5 * 0.5 / 8 * 2^20 = 1048576

    或者最大值 = 默认值 * 2

    相关技术参考:

    http://www.2cto.com/os/201307/230154.html

    net.ipv4.tcp_rmem

    TCP接收套接字缓存的内存最小值、默认值、最大值(以字节为单位),缓存从对端接收的数据,后续会被应用程序读取。

    默认值会覆盖net.core.rmem_default。

    最大值最好是默认值的两倍,不会覆盖net.core.rmem_max。

    默认值:4096 87380 [介于87380字节和6MB之间,取决RAM大小]

    参考值:同tcp_wmem

    TCP建立连接

    net.ipv4.tcp_max_syn_backlog

    记录尚未收到客户端确认信息的连接请求的最大值(三次握手建立阶段接受SYN请求,半连接队列)。设置大一些可使出现Nginx繁忙来不及接收新连接时,Linux不至于丢失客户端发起的链接请求。

    net.ipv4.tcp_syncookies = 1时该参数无效。

    默认值:1024

    参考值:262144

    相关技术参考:

    https://www.cnblogs.com/lpfuture/p/12090045.html

    net.ipv4.tcp_syn_retries

    设置内核放弃建立连接之前向客户端发送SYN包的数据,即客户端发起SYN连接,如果超时会进行重传的次数。

    默认值:6,不应高于127

    参考值:对于大负载而物理通信良好的网络而言,可修改为2。

    相关技术参考:

    https://blog.csdn.net/bytxl/article/details/46437363

    net.ipv4.tcp_syncookies

    当半连接的请求数量超过了tcp_max_syn_backlog时,内核就会启用SYN cookie机制,不再把半连接请求放到队列里,而是用SYN cookie来检验,可防范部分 SYN 攻击。

    但开启后会使用 SHA1 验证 Cookies,理论上会增大 CPU 使用率。

    该选项千万不能用于那些没有收到攻击的高负载服务器,如果在日志中出现syn flood消息,但是调查发现没有收到syn flood攻击,而是合法用户的连接负载过高的原因,你应该调整以下参数来提高服务器性能:tcp_max_syn_backlog、tcp_synack_retries、tcp_abort_on_overflow。

    默认值:0

    参考值:1

    net.ipv4.tcp_synack_retries

    设置内核放弃TCP连接之前向客户端发送SYN+ACK包的数据(三次握手中的第二次握手)。当为1时,内核在放弃连接之前再发送一次SYN+ACK包。

    默认值:5

    参考值:1,根据tcp_syn_retries决定该值。

    TCP关闭连接

    net.ipv4.tcp_max_orphans

    设定系统中最多允许存在多少TCP套接字不被关联到任何一个用户文件句柄上。为了防止简单的DOS攻击。如果超过这个数字,孤立链接将立即被复位并输出警告信息。

    主动关闭端发送了FIN后转到FIN_WAIT_1,这时TCP连接就不属于某个进程了。每个孤儿(orphan)套接字最多能吃掉64K不可交互的内存。

    默认值:8192

    参考值:根据cat /proc/net/sockstatorphan的值,来判断是否需要调整。

    相关技术参考:

    https://www.sudops.com/debian-kernel-socket-memory.html

    net.ipv4.tcp_orphan_retries

    控制主动关闭端发送FIN,没有收到回应,重复发送FIN的次数。由于发送了FIN,处于FIN_WAIT_1状态。

    如果设置为0,则socket会永远停留在FIN_WAIT_1这个状态。

    默认值:8

    参考值:如果系统是负载很大的web服务器﹐那么也许需要降低该值,参考值为3

    net.ipv4.tcp_fin_timeout

    如果socket由服务端要求关闭,则该参数决定了保持在FIN-WAIT-2状态的时间,即指定孤儿连接在内核中生存的时间。

    默认值:60

    参考值:30

    net.ipv4.tcp_max_tw_buckets

    timewait的数量,最大值为262144。如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。

    建议减小,避免TIME_WAIT状态过多消耗整个服务器的资源,但也不能太小,跟后端的处理速度有关,如果速度快可以小,速度慢则适当加大,否则高负载会有请求无法响应或非常慢。

    默认值:180000

    参考值:6000

    net.ipv4.tcp_tw_recycle

    TCP连接中TIME-WAIT的sockets快速回收功能。同时开启的话,缓存每个连接最新的时间戳,若后续的请求中时间戳小于缓存的时间戳时,该请求会被视为无效,导致数据包会被丢弃。

    默认值:0

    参考值:0,需要结合配置net.ipv4.tcp_timestamps = 0

    net.ipv4.tcp_tw_reuse

    允许将TIME-WAIT状态的sockets重新用于新的TCP连接,Nginx反向代理服务器(服务器即做客户端,也做server端时)

    默认值:0

    参考值:1,需要结合配置net.ipv4.tcp_timestamps = 1

    net.ipv4.tcp_timestamps

    设置时间戳,避免序列号的卷绕。

    默认值:1

    参考值:结合tcp_tw_recycle和tcp_tw_reuse使用。

    net.ipv4.tcp_retries1

    放弃回应一个TCP连接请求前,需要进行多少次重试。

    默认值:3

    参考值:3

    net.ipv4.tcp_retries2

    在丢弃激活的TCP连接(已建立通讯状态)之前,需要进行多少次重试。

    默认值:15

    参考值:5

    TCP其他参数

    net.ipv4.ip_local_port_range

    放大本地端口范围。

    默认值:32768 61000

    参考值:15000 65000

    net.ipv4.tcp_keepalive_*

    由3个参数共同控制,表示某个TCP连接在空闲7200秒后,内核才发起探测,探测9次(每次75秒)不成功,内核才发送RST。清理无效链接。

    默认值:

    net.ipv4.tcp_keepalive_intvl = 75

    net.ipv4.tcp_keepalive_probes = 9

    net.ipv4.tcp_keepalive_time = 7200

    参考值:

    net.ipv4.tcp_keepalive_intvl = 15

    net.ipv4.tcp_keepalive_probes = 3

    net.ipv4.tcp_keepalive_time = 600 

    针对用户(进程)

    文件描述符

    表示任何一个用户可以打开的最大的文件描述符数量。

    使用ulimit -n查看的是soft nofile值;使用ulimit -Hn查看的是hard nofile值。

    默认值:1024

    参考值:hard值不能大于/proc/sys/fs/nr_opensoft值不高于hard

    * soft nofile 65535

    * hard nofile 65535

    相关技术参考:

    https://www.jianshu.com/p/47336fcd22da

    用户进程

    表示任何一个用户可以打开的最大的进程数。

    参考值:

    * soft nproc 65535

    * hard nproc 65535

    配置方式

    修改/proc下内核参数文件内容

    由于内核随时可能更改这些文件中的任意一个,因此不能使用编辑器进行编辑,而是使用echo命令输出重定向至 /proc 下所选定的文件中。

    但是重启系统后,该参数又恢复成默认值。

    #将 timeout_timewait 参数设置为30秒:
    echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

    修改/etc/sysctl.conf文件

    修改针对系统的内核参数,把参数添加或修改到/etc/sysctl.conf中,然后执行/sbin/sysctl -p使参数生效。

    修改/etc/security/limits.conf文件

    修改针对用户的内核参数,把参数添加或修改到/etc/security/limits.conf中,重新登录即生效。

    展开全文
  • linux查看sysctl内核参数

    千次阅读 2021-05-10 04:06:42
    查看sysctl内核参数:backlog ,somaxconn,file-max 和 nginx的backlog配置参数,ss -ln取最小值,发现为128,此时resv-q已经在129 ,请求被丢弃。将上述参数修改,并进行优化:检查sysctl内核参数:backlog,...

    查看sysctl内核参数:backlog ,somaxconn,file-max 和 nginx的backlog配置参数,ss -ln取最小值,发现为128,此时resv-q已经在129 ,请求被丢弃。将上述参数修改,并进行优化:

    检查sysctl内核参数:backlog,somaxconn,file-max 和 应用程序的backlog

    worker_processes与worker_connections 设置好合适大小,可以提示nginx处理性能,非常重要。

    原作者的话:

    As a general rule you need the only worker with large number of worker_connections, say 10,000 or 20,000.

    However, if nginx does CPU-intensive work as SSL or gzipping and you have 2 or more CPU, then you may

    set worker_processes to be equal to CPU number.

    Besides, if you serve many static files and the total size of the files is bigger than memory, then you may

    increase worker_processes to utilize a full disk bandwidth.

    Igor Sysoev

    翻译:

    一般一个进程足够了,你可以把连接数设得很大。(worker_processes: 1,worker_connections: 10,000)

    如果有SSL、gzip这些比较消耗CPU的工作,而且是多核CPU的话,可以设为和CPU的数量一样。(worker_processes: CPU核心数)

    或者要处理很多很多的小文件,而且文件总大小比内存大很多的时候,也可以把进程数增加,以充分利用IO带宽(主要似乎是IO操作有block)

    worker_processes,工作进程数

    1.默认:worker_processes: 1

    2.调大:worker_processes: CPU核心数,(双核4线程,可以设置为4)

    worker_connections,单个工作进程可以允许同时建立外部连接的数量

    数字越大,能同时处理的连接越多

    1.默认:worker_connections: 1024

    2.调大:worker_connections: 100000,(调大到10万连接)

    worker_connections解析

    1.connections不是随便设置的,而是与两个指标有重要关联,一是内存,二是操作系统级别的“进程最大可打开文件数”。

    2.内存:每个连接数分别对应一个read_event、一个write_event事件,一个连接数大概占用232字节,2个事件总占用96字节,那么一个连接总共占用328字节,通过数学公式可以算出100000个连接数大概会占用 31M = 100000 * 328 / 1024 / 1024,当然这只是nginx启动时,connections连接数所占用的nginx。

    3.进程最大可打开文件数:进程最大可打开文件数受限于操作系统,可通过 ulimit -n 命令查询,以前是1024,现在是65535,

    nginx提供了worker_rlimit_nofile指令,这是除了ulimit的一种设置可用的描述符的方式。 该指令与使用ulimit对用户的设置是同样的效果。此指令的值将覆盖ulimit的值,如:worker_rlimit_nofile 20960;

    设置ulimits:ulimit -SHn 65535

    worker_processes 2;

    worker_rlimit_nofile 65535;

    #pid logs/nginx.pid;

    events {

    worker_connections 65535;

    }

    1

    2

    3

    4

    5

    6

    通过 ps -elf | grep nginx 找到 nginx 的worker进程ID

    通过 cat /proc/31613/limits 查看,其中2291是worker进程ID,请注意其中的Max open files

    5befdc285ca0d7a2f6e2853a30c36897.png

    从上面的分析可以看出nginx占用内存小,处理性能高,通过提高服务器的配置,Nginx可以应对更大的连接数

    喜欢 (0)or分享 (0)

    bc2536a386bdad0f3a5b1b723479c3dc.png

    展开全文
  • 细说 TCP 内核参数

    万次阅读 多人点赞 2020-06-08 19:57:15
    TCP 性能的提升不仅考察 TCP 的理论知识,还考察了对于操心系统提供的内核参数的理解与应用。

    前言

    TCP 性能的提升不仅考察 TCP 的理论知识,还考察了对于操作系统提供的内核参数的理解与应用。

    TCP 协议是由操作系统实现,所以操作系统提供了不少调节 TCP 的参数。

    Linux TCP 参数

    如何正确有效的使用这些参数,来提高 TCP 性能是一个不那么简单事情。我们需要针对 TCP 每个阶段的问题来对症下药,而不是病急乱投医。

    接下来,将以三个角度来阐述提升 TCP 的策略,分别是:

    • TCP 三次握手的性能提升;
    • TCP 四次挥手的性能提升;
    • TCP 数据传输的性能提升;

    本节提纲


    正文

    01 TCP 三次握手的性能提升

    TCP 是面向连接的、可靠的、双向传输的传输层通信协议,所以在传输数据之前需要经过三次握手才能建立连接。

    三次握手与数据传输

    那么,三次握手的过程在一个 HTTP 请求的平均时间占比 10% 以上,在网络状态不佳、高并发或者遭遇 SYN 攻击等场景中,如果不能有效正确的调节三次握手中的参数,就会对性能产生很多的影响。

    如何正确有效的使用这些参数,来提高 TCP 三次握手的性能,这就需要理解「三次握手的状态变迁」,这样当出现问题时,先用 netstat 命令查看是哪个握手阶段出现了问题,再来对症下药,而不是病急乱投医。

    TCP 三次握手的状态变迁

    客户端和服务端都可以针对三次握手优化性能。主动发起连接的客户端优化相对简单些,而服务端需要监听端口,属于被动连接方,其间保持许多的中间状态,优化方法相对复杂一些。

    所以,客户端(主动发起连接方)和服务端(被动连接方)优化的方式是不同的,接下来分别针对客户端和服务端优化。

    客户端优化

    三次握手建立连接的首要目的是「同步序列号」。

    只有同步了序列号才有可靠传输,TCP 许多特性都依赖于序列号实现,比如流量控制、丢包重传等,这也是三次握手中的报文称为 SYN 的原因,SYN 的全称就叫 Synchronize Sequence Numbers(同步序列号)。

    TCP 头部

    SYN_SENT 状态的优化

    客户端作为主动发起连接方,首先它将发送 SYN 包,于是客户端的连接就会处于 SYN_SENT 状态。

    客户端在等待服务端回复的 ACK 报文,正常情况下,服务器会在几毫秒内返回 SYN+ACK ,但如果客户端长时间没有收到 SYN+ACK 报文,则会重发 SYN 包,重发的次数由 tcp_syn_retries 参数控制,默认是 5 次:

    通常,第一次超时重传是在 1 秒后,第二次超时重传是在 2 秒,第三次超时重传是在 4 秒后,第四次超时重传是在 8 秒后,第五次是在超时重传 16 秒后。没错,每次超时的时间是上一次的 2 倍

    当第五次超时重传后,会继续等待 32 秒,如果服务端仍然没有回应 ACK,客户端就会终止三次握手。

    所以,总耗时是 1+2+4+8+16+32=63 秒,大约 1 分钟左右。

    SYN 超时重传

    你可以根据网络的稳定性和目标服务器的繁忙程度修改 SYN 的重传次数,调整客户端的三次握手时间上限。比如内网中通讯时,就可以适当调低重试次数,尽快把错误暴露给应用程序。

    服务端优化

    当服务端收到 SYN 包后,服务端会立马回复 SYN+ACK 包,表明确认收到了客户端的序列号,同时也把自己的序列号发给对方。

    此时,服务端出现了新连接,状态是 SYN_RCV。在这个状态下,Linux 内核就会建立一个「半连接队列」来维护「未完成」的握手信息,当半连接队列溢出后,服务端就无法再建立新的连接。

    半连接队列与全连接队列

    SYN 攻击,攻击的是就是这个半连接队列。

    如何查看由于 SYN 半连接队列已满,而被丢弃连接的情况?

    我们可以通过该 netstat -s 命令给出的统计结果中, 可以得到由于半连接队列已满,引发的失败次数:

    上面输出的数值是累计值,表示共有多少个 TCP 连接因为半连接队列溢出而被丢弃。隔几秒执行几次,如果有上升的趋势,说明当前存在半连接队列溢出的现象

    如何调整 SYN 半连接队列大小?

    要想增大半连接队列,不能只单纯增大 tcp_max_syn_backlog 的值,还需一同增大 somaxconn 和 backlog,也就是增大 accept 队列。否则,只单纯增大 tcp_max_syn_backlog 是无效的。

    增大 tcp_max_syn_backlog 和 somaxconn 的方法是修改 Linux 内核参数:

    增大 backlog 的方式,每个 Web 服务都不同,比如 Nginx 增大 backlog 的方法如下:

    最后,改变了如上这些参数后,要重启 Nginx 服务,因为 SYN 半连接队列和 accept 队列都是在 listen() 初始化的。

    如果 SYN 半连接队列已满,只能丢弃连接吗?

    并不是这样,开启 syncookies 功能就可以在不使用 SYN 半连接队列的情况下成功建立连接

    syncookies 的工作原理:服务器根据当前状态计算出一个值,放在己方发出的 SYN+ACK 报文中发出,当客户端返回 ACK 报文时,取出该值验证,如果合法,就认为连接建立成功,如下图所示。

    开启 syncookies 功能

    syncookies 参数主要有以下三个值:

    • 0 值,表示关闭该功能;
    • 1 值,表示仅当 SYN 半连接队列放不下时,再启用它;
    • 2 值,表示无条件开启功能;

    那么在应对 SYN 攻击时,只需要设置为 1 即可:

    SYN_RCV 状态的优化

    当客户端接收到服务器发来的 SYN+ACK 报文后,就会回复 ACK 给服务器,同时客户端连接状态从 SYN_SENT 转换为 ESTABLISHED,表示连接建立成功。

    服务器端连接成功建立的时间还要再往后,等到服务端收到客户端的 ACK 后,服务端的连接状态才变为 ESTABLISHED。

    如果服务器没有收到 ACK,就会重发 SYN+ACK 报文,同时一直处于 SYN_RCV 状态。

    当网络繁忙、不稳定时,报文丢失就会变严重,此时应该调大重发次数。反之则可以调小重发次数。修改重发次数的方法是,调整 tcp_synack_retries 参数

    tcp_synack_retries 的默认重试次数是 5 次,与客户端重传 SYN 类似,它的重传会经历 1、2、4、8、16 秒,最后一次重传后会继续等待 32 秒,如果服务端仍然没有收到 ACK,才会关闭连接,故共需要等待 63 秒。

    服务器收到 ACK 后连接建立成功,此时,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。

    如果进程不能及时地调用 accept 函数,就会造成 accept 队列(也称全连接队列)溢出,最终导致建立好的 TCP 连接被丢弃。

     accept 队列溢出

    accept 队列已满,只能丢弃连接吗?

    丢弃连接只是 Linux 的默认行为,我们还可以选择向客户端发送 RST 复位报文,告诉客户端连接已经建立失败。打开这一功能需要将 tcp_abort_on_overflow 参数设置为 1。

    tcp_abort_on_overflow 共有两个值分别是 0 和 1,其分别表示:

    • 0 :如果 accept 队列满了,那么 server 扔掉 client 发过来的 ack ;
    • 1 :如果 accept 队列满了,server 发送一个 RST 包给 client,表示废掉这个握手过程和这个连接;

    如果要想知道客户端连接不上服务端,是不是服务端 TCP 全连接队列满的原因,那么可以把 tcp_abort_on_overflow 设置为 1,这时如果在客户端异常中可以看到很多 connection reset by peer 的错误,那么就可以证明是由于服务端 TCP 全连接队列溢出的问题。

    通常情况下,应当把 tcp_abort_on_overflow 设置为 0,因为这样更有利于应对突发流量。

    举个例子,当 accept 队列满导致服务器丢掉了 ACK,与此同时,客户端的连接状态却是 ESTABLISHED,客户端进程就在建立好的连接上发送请求。只要服务器没有为请求回复 ACK,客户端的请求就会被多次「重发」。如果服务器上的进程只是短暂的繁忙造成 accept 队列满,那么当 accept 队列有空位时,再次接收到的请求报文由于含有 ACK,仍然会触发服务器端成功建立连接。

    tcp_abort_on_overflow 为 0 可以应对突发流量

    所以,tcp_abort_on_overflow 设为 0 可以提高连接建立的成功率,只有你非常肯定 TCP 全连接队列会长期溢出时,才能设置为 1 以尽快通知客户端。

    如何调整 accept 队列的长度呢?

    accept 队列的长度取决于 somaxconn 和 backlog 之间的最小值,也就是 min(somaxconn, backlog),其中:

    • somaxconn 是 Linux 内核的参数,默认值是 128,可以通过 net.core.somaxconn 来设置其值;
    • backlog 是 listen(int sockfd, int backlog) 函数中的 backlog 大小;

    Tomcat、Nginx、Apache 常见的 Web 服务的 backlog 默认值都是 511。

    如何查看服务端进程 accept 队列的长度?

    可以通过 ss -ltn 命令查看:

    • Recv-Q:当前 accept 队列的大小,也就是当前已完成三次握手并等待服务端 accept() 的 TCP 连接;
    • Send-Q:accept 队列最大长度,上面的输出结果说明监听 8088 端口的 TCP 服务,accept 队列的最大长度为 128;

    如何查看由于 accept 连接队列已满,而被丢弃的连接?

    当超过了 accept 连接队列,服务端则会丢掉后续进来的 TCP 连接,丢掉的 TCP 连接的个数会被统计起来,我们可以使用 netstat -s 命令来查看:

    上面看到的 41150 times ,表示 accept 队列溢出的次数,注意这个是累计值。可以隔几秒钟执行下,如果这个数字一直在增加的话,说明 accept 连接队列偶尔满了。

    如果持续不断地有连接因为 accept 队列溢出被丢弃,就应该调大 backlog 以及 somaxconn 参数。

    如何绕过三次握手?

    以上我们只是在对三次握手的过程进行优化,接下来我们看看如何绕过三次握手发送数据。

    三次握手建立连接造成的后果就是,HTTP 请求必须在一个 RTT(从客户端到服务器一个往返的时间)后才能发送。

    常规 HTTP 请求

    在 Linux 3.7 内核版本之后,提供了 TCP Fast Open 功能,这个功能可以减少 TCP 连接建立的时延。

    接下来说说,TCP Fast Open 功能的工作方式。

    开启 TCP Fast Open 功能

    在客户端首次建立连接时的过程:

    1. 客户端发送 SYN 报文,该报文包含 Fast Open 选项,且该选项的 Cookie 为空,这表明客户端请求 Fast Open Cookie;
    2. 支持 TCP Fast Open 的服务器生成 Cookie,并将其置于 SYN-ACK 数据包中的 Fast Open 选项以发回客户端;
    3. 客户端收到 SYN-ACK 后,本地缓存 Fast Open 选项中的 Cookie。

    所以,第一次发起 HTTP GET 请求的时候,还是需要正常的三次握手流程。

    之后,如果客户端再次向服务器建立连接时的过程:

    1. 客户端发送 SYN 报文,该报文包含「数据」(对于非 TFO 的普通 TCP 握手过程,SYN 报文中不包含「数据」)以及此前记录的 Cookie;
    2. 支持 TCP Fast Open 的服务器会对收到 Cookie 进行校验:如果 Cookie 有效,服务器将在 SYN-ACK 报文中对 SYN 和「数据」进行确认,服务器随后将「数据」递送至相应的应用程序;如果 Cookie 无效,服务器将丢弃 SYN 报文中包含的「数据」,且其随后发出的 SYN-ACK 报文将只确认 SYN 的对应序列号;
    3. 如果服务器接受了 SYN 报文中的「数据」,服务器可在握手完成之前发送「数据」,这就减少了握手带来的 1 个 RTT 的时间消耗
    4. 客户端将发送 ACK 确认服务器发回的 SYN 以及「数据」,但如果客户端在初始的 SYN 报文中发送的「数据」没有被确认,则客户端将重新发送「数据」;
    5. 此后的 TCP 连接的数据传输过程和非 TFO 的正常情况一致。

    所以,之后发起 HTTP GET 请求的时候,可以绕过三次握手,这就减少了握手带来的 1 个 RTT 的时间消耗。

    开启了 TFO 功能,cookie 的值是存放到 TCP option 字段里的:

    TCP option 字段 - TFO

    注:客户端在请求并存储了 Fast Open Cookie 之后,可以不断重复 TCP Fast Open 直至服务器认为 Cookie 无效(通常为过期)。

    Linux 下怎么打开 TCP Fast Open 功能呢?

    在 Linux 系统中,可以通过设置 tcp_fastopn 内核参数,来打开 Fast Open 功能

    tcp_fastopn 各个值的意义:

    • 0 关闭
    • 1 作为客户端使用 Fast Open 功能
    • 2 作为服务端使用 Fast Open 功能
    • 3 无论作为客户端还是服务器,都可以使用 Fast Open 功能

    TCP Fast Open 功能需要客户端和服务端同时支持,才有效果。

    小结

    本小结主要介绍了关于优化 TCP 三次握手的几个 TCP 参数。

    三次握手优化策略

    客户端的优化

    当客户端发起 SYN 包时,可以通过 tcp_syn_retries 控制其重传的次数。

    服务端的优化

    当服务端 SYN 半连接队列溢出后,会导致后续连接被丢弃,可以通过 netstat -s 观察半连接队列溢出的情况,如果 SYN 半连接队列溢出情况比较严重,可以通过 tcp_max_syn_backlog、somaxconn、backlog 参数来调整 SYN 半连接队列的大小。

    服务端回复 SYN+ACK 的重传次数由 tcp_synack_retries 参数控制。如果遭受 SYN 攻击,应把 tcp_syncookies 参数设置为 1,表示仅在 SYN 队列满后开启 syncookie 功能,可以保证正常的连接成功建立。

    服务端收到客户端返回的 ACK,会把连接移入 accpet 队列,等待进行调用 accpet() 函数取出连接。

    可以通过 ss -lnt 查看服务端进程的 accept 队列长度,如果 accept 队列溢出,系统默认丢弃 ACK,如果可以把 tcp_abort_on_overflow 设置为 1 ,表示用 RST 通知客户端连接建立失败。

    如果 accpet 队列溢出严重,可以通过 listen 函数的 backlog 参数和 somaxconn 系统参数提高队列大小,accept 队列长度取决于 min(backlog, somaxconn)。

    绕过三次握手

    TCP Fast Open 功能可以绕过三次握手,使得 HTTP 请求减少了 1 个 RTT 的时间,Linux 下可以通过 tcp_fastopen 开启该功能,同时必须保证服务端和客户端同时支持。


    02 TCP 四次挥手的性能提升

    接下来,我们一起看看针对 TCP 四次挥手关闭连接时,如何优化性能。

    在开始之前,我们得先了解四次挥手状态变迁的过程。

    客户端和服务端双方都可以主动断开连接,通常先关闭连接的一方称为主动方,后关闭连接的一方称为被动方。

    客户端主动关闭

    可以看到,四次挥手过程只涉及了两种报文,分别是 FIN 和 ACK

    • FIN 就是结束连接的意思,谁发出 FIN 报文,就表示它将不会再发送任何数据,关闭这一方向上的传输通道;
    • ACK 就是确认的意思,用来通知对方:你方的发送通道已经关闭;

    四次挥手的过程:

    • 当主动方关闭连接时,会发送 FIN 报文,此时发送方的 TCP 连接将从 ESTABLISHED 变成 FIN_WAIT1。
    • 当被动方收到 FIN 报文后,内核会自动回复 ACK 报文,连接状态将从 ESTABLISHED 变成 CLOSE_WAIT,表示被动方在等待进程调用 close 函数关闭连接。
    • 当主动方收到这个 ACK 后,连接状态由 FIN_WAIT1 变为 FIN_WAIT2,也就是表示主动方的发送通道就关闭了
    • 当被动方进入 CLOSE_WAIT 时,被动方还会继续处理数据,等到进程的 read 函数返回 0 后,应用程序就会调用 close 函数,进而触发内核发送 FIN 报文,此时被动方的连接状态变为 LAST_ACK。
    • 当主动方收到这个 FIN 报文后,内核会回复 ACK 报文给被动方,同时主动方的连接状态由 FIN_WAIT2 变为 TIME_WAIT,在 Linux 系统下大约等待 1 分钟后,TIME_WAIT 状态的连接才会彻底关闭
    • 当被动方收到最后的 ACK 报文后,被动方的连接就会关闭

    你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手

    这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

    主动关闭方和被动关闭方优化的思路也不同,接下来分别说说如何优化他们。

    主动方的优化

    关闭连接的方式通常有两种,分别是 RST 报文关闭和 FIN 报文关闭。

    如果进程异常退出了,内核就会发送 RST 报文来关闭,它可以不走四次挥手流程,是一个暴力关闭连接的方式。

    安全关闭连接的方式必须通过四次挥手,它由进程调用 closeshutdown 函数发起 FIN 报文(shutdown 参数须传入 SHUT_WR 或者 SHUT_RDWR 才会发送 FIN)。

    调用 close 函数和 shutdown 函数有什么区别?

    调用了 close 函数意味着完全断开连接,完全断开不仅指无法传输数据,而且也不能发送数据。 此时,调用了 close 函数的一方的连接叫做「孤儿连接」,如果你用 netstat -p 命令,会发现连接对应的进程名为空。

    使用 close 函数关闭连接是不优雅的。于是,就出现了一种优雅关闭连接的 shutdown 函数,它可以控制只关闭一个方向的连接

    第二个参数决定断开连接的方式,主要有以下三种方式:

    • SHUT_RD(0):关闭连接的「读」这个方向,如果接收缓冲区有已接收的数据,则将会被丢弃,并且后续再收到新的数据,会对数据进行 ACK,然后悄悄地丢弃。也就是说,对端还是会接收到 ACK,在这种情况下根本不知道数据已经被丢弃了。
    • SHUT_WR(1):关闭连接的「写」这个方向,这就是常被称为「半关闭」的连接。如果发送缓冲区还有未发送的数据,将被立即发送出去,并发送一个 FIN 报文给对端。
    • SHUT_RDWR(2):相当于 SHUT_RD 和 SHUT_WR 操作各一次,关闭套接字的读和写两个方向

    close 和 shutdown 函数都可以关闭连接,但这两种方式关闭的连接,不只功能上有差异,控制它们的 Linux 参数也不相同。

    FIN_WAIT1 状态的优化

    主动方发送 FIN 报文后,连接就处于 FIN_WAIT1 状态,正常情况下,如果能及时收到被动方的 ACK,则会很快变为 FIN_WAIT2 状态。

    但是当迟迟收不到对方返回的 ACK 时,连接就会一直处于 FIN_WAIT1 状态。此时,内核会定时重发 FIN 报文,其中重发次数由 tcp_orphan_retries 参数控制(注意,orphan 虽然是孤儿的意思,该参数却不只对孤儿连接有效,事实上,它对所有 FIN_WAIT1 状态下的连接都有效),默认值是 0。

    你可能会好奇,这 0 表示几次?实际上当为 0 时,特指 8 次,从下面的内核源码可知:

    如果 FIN_WAIT1 状态连接很多,我们就需要考虑降低 tcp_orphan_retries 的值,当重传次数超过 tcp_orphan_retries 时,连接就会直接关闭掉。

    对于普遍正常情况时,调低 tcp_orphan_retries 就已经可以了。如果遇到恶意攻击,FIN 报文根本无法发送出去,这由 TCP 两个特性导致的:

    • 首先,TCP 必须保证报文是有序发送的,FIN 报文也不例外,当发送缓冲区还有数据没有发送时,FIN 报文也不能提前发送。
    • 其次,TCP 有流量控制功能,当接收方接收窗口为 0 时,发送方就不能再发送数据。所以,当攻击者下载大文件时,就可以通过接收窗口设为 0 ,这就会使得 FIN 报文都无法发送出去,那么连接会一直处于 FIN_WAIT1 状态。

    解决这种问题的方法,是调整 tcp_max_orphans 参数,它定义了「孤儿连接」的最大数量

    当进程调用了 close 函数关闭连接,此时连接就会是「孤儿连接」,因为它无法再发送和接收数据。Linux 系统为了防止孤儿连接过多,导致系统资源长时间被占用,就提供了 tcp_max_orphans 参数。如果孤儿连接数量大于它,新增的孤儿连接将不再走四次挥手,而是直接发送 RST 复位报文强制关闭。

    FIN_WAIT2 状态的优化

    当主动方收到 ACK 报文后,会处于 FIN_WAIT2 状态,就表示主动方的发送通道已经关闭,接下来将等待对方发送 FIN 报文,关闭对方的发送通道。

    这时,如果连接是用 shutdown 函数关闭的,连接可以一直处于 FIN_WAIT2 状态,因为它可能还可以发送或接收数据。但对于 close 函数关闭的孤儿连接,由于无法再发送和接收数据,所以这个状态不可以持续太久,而 tcp_fin_timeout 控制了这个状态下连接的持续时长,默认值是 60 秒:

    它意味着对于孤儿连接(调用 close 关闭的连接),如果在 60 秒后还没有收到 FIN 报文,连接就会直接关闭。

    这个 60 秒不是随便决定的,它与 TIME_WAIT 状态持续的时间是相同的,后面我们再来说说为什么是 60 秒。

    TIME_WAIT 状态的优化

    TIME_WAIT 是主动方四次挥手的最后一个状态,也是最常遇见的状态。

    当收到被动方发来的 FIN 报文后,主动方会立刻回复 ACK,表示确认对方的发送通道已经关闭,接着就处于 TIME_WAIT 状态。在 Linux 系统,TIME_WAIT 状态会持续 60 秒后才会进入关闭状态。

    TIME_WAIT 状态的连接,在主动方看来确实快已经关闭了。然后,被动方没有收到 ACK 报文前,还是处于 LAST_ACK 状态。如果这个 ACK 报文没有到达被动方,被动方就会重发 FIN 报文。重发次数仍然由前面介绍过的 tcp_orphan_retries 参数控制。

    TIME-WAIT 的状态尤其重要,主要是两个原因:

    • 防止具有相同「四元组」的「旧」数据包被收到;
    • 保证「被动关闭连接」的一方能被正确的关闭,即保证最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭;

    原因一:防止旧连接的数据包

    TIME-WAIT 的一个作用是防止收到历史数据,从而导致数据错乱的问题。

    假设 TIME-WAIT 没有等待时间或时间过短,被延迟的数据包抵达后会发生什么呢?

    接收到历史数据的异常

    • 如上图黄色框框服务端在关闭连接之前发送的 SEQ = 301 报文,被网络延迟了。
    • 这时有相同端口的 TCP 连接被复用后,被延迟的 SEQ = 301 抵达了客户端,那么客户端是有可能正常接收这个过期的报文,这就会产生数据错乱等严重的问题。

    所以,TCP 就设计出了这么一个机制,经过 2MSL 这个时间,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。

    原因二:保证连接正确关闭

    TIME-WAIT 的另外一个作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。

    假设 TIME-WAIT 没有等待时间或时间过短,断开连接会造成什么问题呢?

    没有确保正常断开的异常

    • 如上图红色框框客户端四次挥手的最后一个 ACK 报文如果在网络中被丢失了,此时如果客户端 TIME-WAIT 过短或没有,则就直接进入了 CLOSE 状态了,那么服务端则会一直处在 LAST-ACK 状态。
    • 当客户端发起建立连接的 SYN 请求报文后,服务端会发送 RST 报文给客户端,连接建立的过程就会被终止。

    我们再回过头来看看,为什么 TIME_WAIT 状态要保持 60 秒呢?这与孤儿连接 FIN_WAIT2 状态默认保留 60 秒的原理是一样的,因为这两个状态都需要保持 2MSL 时长。MSL 全称是 Maximum Segment Lifetime,它定义了一个报文在网络中的最长生存时间(报文每经过一次路由器的转发,IP 头部的 TTL 字段就会减 1,减到 0 时报文就被丢弃,这就限制了报文的最长存活时间)。

    为什么是 2 MSL 的时长呢?这其实是相当于至少允许报文丢失一次。比如,若 ACK 在一个 MSL 内丢失,这样被动方重发的 FIN 会在第 2 个 MSL 内到达,TIME_WAIT 状态的连接可以应对。

    为什么不是 4 或者 8 MSL 的时长呢?你可以想象一个丢包率达到百分之一的糟糕网络,连续两次丢包的概率只有万分之一,这个概率实在是太小了,忽略它比解决它更具性价比。

    因此,TIME_WAIT 和 FIN_WAIT2 状态的最大时长都是 2 MSL,由于在 Linux 系统中,MSL 的值固定为 30 秒,所以它们都是 60 秒。

    虽然 TIME_WAIT 状态有存在的必要,但它毕竟会消耗系统资源。如果发起连接一方的 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。

    • 客户端受端口资源限制:如果客户端 TIME_WAIT 过多,就会导致端口资源被占用,因为端口就65536个,被占满就会导致无法创建新的连接;
    • 服务端受系统资源限制:由于一个四元组表示TCP连接,理论上服务端可以建立很多连接,服务端确实只监听一个端口,但是会把连接扔给处理线程,所以理论上监听的端口可以继续监听。但是线程池处理不了那么多一直不断的连接了。所以当服务端出现大量 TIME_WAIT 时,系统资源被占满时,会导致处理不过来新的连接;

    另外,Linux 提供了 tcp_max_tw_buckets 参数,当 TIME_WAIT 的连接数量超过该参数时,新关闭的连接就不再经历 TIME_WAIT 而直接关闭:

    当服务器的并发连接增多时,相应地,同时处于 TIME_WAIT 状态的连接数量也会变多,此时就应当调大 tcp_max_tw_buckets 参数,减少不同连接间数据错乱的概率。

    tcp_max_tw_buckets 也不是越大越好,毕竟内存和端口都是有限的。

    有一种方式可以在建立新连接时,复用处于 TIME_WAIT 状态的连接,那就是打开 tcp_tw_reuse 参数。但是需要注意,该参数是只用于客户端(建立连接的发起方),因为是在调用 connect() 时起作用的,而对于服务端(被动连接方)是没有用的。

    tcp_tw_reuse 从协议角度理解是安全可控的,可以复用处于 TIME_WAIT 的端口为新的连接所用。

    什么是协议角度理解的安全可控呢?主要有两点:

    • 只适用于连接发起方,也就是 C/S 模型中的客户端;
    • 对应的 TIME_WAIT 状态的连接创建时间超过 1 秒才可以被复用。

    使用这个选项,还有一个前提,需要打开对 TCP 时间戳的支持(对方也要打开 ):

    由于引入了时间戳,它能带来了些好处:

    • 我们在前面提到的 2MSL 问题就不复存在了,因为重复的数据包会因为时间戳过期被自然丢弃;
    • 同时,它还可以防止序列号绕回,也是因为重复的数据包会由于时间戳过期被自然丢弃;

    时间戳是在 TCP 的选项字段里定义的,开启了时间戳功能,在 TCP 报文传输的时候会带上发送报文的时间戳。

    TCP option 字段 - 时间戳

    我们来看看开启了 tcp_tw_reuse 功能,如果四次挥手中的最后一次 ACK 在网络中丢失了,会发生什么?

    四次挥手中的最后一次 ACK 在网络中丢失

    上图的流程:

    • 四次挥手中的最后一次 ACK 在网络中丢失了,服务端一直处于 LAST_ACK 状态;
    • 客户端由于开启了 tcp_tw_reuse 功能,客户端再次发起新连接的时候,会复用超过 1 秒后的 time_wait 状态的连接。但客户端新发的 SYN 包会被忽略(由于时间戳),因为服务端比较了客户端的上一个报文与 SYN 报文的时间戳,过期的报文就会被服务端丢弃
    • 服务端 FIN 报文迟迟没有收到四次挥手的最后一次 ACK,于是超时重发了 FIN 报文给客户端;
    • 处于 SYN_SENT 状态的客户端,由于收到了 FIN 报文,则会回 RST 给服务端,于是服务端就离开了 LAST_ACK 状态;
    • 最初的客户端 SYN 报文超时重发了( 1 秒钟后),此时就与服务端能正确的三次握手了。

    所以大家都会说开启了 tcp_tw_reuse,可以在复用了 time_wait 状态的 1 秒过后成功建立连接,这 1 秒主要是花费在 SYN 包重传。

    另外,老版本的 Linux 还提供了 tcp_tw_recycle 参数,但是当开启了它,就有两个坑:

    • Linux 会加快客户端和服务端 TIME_WAIT 状态的时间,也就是它会使得 TIME_WAIT 状态会小于 60 秒,很容易导致数据错乱;
    • 另外,Linux 会丢弃所有来自远端时间戳小于上次记录的时间戳(由同一个远端发送的)的任何数据包。就是说要使用该选项,则必须保证数据包的时间戳是单调递增的。那么,问题在于,此处的时间戳并不是我们通常意义上面的绝对时间,而是一个相对时间。很多情况下,我们是没法保证时间戳单调递增的,比如使用了 NAT、LVS 等情况;

    所以,不建议设置为 1 ,在 Linux 4.12 版本后,Linux 内核直接取消了这一参数,建议关闭它:

    另外,我们可以在程序中设置 socket 选项,来设置调用 close 关闭连接行为。

    如果 l_onoff 为非 0, 且 l_linger 值为 0,那么调用 close 后,会立该发送一个 RST 标志给对端,该 TCP 连接将跳过四次挥手,也就跳过了 TIME_WAIT 状态,直接关闭。

    但这为跨越 TIME_WAIT 状态提供了一个可能,不过是一个非常危险的行为,不值得提倡。

    被动方的优化

    当被动方收到 FIN 报文时,内核会自动回复 ACK,同时连接处于 CLOSE_WAIT 状态,顾名思义,它表示等待应用进程调用 close 函数关闭连接。

    内核没有权利替代进程去关闭连接,因为如果主动方是通过 shutdown 关闭连接,那么它就是想在半关闭连接上接收数据或发送数据。因此,Linux 并没有限制 CLOSE_WAIT 状态的持续时间。

    当然,大多数应用程序并不使用 shutdown 函数关闭连接。所以,当你用 netstat 命令发现大量 CLOSE_WAIT 状态。就需要排查你的应用程序,因为可能因为应用程序出现了 Bug,read 函数返回 0 时,没有调用 close 函数。

    处于 CLOSE_WAIT 状态时,调用了 close 函数,内核就会发出 FIN 报文关闭发送通道,同时连接进入 LAST_ACK 状态,等待主动方返回 ACK 来确认连接关闭。

    如果迟迟收不到这个 ACK,内核就会重发 FIN 报文,重发次数仍然由 tcp_orphan_retries 参数控制,这与主动方重发 FIN 报文的优化策略一致。

    还有一点我们需要注意的,如果被动方迅速调用 close 函数,那么被动方的 ACK 和 FIN 有可能在一个报文中发送,这样看起来,四次挥手会变成三次挥手,这只是一种特殊情况,不用在意。

    如果连接双方同时关闭连接,会怎么样?

    由于 TCP 是双全工的协议,所以是会出现两方同时关闭连接的现象,也就是同时发送了 FIN 报文。

    此时,上面介绍的优化策略仍然适用。两方发送 FIN 报文时,都认为自己是主动方,所以都进入了 FIN_WAIT1 状态,FIN 报文的重发次数仍由 tcp_orphan_retries 参数控制。

    同时关闭

    接下来,双方在等待 ACK 报文的过程中,都等来了 FIN 报文。这是一种新情况,所以连接会进入一种叫做 CLOSING 的新状态,它替代了 FIN_WAIT2 状态。接着,双方内核回复 ACK 确认对方发送通道的关闭后,进入 TIME_WAIT 状态,等待 2MSL 的时间后,连接自动关闭。

    小结

    针对 TCP 四次挥手的优化,我们需要根据主动方和被动方四次挥手状态变化来调整系统 TCP 内核参数。

    四次挥手的优化策略

    主动方的优化

    主动发起 FIN 报文断开连接的一方,如果迟迟没收到对方的 ACK 回复,则会重传 FIN 报文,重传的次数由 tcp_orphan_retries 参数决定。

    当主动方收到 ACK 报文后,连接就进入 FIN_WAIT2 状态,根据关闭的方式不同,优化的方式也不同:

    • 如果这是 close 函数关闭的连接,那么它就是孤儿连接。如果 tcp_fin_timeout 秒内没有收到对方的 FIN 报文,连接就直接关闭。同时,为了应对孤儿连接占用太多的资源,tcp_max_orphans 定义了最大孤儿连接的数量,超过时连接就会直接释放。
    • 反之是 shutdown 函数关闭的连接,则不受此参数限制;

    当主动方接收到 FIN 报文,并返回 ACK 后,主动方的连接进入 TIME_WAIT 状态。这一状态会持续 1 分钟,为了防止 TIME_WAIT 状态占用太多的资源,tcp_max_tw_buckets 定义了最大数量,超过时连接也会直接释放。

    当 TIME_WAIT 状态过多时,还可以通过设置 tcp_tw_reusetcp_timestamps 为 1 ,将 TIME_WAIT 状态的端口复用于作为客户端的新连接,注意该参数只适用于客户端。

    被动方的优化

    被动关闭的连接方应对非常简单,它在回复 ACK 后就进入了 CLOSE_WAIT 状态,等待进程调用 close 函数关闭连接。因此,出现大量 CLOSE_WAIT 状态的连接时,应当从应用程序中找问题。

    当被动方发送 FIN 报文后,连接就进入 LAST_ACK 状态,在未等到 ACK 时,会在 tcp_orphan_retries 参数的控制下重发 FIN 报文。


    03 TCP 传输数据的性能提升

    在前面介绍的是三次握手和四次挥手的优化策略,接下来主要介绍的是 TCP 传输数据时的优化策略。

    TCP 连接是由内核维护的,内核会为每个连接建立内存缓冲区:

    • 如果连接的内存配置过小,就无法充分使用网络带宽,TCP 传输效率就会降低;
    • 如果连接的内存配置过大,很容易把服务器资源耗尽,这样就会导致新连接无法建立;

    因此,我们必须理解 Linux 下 TCP 内存的用途,才能正确地配置内存大小。

    滑动窗口是如何影响传输速度的?

    TCP 会保证每一个报文都能够抵达对方,它的机制是这样:报文发出去后,必须接收到对方返回的确认报文 ACK,如果迟迟未收到,就会超时重发该报文,直到收到对方的 ACK 为止。

    所以,TCP 报文发出去后,并不会立马从内存中删除,因为重传时还需要用到它。

    由于 TCP 是内核维护的,所以报文存放在内核缓冲区。如果连接非常多,我们可以通过 free 命令观察到 buff/cache 内存是会增大。

    如果 TCP 是每发送一个数据,都要进行一次确认应答。当上一个数据包收到了应答了, 再发送下一个。这个模式就有点像我和你面对面聊天,你一句我一句,但这种方式的缺点是效率比较低的。

    按数据包进行确认应答

    所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低

    要解决这一问题不难,并行批量发送报文,再批量确认报文即可。

    并行处理

    然而,这引出了另一个问题,发送方可以随心所欲的发送报文吗?当然这不现实,我们还得考虑接收方的处理能力。

    当接收方硬件不如发送方,或者系统繁忙、资源紧张时,是无法瞬间处理这么多报文的。于是,这些报文只能被丢掉,使得网络效率非常低。

    为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是滑动窗口的由来。

    接收方根据它的缓冲区,可以计算出后续能够接收多少字节的报文,这个数字叫做接收窗口。当内核接收到报文时,必须用缓冲区存放它们,这样剩余缓冲区空间变小,接收窗口也就变小了;当进程调用 read 函数后,数据被读入了用户空间,内核缓冲区就被清空,这意味着主机可以接收更多的报文,接收窗口就会变大。

    因此,接收窗口并不是恒定不变的,接收方会把当前可接收的大小放在 TCP 报文头部中的窗口字段,这样就可以起到窗口大小通知的作用。

    发送方的窗口等价于接收方的窗口吗?如果不考虑拥塞控制,发送方的窗口大小「约等于」接收方的窗口大小,因为窗口通知报文在网络传输是存在时延的,所以是约等于的关系。

    TCP 头部

    从上图中可以看到,窗口字段只有 2 个字节,因此它最多能表达 65535 字节大小的窗口,也就是 64KB 大小。

    这个窗口大小最大值,在当今高速网络下,很明显是不够用的。所以后续有了扩充窗口的方法:在 TCP 选项字段定义了窗口扩大因子,用于扩大 TCP 通告窗口,其值大小是 2^14,这样就使 TCP 的窗口大小从 16 位扩大为 30 位(2^16 * 2^ 14 = 2^30),所以此时窗口的最大值可以达到 1GB。

    TCP option 选项 - 窗口扩展

    Linux 中打开这一功能,需要把 tcp_window_scaling 配置设为 1(默认打开):

    要使用窗口扩大选项,通讯双方必须在各自的 SYN 报文中发送这个选项:

    • 主动建立连接的一方在 SYN 报文中发送这个选项;
    • 而被动建立连接的一方只有在收到带窗口扩大选项的 SYN 报文之后才能发送这个选项。

    这样看来,只要进程能及时地调用 read 函数读取数据,并且接收缓冲区配置得足够大,那么接收窗口就可以无限地放大,发送方也就无限地提升发送速度。

    这是不可能的,因为网络的传输能力是有限的,当发送方依据发送窗口,发送超过网络处理能力的报文时,路由器会直接丢弃这些报文。因此,缓冲区的内存并不是越大越好。

    如何确定最大传输速度?

    在前面我们知道了 TCP 的传输速度,受制于发送窗口与接收窗口,以及网络设备传输能力。其中,窗口大小由内核缓冲区大小决定。如果缓冲区与网络传输能力匹配,那么缓冲区的利用率就达到了最大化。

    问题来了,如何计算网络的传输能力呢?

    相信大家都知道网络是有「带宽」限制的,带宽描述的是网络传输能力,它与内核缓冲区的计量单位不同:

    • 带宽是单位时间内的流量,表达是「速度」,比如常见的带宽 100 MB/s;
    • 缓冲区单位是字节,当网络速度乘以时间才能得到字节数;

    这里需要说一个概念,就是带宽时延积,它决定网络中飞行报文的大小,它的计算方式:

    比如最大带宽是 100 MB/s,网络时延(RTT)是 10ms 时,意味着客户端到服务端的网络一共可以存放 100MB/s * 0.01s = 1MB 的字节。

    这个 1MB 是带宽和时延的乘积,所以它就叫「带宽时延积」(缩写为 BDP,Bandwidth Delay Product)。同时,这 1MB 也表示「飞行中」的 TCP 报文大小,它们就在网络线路、路由器等网络设备上。如果飞行报文超过了 1 MB,就会导致网络过载,容易丢包。

    由于发送缓冲区大小决定了发送窗口的上限,而发送窗口又决定了「已发送未确认」的飞行报文的上限。因此,发送缓冲区不能超过「带宽时延积」。

    发送缓冲区与带宽时延积的关系:

    • 如果发送缓冲区「超过」带宽时延积,超出的部分就没办法有效的网络传输,同时导致网络过载,容易丢包;
    • 如果发送缓冲区「小于」带宽时延积,就不能很好的发挥出网络的传输效率。

    所以,发送缓冲区的大小最好是往带宽时延积靠近。

    怎样调整缓冲区大小?

    在 Linux 中发送缓冲区和接收缓冲都是可以用参数调节的。设置完后,Linux 会根据你设置的缓冲区进行动态调节

    调节发送缓冲区范围

    先来看看发送缓冲区,它的范围通过 tcp_wmem 参数配置;

    上面三个数字单位都是字节,它们分别表示:

    • 第一个数值是动态范围的最小值,4096 byte = 4K;
    • 第二个数值是初始默认值,87380 byte ≈ 86K;
    • 第三个数值是动态范围的最大值,4194304 byte = 4096K(4M);

    发送缓冲区是自行调节的,当发送方发送的数据被确认后,并且没有新的数据要发送,就会把发送缓冲区的内存释放掉。

    调节接收缓冲区范围

    而接收缓冲区的调整就比较复杂一些,先来看看设置接收缓冲区范围的 tcp_rmem 参数:

    上面三个数字单位都是字节,它们分别表示:

    • 第一个数值是动态范围的最小值,表示即使在内存压力下也可以保证的最小接收缓冲区大小,4096 byte = 4K;
    • 第二个数值是初始默认值,87380 byte ≈ 86K;
    • 第三个数值是动态范围的最大值,6291456 byte = 6144K(6M);

    接收缓冲区可以根据系统空闲内存的大小来调节接收窗口:

    • 如果系统的空闲内存很多,就可以自动把缓冲区增大一些,这样传给对方的接收窗口也会变大,因而提升发送方发送的传输数据数量;
    • 反之,如果系统的内存很紧张,就会减少缓冲区,这虽然会降低传输效率,可以保证更多的并发连接正常工作;

    发送缓冲区的调节功能是自动开启的,而接收缓冲区则需要配置 tcp_moderate_rcvbuf 为 1 来开启调节功能

    调节 TCP 内存范围

    接收缓冲区调节时,怎么知道当前内存是否紧张或充分呢?这是通过 tcp_mem 配置完成的:

    上面三个数字单位不是字节,而是「页面大小」,1 页表示 4KB,它们分别表示:

    • 当 TCP 内存小于第 1 个值时,不需要进行自动调节;
    • 在第 1 和第 2 个值之间时,内核开始调节接收缓冲区的大小;
    • 大于第 3 个值时,内核不再为 TCP 分配新内存,此时新连接是无法建立的;

    一般情况下这些值是在系统启动时根据系统内存数量计算得到的。根据当前 tcp_mem 最大内存页面数是 177120,当内存为 (177120 * 4) / 1024K ≈ 692M 时,系统将无法为新的 TCP 连接分配内存,即 TCP 连接将被拒绝。

    根据实际场景调节的策略

    在高并发服务器中,为了兼顾网速与大量的并发连接,我们应当保证缓冲区的动态调整的最大值达到带宽时延积,而最小值保持默认的 4K 不变即可。而对于内存紧张的服务而言,调低默认值是提高并发的有效手段。

    同时,如果这是网络 IO 型服务器,那么,调大 tcp_mem 的上限可以让 TCP 连接使用更多的系统内存,这有利于提升并发能力。需要注意的是,tcp_wmem 和 tcp_rmem 的单位是字节,而 tcp_mem 的单位是页面大小。而且,千万不要在 socket 上直接设置 SO_SNDBUF 或者 SO_RCVBUF,这样会关闭缓冲区的动态调整功能。

    小结

    本节针对 TCP 优化数据传输的方式,做了一些介绍。

    数据传输的优化策略

    TCP 可靠性是通过 ACK 确认报文实现的,又依赖滑动窗口提升了发送速度也兼顾了接收方的处理能力。

    可是,默认的滑动窗口最大值只有 64 KB,不满足当今的高速网络的要求,要想提升发送速度必须提升滑动窗口的上限,在 Linux 下是通过设置 tcp_window_scaling 为 1 做到的,此时最大值可高达 1GB。

    滑动窗口定义了网络中飞行报文的最大字节数,当它超过带宽时延积时,网络过载,就会发生丢包。而当它小于带宽时延积时,就无法充分利用网络带宽。因此,滑动窗口的设置,必须参考带宽时延积。

    内核缓冲区决定了滑动窗口的上限,缓冲区可分为:发送缓冲区 tcp_wmem 和接收缓冲区 tcp_rmem。

    Linux 会对缓冲区动态调节,我们应该把缓冲区的上限设置为带宽时延积。发送缓冲区的调节功能是自动打开的,而接收缓冲区需要把 tcp_moderate_rcvbuf 设置为 1 来开启。其中,调节的依据是 TCP 内存范围 tcp_mem。

    但需要注意的是,如果程序中的 socket 设置 SO_SNDBUF 和 SO_RCVBUF,则会关闭缓冲区的动态整功能,所以不建议在程序设置它俩,而是交给内核自动调整比较好。

    有效配置这些参数后,既能够最大程度地保持并发性,也能让资源充裕时连接传输速度达到最大值。


    巨人的肩膀

    [1] 系统性能调优必知必会.陶辉.极客时间.

    [2] 网络编程实战专栏.盛延敏.极客时间.

    [3] http://www.blogjava.net/yongboy/archive/2013/04/11/397677.html

    [4] http://blog.itpub.net/31559359/viewspace-2284113/

    [5] https://blog.51cto.com/professor/1909022

    [6] https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux


    唠嗑唠嗑

    小林是专为大家图解的工具人,Goodbye,我们下次见!


    读者问答

    读者问:“小林,请教个问题,somaxconn和backlog是不是都是指的是accept队列?然后somaxconn是内核参数,backlog是通过系统调用间隔地修改somaxconn,比如Linux中listen()函数?”

    两者取最小值才是 accpet 队列。

    读者问:“小林,还有个问题要请教下,“如果 accept 队列满了,那么 server 扔掉 client 发过来的 ack”,也就是说该TCP连接还是位于半连接队列中,没有丢弃吗?”

    1. 当 accept 队列满了,后续新进来的syn包都会被丢失
    2. 我文章的突发流量例子是,那个连接进来的时候 accept 队列还没满,但是在第三次握手的时候,accept 队列突然满了,就会导致 ack 被丢弃,就一直处于半连接队列。

    「图解网络」文章受到了很多读者的喜爱与支持,为了方便大家阅读,小林把自己原创的图解网络系列文章整理成了pdf,内容涵盖计算机网络的重点知识,比如 HTTP、TCP、UDP、IP等等,pdf 共「300 页 + 9W字 + 30 张图」

    并且根据不同读者的阅读习惯,我整了两种风格的图解网络pdf,分别是「亮白版本」和「暗黑版本」。

    亮白

    暗黑版本

    百度网盘下载链接如下:

    链接:https://pan.baidu.com/s/1dRNDPW_WjV6vb3liiLPqHA

    提取码:t95u

    展开全文
  • linux centOS7内核参数调整

    千次阅读 2021-02-12 12:53:38
    #修改内核参数 [root@centos1 ~]# sysctl -a|egrep 'file-max|nr_open' #查看当前值 fs.file-max = 85204 #所有进程可打开的文件句柄的数量限制 fs.nr_open = 1048576 #单个进程打开文件句柄数上限 [root@centos1 ~]...
  • 内核参数
  • 内核参数参考

    2014-08-22 14:18:13
    内核参数参考,列举了一些网络参数的参考含义
  • Linux如何在系统运行过程中修改内核参数发布时间:2009-01-02 00:12:14来源:红联作者:jerry520RedHat向管理员提供了非常好的方法,使我们可以在系统运行时更改内核参数,而不需要重新引导系统。这是通过/proc虚拟文件...
  • 那如何修改Linux内核参数呢?这里有两种方法 方法1:输入重定向改内核参数,临时生效 临时修改网络协议参数 [root@sotneC6 ~]# cat /proc/sys/net/ipv4/icmp_echo_ignore_all 0 [root@sotneC6 ~]# echo 1 > /...
  • Linux内核参数配置

    千次阅读 2018-04-13 10:45:19
    Linux内核参数配置Linux在系统运行时修改内核参数(/proc/sys与/etc/sysctl.conf),而不需要重新引导系统,这个功能是通过/proc虚拟文件系统实现的。在/proc/sys目录下存放着大多数的内核参数,并且设计成可以在系统...
  • 内核参数使用方法的实验,写的很详细,重点说明的是带有源代码的,2个分绝对不多。
  • 注释: /proc:虚拟文件系统 /proc/sys/:内核参数 常用参数大全: https://www.cnblogs.com/tolimit/p/5065761.html 内核参数调优: http://blog.chinaunix.net/uid-16909016-id-199050.html ...
  • linux内核参数修改方法

    千次阅读 2020-12-07 11:17:39
    由于Linux的内核参数信息都存在内存中,因此可以通过命令直接修改,并且修改后直接生效。但是,当系统重新启动后,原来设置的参数值就会丢失,而系统每次启动时都会自动去/etc/sysctl.conf文件中读取内核参数,因此...
  • linux 操作系统启动过程和内核参数修改添加方法 操作系统启动过程 操作系统启动过程一般分为五个阶段:(centos7为例) BIOS初始化 加载MBR到内存 GRUB阶段 加载内核和initramfs模块 systemd阶段 BIOS初始化 上电后...
  • 如何查看内核参数的说明文档

    千次阅读 2019-02-13 15:59:11
    如何查看内核参数的说明文档 原文链接 Linux内核源代码释出时会包含有一些关于内核参数(如sysctl.conf中的参数)和函数的说明文档,在CentOS/RedHat系统中,kernel-doc软件包里面打包的就是这些文档(也可以从官网...
  • CentOS 7 内核参数优化

    千次阅读 2019-11-08 08:59:40
    打开内核参数文件 vi /etc/sysctl.conf 立即使配置文件生效 sysctl -p 一、防DDoS,CC和SYN攻击 1、开启SYN Cookies,当SYN等待队列溢出时,启用cookies来处理,可以防范少量的SYN攻击,默认为0,表示关闭 ...
  • linux内核参数设置_linux内核的功能有哪些.docx
  • Ubuntu16.04内核参数调优

    千次阅读 2019-06-02 15:09:50
    在window上只有65535个端口,在使用IDEA测试连接数到16000左右就占用光了,即使后来经过tcp参数调优后有60000出头的连接数。见到网上使用linux测试连接数的居多,就在电脑上装了个Ubuntu16.04的虚拟机尝试。 二...
  • 使用initcontainer 修改pod 中容器的内核参数 在pod 中使用的案例 apiVersion: v1 kind: Pod metadata: name: test-sysctl-init namespace: default spec: containers: - image: nginx imagePullPolicy: ...
  • Kubernetes Pod中的内核参数调整

    千次阅读 2020-03-05 19:27:01
    使用uwsgi部署了一个django的应用,并且使用Kubernetes来运行,但是运行以后老是报如下的错误,后来在网上查询了,是一个系统内核参数(net.core.somaxconn)太小了,默认是128.所以需要将它调整大一些。 uwsgi_proto_...
  • k8s内核参数调优

    千次阅读 2020-05-19 13:52:41
    cat/etc/sysctl.conf kernel.core_uses_pid=1 kernel.pid_max=4194303 kernel.ctrl-alt-del=1 # kernel.core_pattern = /disk/ssd00/cores/core ... kernel.shmmax=8589...
  • centos对内核参数的修改

    千次阅读 2019-09-18 06:49:58
    在centos中 sysctl -a 显示当前系统中可用的内核参数Linux修改内核参数有三种方式:(1)修改 /etc/sysctl.conf 文件,加入配置选项,格式为 key = value ,修改保存后调用 sysctl -p 加载新配置(此种方式在系统...
  • Linux内核参数修改方法

    千次阅读 2019-10-08 12:54:02
    由于Linux的内核参数信息都存在内存中,因此可以通过命令直接修改,并且修改后直接生效。但是,当系统重新启动后,原来设置的参数值就会丢失,而系统每次启动时都会自动去/etc/sysctl.conf文件中读取内核参数,因此...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 617,186
精华内容 246,874
关键字:

内核参数

友情链接: code.zip