每日一问题探索-高并发下的linux优化
原创 五分钟学SRE 五分钟学SRE 2023-02-25 23:42 发表于香港 收录于合集 #每日一问题探索10个 #五分钟学SRE51个
针对高并发服务,对 Linux 内核和网络进行优化可以提高系统的性能和稳定性。本文将深入探讨如何对 Linux 内核和网络进行优化,包括调整内核参数、调整网络性能参数、使用 TCP/IP 协议栈加速技术、下面将介绍一些可用于优化Linux内核和网络的技术,并详细说明需要优化哪些配置。
Linux内核优化
Linux内核是高并发服务的关键组件之一。以下是一些可用于优化Linux内核的配置。
调整文件句柄限制
Linux 内核对于每个进程都有一个文件描述符(file descriptor)数组,文件描述符可以看成是操作系统对于文件或者 I/O 设备打开的引用。在高并发场景下,进程所需的文件描述符数量会增加,如果进程的文件描述符数量不足,就会出现“too many open files”的错误。因此,需要适当调整文件句柄数量,增加系统可同时打开的文件数。可以通过以下命令来查看当前文件句柄限制:
ulimit -n
默认情况下,文件句柄限制为1024。如果需要打开更多的文件和套接字,请使用以下命令来增加文件句柄限制:
ulimit -n 65535
调整进程数量限制
在高并发场景下,进程数量可能会增加。如果系统对于进程数量的限制过低,就会导致进程无法创建,从而影响系统的正常运行。因此,需要适当调整进程数量限制。
在 Linux 中,可以通过修改 /etc/security/limits.conf 文件来调整进程数量限制。
例如,可以将每个用户可创建的进程数量修改为 65535:
* soft nproc 65535 * hard nproc 65535
调整TCP参数
TCP/IP协议栈是高并发服务中的重要组成部分,通过调整TCP/IP协议栈参数,可以提高网络性能。以下是一些常用的TCP/IP协议栈参数:
net.ipv4.tcp_max_syn_backlog:用于指定SYN队列的最大长度。
net.ipv4.tcp_syncookies:用于启用SYN Cookies机制,防止SYN Flood攻击。
net.ipv4.tcp_syn_retries:用于指定SYN重试次数。
net.ipv4.tcp_synack_retries:用于指定SYN/ACK重试次数。
net.ipv4.tcp_fin_timeout:用于指定TCP连接关闭的超时时间。
net.ipv4.tcp_tw_reuse:用于启用TIME-WAIT状态的连接重用。
net.ipv4.tcp_tw_recycle:用于启用TIME-WAIT状态的连接回收。
net.ipv4.tcp_max_tw_buckets:用于指定TIME-WAIT状态的连接的最大数量。
net.ipv4.tcp_rmem:用于指定接收缓冲区的大小。
net.ipv4.tcp_wmem:用于指定发送缓冲区的大小。
net.core.somaxconn:用于指定套接字的最大连接数。
net.core.netdev_max_backlog:用于指定网络设备接收队列的最大长度。
可以使用以下命令来查看当前TCP/IP协议栈参数:
sysctl net.ipv4.tcp*
可以使用以下命令来修改TCP/IP协议栈参数:
sysctl -w 参数名=参数值
#或者修改配置文件
vim /etc/sysctl.conf
#生效
/sbin/sysctl -p
调整内存参数
在高并发服务中,内存管理也是很重要的。可以通过调整内存参数来优化内存管理。以下是一些常用的内存参数:
-
vm.min_free_kbytes:这个参数用来指定系统中最小的空闲内存大小。如果系统中的空闲内存低于这个值,系统会尝试回收内存。对于高并发服务,建议将这个值调整为较高的数值,例如 65536(64MB)。
-
vm.swappiness:这个参数用来控制系统使用 swap 分区的程度。如果这个值为 0,系统只有在完全没有空闲内存时才会使用 swap 分区。如果这个值为 100,系统会尽可能地使用 swap 分区。对于高并发服务,建议将这个值调整为较低的数值,例如 10。
-
vm.dirty_ratio 和 vm.dirty_background_ratio:这两个参数用来控制脏页的数量。脏页是指已经被修改但尚未被写回磁盘的页。当系统中的脏页数量超过这两个参数指定的阈值时,系统会触发写回操作。对于高并发服务,建议将这两个值调整为较低的数值,例如 5 和 2。
可以使用以下命令来查看当前内存参数:
sysctl vm.*
可以使用以下命令来修改内存参数:
sysctl -w 参数名=参数值
#或者修改配置文件
vim /etc/sysctl.conf
#生效
/sbin/sysctl -p
Linux网络优化
Linux网络是高并发服务的另一个关键组件。以下是一些可用于优化Linux网络的配置。
调整MTU
MTU是最大传输单元的缩写。在高并发服务中,MTU的大小会影响网络性能。如果MTU太小,则会增加网络包的数量,从而增加了网络负载。如果MTU太大,则可能会导致网络包被分成多个片段,从而增加了网络延迟。因此,调整MTU是提高网络性能的重要步骤之一。
可以使用以下命令来查看当前MTU值:
ip link show
可以使用以下命令来修改MTU值:
ip link set dev eth0 mtu 1500
调整网络缓冲区
在高并发服务中,网络缓冲区的大小也会影响网络性能。可以通过调整网络缓冲区来提高网络性能。以下是一些常用的网络缓冲区参数:
net.core.rmem_max:用于指定接收缓冲区的最大大小。
net.core.wmem_max:用于指定发送缓冲区的最大大小。
net.core.rmem_default:用于指定接收缓冲区的默认大小。
net.core.wmem_default:用于指定发送缓冲区的默认大小。
可以使用以下命令来查看当前网络缓冲区参数:
sysctl net.core.*
可以使用以下命令来修改网络缓冲区参数:
sysctl -w 参数名=参数值
使用TCP/IP协议栈加速技术
TCP协议栈的加速主要通过以下两种方式实现:
-
改进拥塞控制算法
TCP拥塞控制算法是保证网络传输可靠的重要机制,但是其效率较低。因此,可以通过改进拥塞控制算法来提高网络传输的速度和性能。例如,可以采用一些更为先进的拥塞控制算法,如TCP BBR、TCP Cubic等。
-
增加TCP窗口大小
TCP窗口大小是控制数据传输速度的重要参数。通过增加TCP窗口大小,可以提高网络传输的速度和性能。例如,可以通过调整TCP窗口大小的最大值和初始值来提高网络传输的速度和性能。
UDP协议栈的加速主要通过以下方式实现:
-
发送方尽量避免丢包
由于UDP协议是面向无连接的,因此在数据传输过程中容易出现丢包的情况。为了提高网络传输的速度和性能,可以在发送数据时尽量避免丢包。例如,可以通过采用一些更为先进的数据校验算法来减少丢包的概率。
-
接收方尽量避免重复数据
在UDP协议中,数据包的发送和接收是没有任何顺序的。因此,在数据接收过程中,可能会出现重复数据的情况。为了提高网络传输的速度和性能,可以在接收数据时尽量避免重复数据。例如,可以通过维护一个接收窗口来过滤掉重复数据。
开启 TCP Fast Open
TCP Fast Open(TFO)是一种加速 TCP 三次握手的技术。当启用 TFO 时,客户端和服务器之间在进行三次握手时,客户端可以在 SYN 报文中携带数据,这样服务器就可以在收到 SYN 报文时就开始处理请求,从而加快请求的响应速度。
在 Linux 中,可以通过修改 /etc/sysctl.conf 文件来开启 TFO:
net.ipv4.tcp_fastopen=3
开启 BBR 拥塞控制算法
BBR 是 Google 开发的一种拥塞控制算法,可以显著提高网络的吞吐量和延迟。可以通过开启 BBR 拥塞控制算法来提高网络性能。
在 Linux 中,可以通过修改 /etc/sysctl.conf 文件来开启 BBR:
net.core.default_qdisc=fqnet.ipv4.tcp_congestion_control=bbr
TCP/IP 协议栈的零拷贝
传统的 TCP/IP 协议栈在传输数据时,需要将数据从用户空间复制到内核空间,然后再从内核空间复制到网络卡,这个过程被称为“拷贝”。在高并发场景下,大量的拷贝操作会成为瓶颈,影响网络传输的效率。为了解决这个问题,TCP/IP 协议栈的零拷贝技术应运而生。
零拷贝技术的基本思想是:通过让内核空间和用户空间共享同一块内存来避免数据的复制,从而提高网络传输效率。具体实现方式包括:mmap、sendfile 和 splice 等。
mmap
mmap 是一种内存映射技术,它可以将文件或设备的数据映射到进程的虚拟地址空间中,从而实现用户空间和内核空间之间的数据共享。在 Linux 系统中,可以使用 mmap 函数将网络数据映射到用户空间中,然后通过 DMA(直接内存访问)技术将数据发送到网络卡中,从而实现零拷贝。
sendfile
sendfile 是一种高效的文件传输方式,它可以将文件数据直接发送到网络卡,而无需经过内核空间和用户空间的复制。在 Linux 系统中,可以使用 sendfile 函数将文件数据发送到网络卡中,从而实现零拷贝。
splice
splice 是一种高效的数据传输方式,它可以将两个文件描述符之间的数据传输,而无需经过内核空间和用户空间的复制。在 Linux 系统中,可以使用 splice 函数将数据从一个文件描述符传输到另一个文件描述符中,从而实现零拷贝。
tip:
在使用TCP/IP协议栈加速技术时,也需要注意一些调整参数。以下是一些常见的可调整参数:
-
TCP连接数限制:通过调整
/proc/sys/net/ipv4/tcp_max_syn_backlog
参数可以调整TCP连接数的限制,从而避免TCP连接被阻塞。 -
内存限制:TCP/IP协议栈需要大量的内存来缓存数据,因此需要通过调整
/proc/sys/net/core/rmem_max
和/proc/sys/net/core/wmem_max
参数来限制协议栈可以使用的内存大小。 -
时间限制:TCP/IP协议栈需要定期清除过期的数据,因此需要通过调整
/proc/sys/net/ipv4/tcp_keepalive_time
参数来设置TCP连接的超时时间,从而避免过期数据占用内存。 -
接收缓存大小:通过调整
/proc/sys/net/core/rmem_default
参数可以设置TCP接收缓存的大小,从而提高TCP接收数据的速度。 -
发送缓存大小:通过调整
/proc/sys/net/core/wmem_default
参数可以设置TCP发送缓存的大小,从而提高TCP发送数据的速度。 -
TCP拥塞控制算法:TCP拥塞控制算法可以根据网络拥塞情况自动调整数据发送速率。Linux内核支持多种TCP拥塞控制算法,可以通过
/proc/sys/net/ipv4/tcp_congestion_control
参数来设置。 -
TCP窗口大小:通过调整
/proc/sys/net/ipv4/tcp_window_scaling
参数可以启用TCP窗口缩放功能,从而提高TCP传输数据的速度。