写在后面
最近,有小伙伴在群里发问:Linux 零碎怎么设置 tcp_nodelay 参数?也有小伙伴说问我。那明天,咱们就来依据这个问题来聊聊在高并发场景下如何优化服务器的性能这个话题。
其实,tcp_nodelay 参数并不是在操作系统级别进行配置的,而是在 TCP 套接字上增加 tcp_nodelay 参数来敞开粘包算法,以便使数据包可能立刻投递进来。tcp_nodelay 参数次要是对 TCP 套接字来说的,那对于服务器硬件,如果要使其可能撑持上百万甚至上千万的并发,咱们该如何对其进行优化呢?
文章已收录到:
https://github.com/sunshinelyz/technology-binghe
https://gitee.com/binghe001/technology-binghe
操作系统
这里,我应用的操作系统为 CentOS 8,咱们能够输出如下命令来查看操作系统的版本。
CentOS Linux release 8.0.1905 (Core)
对于高并发的场景,咱们次要还是优化操作系统的网络性能,而操作系统中,有很多对于网络协议的参数,咱们对于服务器网络性能的优化,次要是对这些零碎参数进行调优,以达到晋升咱们利用拜访性能的目标。
零碎参数
在 CentOS 操作系统中,咱们能够通过如下命令来查看所有的零碎参数。
/sbin/sysctl -a
局部输入后果如下所示。
这里的参数太多了,大略有一千多个,在高并发场景下,咱们不可能对操作系统的所有参数进行调优。咱们更多的是关注与网络相干的参数。如果想取得与网络相干的参数,那么,咱们首先须要获取操作系统参数的类型,如下命令能够获取操作系统参数的类型。
/sbin/sysctl -a|awk -F "." '{print $1}'|sort -k1|uniq
运行命令输入的后果信息如下所示。
abi
crypto
debug
dev
fs
kernel
net
sunrpc
user
vm
其中的 net 类型就是咱们要关注的与网络相干的操作系统参数。咱们能够获取 net 类型下的子类型,如下所示。
/sbin/sysctl -a|grep "^net."|awk -F "[.|]" '{print $2}'|sort -k1|uniq
输入的后果信息如下所示。
bridge
core
ipv4
ipv6
netfilter
nf_conntrack_max
unix
在 Linux 操作系统中,这些与网络相干的参数都能够在 /etc/sysctl.conf 文件里批改,如果 /etc/sysctl.conf 文件中不存在这些参数,咱们能够自行在 /etc/sysctl.conf 文件中增加这些参数。
在 net 类型的子类型中,咱们须要重点关注的子类型有:core 和 ipv4。
优化套接字缓冲区
如果服务器的网络套接字缓冲区太小,就会导致应用程序读写屡次能力将数据处理完,这会大大影响咱们程序的性能。如果网络套接字缓冲区设置的足够大,从肯定水平上可能晋升咱们程序的性能。
咱们能够在服务器的命令行输出如下命令,来获取无关服务器套接字缓冲区的信息。
/sbin/sysctl -a|grep "^net."|grep "[r|w|_]mem[_|]"
输入的后果信息如下所示。
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992
net.ipv4.tcp_mem = 43545 58062 87090
net.ipv4.tcp_rmem = 4096 87380 6291456
net.ipv4.tcp_wmem = 4096 16384 4194304
net.ipv4.udp_mem = 87093 116125 174186
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
其中,带有 max、default、min 关键字的为别离代表:最大值、默认值和最小值;带有 mem、rmem、wmem 关键字的别离为:总内存、接收缓冲区内存、发送缓冲区内存。
这里须要留神的是:带有 rmem 和 wmem 关键字的单位都是“字节”,而带有 mem 关键字的单位是“页”。“页”是操作系统治理内存的最小单位,在 Linux 零碎里,默认一页是 4KB 大小。
如何优化频繁收发大文件
如果在高并发场景下,须要频繁的收发大文件,咱们该如何优化服务器的性能呢?
这里,咱们能够批改的零碎参数如下所示。
net.core.rmem_default
net.core.rmem_max
net.core.wmem_default
net.core.wmem_max
net.ipv4.tcp_mem
net.ipv4.tcp_rmem
net.ipv4.tcp_wmem
这里,咱们做个假如,假如零碎最大能够给 TCP 调配 2GB 内存,最小值为 256MB,压力值为 1.5GB。依照一页为 4KB 来计算,tcp_mem 的最小值、压力值、最大值别离是 65536、393216、524288,单位是“页”。
如果均匀每个文件数据包为 512KB,每个套接字读写缓冲区最小能够各包容 2 个数据包,默认能够各包容 4 个数据包,最大能够各包容 10 个数据包,那咱们能够算出 tcp_rmem 和 tcp_wmem 的最小值、默认值、最大值别离是 1048576、2097152、5242880,单位是“字节”。而 rmem_default 和 wmem_default 是 2097152,rmem_max 和 wmem_max 是 5242880。
注:前面具体介绍这些数值是如何计算的~~
这里,还须要留神的是:缓冲区超过了 65535,还须要将 net.ipv4.tcp_window_scaling 参数设置为 1。
通过下面的剖析后,咱们最终得出的零碎调优参数如下所示。
net.core.rmem_default = 2097152
net.core.rmem_max = 5242880
net.core.wmem_default = 2097152
net.core.wmem_max = 5242880
net.ipv4.tcp_mem = 65536 393216 524288
net.ipv4.tcp_rmem = 1048576 2097152 5242880
net.ipv4.tcp_wmem = 1048576 2097152 5242880
优化 TCP 连贯
对计算机网络有肯定理解的小伙伴都晓得,TCP 的连贯须要通过“三次握手”和“四次挥手”的,还要通过慢启动、滑动窗口、粘包算法等反对可靠性传输的一系列技术支持。尽管,这些可能保障 TCP 协定的可靠性,但有时这会影响咱们程序的性能。
那么,在高并发场景下,咱们该如何优化 TCP 连贯呢?
(1)敞开粘包算法
如果用户对于申请的耗时很敏感,咱们就须要在 TCP 套接字上增加 tcp_nodelay 参数来敞开粘包算法,以便数据包可能立即发送进来。此时,咱们也能够设置 net.ipv4.tcp_syncookies 的参数值为 1。
(2)防止频繁的创立和回收连贯资源
网络连接的创立和回收是十分耗费性能的,咱们能够通过敞开闲暇的连贯、反复利用曾经调配的连贯资源来优化服务器的性能。反复利用曾经调配的连贯资源大家其实并不生疏,像:线程池、数据库连接池就是复用了线程和数据库连贯。
咱们能够通过如下参数来敞开服务器的闲暇连贯和复用已调配的连贯资源。
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time=1800
(3)防止反复发送数据包
TCP 反对超时重传机制。如果发送方将数据包曾经发送给接管方,但发送方并未收到反馈,此时,如果达到设置的工夫距离,就会触发 TCP 的超时重传机制。为了防止发送胜利的数据包再次发送,咱们须要将服务器的 net.ipv4.tcp_sack 参数设置为 1。
(4)增大服务器文件描述符数量
在 Linux 操作系统中,一个网络连接也会占用一个文件描述符,连贯越多,占用的文件描述符也就越多。如果文件描述符设置的比拟小,也会影响咱们服务器的性能。此时,咱们就须要增大服务器文件描述符的数量。
例如:fs.file-max = 10240000,示意服务器最多能够关上 10240000 个文件。
好了,本文联合群内读者的发问进行的一些总结,心愿可能给小伙伴们带来实质性的帮忙。明天就到这儿吧,我是冰河,大家有啥问题能够在下方留言,也能够加我微信:sun_shine_lyz,一起交换技术,一起进阶,一起牛逼~~