高并发场景下如何优化服务器的性能?
写在前面
最近,有小伙伴在群里提问: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 操作系统中,我们可以通过如下命令来查看所有的系统参数。
部分输出结果如下所示。
这里的参数太多了,大概有一千多个,在高并发场景下,我们不可能对操作系统的所有参数进行调优。我们更多的是关注与网络相关的参数。如果想获得与网络相关的参数,那么,我们首先需要获取操作系统参数的类型,如下命令可以获取操作系统参数的类型。
运行命令输出的结果信息如下所示。
其中的 net 类型就是我们要关注的与网络相关的操作系统参数。我们可以获取 net 类型下的子类型,如下所示。
输出的结果信息如下所示。
在 Linux 操作系统中,这些与网络相关的参数都可以在/etc/sysctl.conf 文件里修改,如果/etc/sysctl.conf 文件中不存在这些参数,我们可以自行在/etc/sysctl.conf 文件中添加这些参数。
在 net 类型的子类型中,我们需要重点关注的子类型有:core 和 ipv4。
优化套接字缓冲区
如果服务器的网络套接字缓冲区太小,就会导致应用程序读写多次才能将数据处理完,这会大大影响我们程序的性能。如果网络套接字缓冲区设置的足够大,从一定程度上能够提升我们程序的性能。
我们可以在服务器的命令行输入如下命令,来获取有关服务器套接字缓冲区的信息。
输出的结果信息如下所示。
其中,带有 max、default、min 关键字的为分别代表:最大值、默认值和最小值;带有 mem、rmem、wmem 关键字的分别为:总内存、接收缓冲区内存、发送缓冲区内存。
这里需要注意的是:带有 rmem 和 wmem 关键字的单位都是“字节”,而带有 mem 关键字的单位是“页”。“页”是操作系统管理内存的最小单位,在 Linux 系统里,默认一页是 4KB 大小。
如何优化频繁收发大文件
如果在高并发场景下,需要频繁的收发大文件,我们该如何优化服务器的性能呢?
这里,我们可以修改的系统参数如下所示。
这里,我们做个假设,假设系统最大可以给 TCP 分配 2GB 内存,最小值为 256MB,压力值为 1.5GB。按照一页为 4KB 来计算, tcp_mem 的最小值、压力值、最大值分别是 65536、393216、524288,单位是“页” 。
假如平均每个文件数据包为 512KB,每个套接字读写缓冲区最小可以各容纳 2 个数据包,默认可以各容纳 4 个数据包,最大可以各容纳 10 个数据包,那我们可以算出 tcprmem 和 tcpwmem 的最小值、默认值、最大值分别是 1048576、2097152、5242880,单位是“字节”。而 rmemdefault 和 wmemdefault 是 2097152,rmemmax 和 wmemmax 是 5242880。
注:后面详细介绍这些数值是如何计算的~~
这里,还需要注意的是:缓冲区超过了 65535,还需要将 net.ipv4.tcpwindowscaling 参数设置为 1。
经过上面的分析后,我们最终得出的系统调优参数如下所示。
优化 TCP 连接
对计算机网络有一定了解的小伙伴都知道,TCP 的连接需要经过“三次握手”和“四次挥手”的,还要经过慢启动、滑动窗口、粘包算法等支持可靠性传输的一系列技术支持。虽然,这些能够保证 TCP 协议的可靠性,但有时这会影响我们程序的性能。
那么,在高并发场景下,我们该如何优化 TCP 连接呢?
(1)关闭粘包算法
如果用户对于请求的耗时很敏感,我们就需要在 TCP 套接字上添加 tcpnodelay 参数来关闭粘包算法,以便数据包能够立刻发送出去。此时,我们也可以设置 net.ipv4.tcpsyncookies 的参数值为 1。
(2)避免频繁的创建和回收连接资源
网络连接的创建和回收是非常消耗性能的,我们可以通过关闭空闲的连接、重复利用已经分配的连接资源来优化服务器的性能。重复利用已经分配的连接资源大家其实并不陌生,像:线程池、数据库连接池就是复用了线程和数据库连接。
我们可以通过如下参数来关闭服务器的空闲连接和复用已分配的连接资源。
(3)避免重复发送数据包
TCP 支持超时重传机制。如果发送方将数据包已经发送给接收方,但发送方并未收到反馈,此时,如果达到设置的时间间隔,就会触发 TCP 的超时重传机制。为了避免发送成功的数据包再次发送,我们需要将服务器的 net.ipv4.tcp_sack 参数设置为 1。
(4)增大服务器文件描述符数量
在 Linux 操作系统中,一个网络连接也会占用一个文件描述符,连接越多,占用的文件描述符也就越多。如果文件描述符设置的比较小,也会影响我们服务器的性能。此时,我们就需要增大服务器文件描述符的数量。
例如:fs.file-max = 10240000,表示服务器最多可以打开 10240000 个文件。
好了,本文结合群内读者的提问进行的一些总结,希望能够给小伙伴们带来实质性的帮助。今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,一起交流技术,一起进阶,一起牛逼~~
版权声明: 本文为 InfoQ 作者【冰河】的原创文章。
原文链接:【http://xie.infoq.cn/article/2223f7737cad7d04c4776d34f】。文章转载请联系作者。
评论