网站性能优化从入门到粗通(PHP 篇)
阅读原文时间:2021年04月22日阅读:1

本文来自作者 蒋岩 在 GitChat 上分享 「网站性能优化从入门到粗通(PHP 篇)」,「阅读原文」查看交流实录。

「文末高能」

编辑 | 哈比

题外话:本次 Chat 的主题是入门到粗通,所以内容对于老司机来说会比较 Low,请多包涵。

进入正题。

一、测试工具推荐

笔者第一次接触网站性能优化是在 2009 年实习时期,当时所在的公司有一个 PHP+Mysql 开发的 B2C 平台需要做用户体验优化。

因为用户量有限,网站整体架构比较简单,所以我选择的测试工具是 Google
的 PageSpeed Insights 以及 Yahoo 的 Yslow。

Google 官方的 PageSpeed Tools 针对 Firefox 以及 Google Chrome 都有扩展插件,这里以在线版做一点简单的演示。PageSpeed Tools 在线版网址:https://developers.google.com/speed/pagespeed/。

大家可以访问 这个链接地址 来查看 PageSpeed Tools 给出的评估结果和建议、对于如何优化它有相应的介绍。

工具所给出的修缮细节这里不做详细介绍,感兴趣的童鞋可以使用该工具给自己的网站做一个测试,并结合 PageSpeed Tools 提供的思路和解决方案来做一些优化。

接着可以使用 http://www.webpagetest.org/ 这个在线工具查看每一个元素加载时间具体耗时。

点击图片即可看到清晰的报告:

这里可以看到整个页面从解析 dns 到完全加载所消耗的详细时间,针对耗时严重的节点因地制宜地处理。

二、套路推荐

接下来一些没有技术含量的优化套路(个人觉得适合运维的童鞋)。

1. 升级硬环境配置

所谓工欲善其事、必先利其器。功夫再好,也怕菜刀。通过几个常用的 linux 命令来检测自己机器硬件是否牛逼。

1)查看 CPU

grep “model name” /proc/cpuinfo | cut -f2 -d:

2)查看内存大小及使用情况


3)查看服务器负载情况

命令详解请参考 http://www.jb51.net/article/40807.htm。

4)咨询服务商机器带宽

**

如果这几个数据排查来来结果不理想,请砸钱狠狠升级硬件,把砍柴刀升级到屠龙刀、只要代码层面不是太作死,一般都可以在性能有很大的提升。

非常建议直接选购阿里等大厂优化过软环境参数的高配服务器(如果您有这个想法和条件,后面就不用继继续看下去了,毕竟我的知识深度在大厂的大牛面前不值一提),另外如果图片、JS、CSS、等静态资源等资源,建议选用稳定性及效果比较好的 CDN 加速节点服务。

如果在意 “节点数量” 可选择安全宝。
如果在意 “节点稳定性及 SEO 优化” 可选择百度云加速。
如果在意 “是否免费” 可选择 360 卫士。
如果在意 “功能均衡” 可选择加速乐。

2. 软环境升级

1)升级 PHP

**

如鸟哥惠新宸大大多次提到,PHP7 的性能在多方面都是 PHP5 的 2 倍以上、如果你的代码兼容 PHP5.6,那么放心大胆的把 PHP 环境升级到 7 吧。关于从 5 到 7 性能提升的报告,请参考 鸟哥的 PPT。

如果你对性能的要求非常的极致、那么请使用 PHP7 的强类型模式、一定可以让你获得非常不错的体验。

2)升级 Nginx 版本

Nginx 从 1.7.11 开始实现了线程池机制,大部分场景中可以避免使用阻塞,整体性能有了数倍提升。

如果你还在使用低版本的 Nginx 并且想在并发效率上做一个质的提升,新版本 Nginx 在等到你的召唤。
请参考官网的介绍:

https://www.nginx.com/blog/thread-pools-boost-performance-9x/

3)选择 Mysql 版本

这里建议使用 Mysql 5.6 版本(相对更稳定,更快)。Mysql 5.7 这个版本因为增加了些新特性,普通的软件工程师未必能 Hold 住,当然,如果您公司有大牛 DBA 支持,则建议使用 Mysql5.7 版本。

三、修炼内功

1. PHP 框架的选择和优化

这里强烈建议选择兼容 PHP7 的框架,生产环境配合 PHP7+ 和 Nginx1.7+ 可以在整体的执行效率上好很多,当然如果您习惯类似 CodeIgniter 3 这类不完全兼容 PHP7 的但是轻量级的框架,那么您可以自己修改代码让其兼容 PHP7。

使用框架开发很大可能的会带来一个问题——资源浪费,因为不是每一个框架加载的模块都是我们需要的,那么我们最好移除或禁用相应模块。

比方 Magento1.* 这个庞大的产品,默认开启了 N 多个模块,很多是我们不需要的,笔者在数年的 Mangento 开发和运维中都是依靠禁用相应模块这个方法来给产品加速。

对于这种庞然大物,我也会给它加上一个 Redis 缓存中间件(推荐使用最新稳定版的偶数版本,相对稳定。

关于 redis 的性能测试报告,这里不多介绍,继续请看 推荐的链接。Mysql 数据库这块我会做一个主从复制,读写分离策略。

2. PHP.ini 配置文件的优化

注:默认安装的 PHP 是使用的是一个通用配置,可以正常运行项目,但是不一定是最适合我们的配置,因此最好根据自己的实际情况来调整参数配置,首先建议使用 PHP Iniscan 工具扫描 php.ini,工具会给出一个安全配置方面的建议。

这里谈一下常见的几个配置选项,memory_limit 这个用于设定单个 PHP 进程可以使用的系统内存最大值,从系统可用性上来讲建议越大越好。

笔者曾经遇到过一个项目是 PHP 操作 Redis Set 集合,Set 集合中有 500 万 + 的数据,当时测试下来脚本无法执行。后来通过一个办法解决了,就是修改 php.ini 中的一个参数找到memory_limit,设置到 2G 以上。问题解决了。

当然如果您的项目中每页页面使用的内存不大,建议改成小一些,这样可以承载更多的并发处理。

可以使用 top 命令或者在 PHP 脚本中调用 memory_get_peak_usage()函数多次测试自己项目脚本,来不断修缮以得到一个比较精确的值。

配置 PHP 的 Zend OPcache 扩展,内容较多可以参考 http://laravelacademy.org/post/4396.html,就不多过多介绍了。

php.ini 文件中的 max_execution_time 用于设置单个 PHP 进程在终止之前最长可运行时间。如果您的脚本都是需要较长时间才能执行的,那么设置的大一些,不然建议设置为 5-10 秒之间。

Session 会话放在 Redis 或者 Memcached 中,这么做不仅可以减少磁盘的 IO 操作频率,还可以方便业务服务器伸缩。如果想把会话数据保存在 Memcached 中,需要做如下配置:

session.save_handler = 'memcached'
session.save_path = '127.0.0.1:11211'

真实路径缓存

PHP 会缓存应用使用的文件路径,这样每次包含或导入文件时就无需不断搜索包含路径了,这个缓存叫真实路径缓存(realpath cache),如果运行的是大型的 PHP 文件(如 Composer 组件),使用了大量文件,增加 PHP 真实路径缓存的大小能得到更好的性能。

3. 开启 GZip 压缩

接下来讨论 GZIP 压缩的问题。(gzip 原本是文件压缩格式,扩展名为 .gz,HTTP 协议用它来改进 WEB 应用程序性能,加快 HTTP 请求返回内容的下载速度,降低网络带宽占用。)

http://tool.chinaz.com/Gzips/

使用该工具可以查看我们的网站是否开起来 Gzip 压缩功能。

该工具既可以测试 gzip 是否已开启,也可以测试页面加载的时间。针对 php 常用的环境 apache 和 nginx 我们分别来看看如何开启 gzip 压缩。

1)首先检查我们的服务器是否安装了 mod_so.c

apachectl -l

发现 mod_so.c,ok 可以动态加模块,不用重新编译。

Apache ☞修改 httpd.conf。编辑 httpd.conf,配置mod_deflate。对下类型文件的开启mod_deflate

DeflateCompressionLevel 9 AddOutputFilterByType DEFLATE text/htmltext/plaintext/csstext/xmltext/javascript AddOutputFilter DEFLATE css js SetOutputFilter DEFLATE SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzipdont-vary SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzipdont-vary SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzipdont-vary

这里需要注意的是LoadModule deflate_module需要放在LoadModule php5_module之后。

DeflateCompressionLevel 为压缩级别 1-9 ,数字越高说明压缩比越大,同时更占用 CPU 资源。默认建议从 4 开始设置根据实际情况调整。

2)添加到 httpd.conf 的文件尾,去掉注释


DeflateCompressionLevel 4 # 压缩程度的等级
AddOutputFilterByType DEFLATE text/htmltext/plaintext/csstext/xmltext/javascript#特定的 MIME 类型指定输出过滤器
AddOutputFilter DEFLATE css js#压缩后输出
SetOutputFilter DEFLATE # 插入过滤器,对所有输出启用压缩
@#不压缩图片、视频
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzipdont-vary
SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzipdont-vary
SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzipdont-vary

3)参考内容

DeflateCompressionLevel 4 AddOutputFilterByType DEFLATE text/htmltext/plaintext/csstext/xmltext/javascript AddOutputFilter DEFLATE css js SetOutputFilter DEFLATE SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzipdont-vary SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzipdont-vary SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzipdont-vary

这段代码在配置文件里面添加的时候要去掉注释,不然 apache 启动的时候会报错。

4)重启 apache,让配置生效

或将此内容放到网站根目录下的 .htaccess 文件中:

DeflateCompressionLevel 4 AddOutputFilterByType DEFLATE text/htmltext/plaintext/csstext/xmltext/javascript AddOutputFilter DEFLATE css js SetOutputFilter DEFLATE SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzipdont-vary SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzipdont-vary SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzipdont-vary

Nginx 下的 Gzip 开启方法:打开 nginx.conf,找到如下一段,进行修改。

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 4;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";

注解一下:

  • 第 1 行:开启 Gzip。

  • 第 2 行:不压缩临界值,大于 1K 的才压缩,一般不用改。

  • 第 3 行:buffer,缓冲大小,不用改。

  • 第 4 行:用了反向代理的话,末端通信是 HTTP/1.0,有需求的应该也不用看我这科普文了;有这句的话注释了就行了,默认是 HTTP/1.1。

  • 第 5 行:压缩级别,1-10,数字越大压缩的越好,时间也越长,建议从 4 开始测试(根据实际项目调试)。

  • 第 6 行:进行压缩的文件类型,缺啥补啥就行了,JavaScript 有两种写法,最好都写上吧,总有人抱怨 js 文件没有压缩,其实多写一种格式就行了。

  • 第 7 行:跟 Squid 等缓存服务有关,on 的话会在 Header 里增加 “Vary: Accept-Encoding”,我不需要这玩意,自己对照情况看着办吧。

  • 第 8 行:IE6 对 Gzip 不怎么友好,不给它 Gzip 了。

保存后重启 nginx,然后用 http://tool.chinaz.com/Gzips/ 这个工具测试一下是否生效了。

从图片上可以看出,没压缩和压缩之间是差了很多的。

同时可以考虑禁用 Apache 和 Nginx 内置的我们用不到的模块,这样可以释放不少的系统资源出来。通过 apachectl -M 命令列举当前服务器加载的模块。

可以到 httpd.conf 文件中把不需要的模块哪一行前面加个#号把它干掉。

4. 优化 Nginx 的配置

通常情况下,nginx 默认的配置都不是最适合当前服务器硬件条件的,当我们提高了硬件环境后,nginx 的软配置也要做相应的修改,Nginx 提供 2 个参数来适配,分别是nginx worker_processesworker_connections

worker_processes是表示工作进程的数量,但是这个值应该怎么设置呢?理论上来说按照 cpu 核心数的倍数来设置是没错的,但是到底是几倍呢?有的人说是有多少个核心就设置多少个进程,还有种说法是设成 cpu 核心数的两倍。这里建议设置成核心数即可。

同时不要忘了设置worker_cpu_affinity,这个配置用于将 worker process 与指定 cpu 核绑定,降低由于多 CPU 核切换造成的寄存器等现场重建带来的性能损耗。这个配置的修改请参考:

https://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity

接着是worker_connections的设置,安装好 nginx 之后,其初始最大的并发数为 1024,如果你的网站访问量已经远远超过这个并发数,那你就要修改worker_connecions这个值 ,这个值越大,并发数也有就大。不过必须根据实际情况,不能让你的 CPU 负载太高。

如果你修改提高了配置文件中的worker_connections值,重启 nginx 后在日志里发现一个 warn 警告提示,大概的意思就是: 20000 并发连接已经超过了打开文件的资源限制:1024!

在这种情况下,我们就要修改配置文件,添加一行来解除这个限制,这就好像是 apache 中的 ServerLimit。

打开配置文件在 “event” 这行上面添加这一行:

worker_rlimit_nofile   xxxxx;           ####Specifies the value for maximum file descriptors that can be opened by this process.

注意:设置了这个后,你修改worker_connections值时,是不能超过worker_rlimit_nofile的这个值,不然又会有前面的那个 warn 提示。保存配置文件,退出重启 nginx。

如果 nginx 中worker_connections 值设置是 1024,worker_processes值设置是 4,按反向代理模式下最大连接数的理论计算公式:最大连接数 = worker_processes * worker_connections/4建议生产环境中worker_connections建议值设置为 10240,运行一段时间后和优化前做一下对比,慢慢找到一个适合自己服务器的值。

如果你的网站都是静态资源,可以试试如下配置,并发可以做的更大。Nginx 指令中的优化(配置文件):

worker_processes 8;

nginx 进程数,建议按照 cpu 数目来指定,一般为它的倍数。

worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

为每个进程分配 cpu,上例中将 8 个进程分配到 8 个 cpu,当然可以写多个,或者将一个进程分配到多个 cpu。

worker_rlimit_nofile 102400;

这个指令是指当一个 nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与 nginx 进程数相除,但是 nginx 分配请求并不是那么均匀,所以最好与 ulimit -n 的值保持一致。

use epoll;

使用 epoll 的 I/O 模型,这个不用说了吧。

worker_connections 102400;

每个进程允许的最多连接数,理论上每台 nginx 服务器的最大连接数为:

worker_processes*worker_connections。

keepalive_timeout 60;

keepalive 超时时间。

client_header_buffer_size 4k;

客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过 1k,不过由于一般系统分页都要大于 1k,所以这里设置为分页大小。

分页大小可以用命令 getconf PAGESIZE 取得。

open_file_cache max=102400 inactive=20s;

这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。

open_file_cache_valid 30s;

这个是指多长时间检查一次缓存的有效信息。

open_file_cache_min_uses 1;

open_file_cache指令中的 inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在 inactive 时间内一次没被使用,它将被移除。内核参数的优化:

net.ipv4.tcp_max_tw_buckets = 6000

timewait 的数量,默认是 180000。

net.ipv4.ip_local_port_range = 1024    65000

允许系统打开的端口范围。

net.ipv4.tcp_tw_recycle = 1

启用 timewait 快速回收。

net.ipv4.tcp_tw_reuse = 1

开启重用。允许将 TIME-WAIT sockets 重新用于新的 TCP 连接。

net.ipv4.tcp_syncookies = 1

开启 SYN Cookies,当出现 SYN 等待队列溢出时,启用 cookies 来处理。

net.core.somaxconn = 262144

web 应用中 listen 函数的 backlog 默认会给我们内核参数的 net.core.somaxconn 限制到 128,而 nginx 定义的NGX_LISTEN_BACKLOG默认为 511,所以有必要调整这个值。

net.core.netdev_max_backlog = 262144

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

net.ipv4.tcp_max_orphans = 262144

系统中最多有多少个 TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。

这个限制仅仅是为了防止简单的 DoS 攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。

net.ipv4.tcp_max_syn_backlog = 262144

记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有 128M 内存的系统而言,缺省值是 1024,小内存的系统则是 128。

net.ipv4.tcp_timestamps = 0

时间戳可以避免序列号的卷绕。一个 1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种 “异常” 的数据包。这里需要将其关掉。

net.ipv4.tcp_synack_retries = 1

为了打开对端的连接,内核需要发送一个 SYN 并附带一个回应前面一个 SYN 的 ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送 SYN+ACK 包的数量。

net.ipv4.tcp_syn_retries = 1

在内核放弃建立连接之前发送 SYN 包的数量。

net.ipv4.tcp_fin_timeout = 1

如果套接字由本端要求关闭,这个参数决定了它保持在 FIN-WAIT-2 状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是 60 秒。2.2 内核的通常值是 180 秒,你可以按这个设置。

但要记住的是,即使你的机器是一个轻载的 WEB 服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2 的危险性比 FIN-WAIT-1 要小,因为它最多只能吃掉 1.5K 内存,但是它们的生存期长些。

net.ipv4.tcp_keepalive_time = 30

当 keepalive 起用的时候,TCP 发送 keepalive 消息的频度。缺省是 2 小时。

5. 全页面缓存

假如我们的网站是博客,新闻等静态信息,我们可以把页面全部静态化、这样网站就变成了类似静态 html 页面。代码层面可以参考一下这里:

http://www.jb51.net/article/59693.htm

这里再推荐一个工具 Varnish,可以做全页面动态缓存,也可以实现负载均衡,减轻服务器压力。本次 Chat 里就不做深入探讨,感兴趣的可以参考:

http://www.drupal001.com/2011/12/varnish-drupal-basic/

也可以利用缓存模块(如 Memcache)或者模板系统(如 Smarty)进行缓存处理。我们可以缓存数据库结果和提取页面结果的方式来提升网站性能。也可以网站部署环境安装 APC 或者 Xcache 缓存能够有效提升网站运行性能和内存占用。

XCache 是一个开源的 opcode 缓存器 / 优化器 , 这意味着他能够提高您服务器上 的 PHP 性能 . 他通过把编译 PHP 后的数据缓冲到共享内存从而避免重复的编译 过程 , 能够直接使用缓冲区已编译的代码从而提高速度 . 通常能够提高您的页面生 成速率 2 到 5 倍 , 降低服务器负载。

Alternative PHP Cache (APC) 是一种对 PHP 有效的开放源高速缓冲储存器工具,它能够缓存 opcode 的 php 中间码。

6. 静态资源合并

这里主要从 css,js 这两个方面来下手,客户访问我们的网站,是需要将我们服务器上的各种资源全部加载到他电脑本地的,因此我们服务器里面的内容减轻一些,传输给客户的内容也就少一些。

js 和 css 中的空格,换行,注释,空行等也都是需要占用空间的,因此我们建议使用 Minify 这个 PHP 编写的库来操作。

为节省篇幅,操作的方法和介绍请参考 https://www.cnblogs.com/simaosu/p/3735784.html。

7. Nginx.conf 响应时间优化

是 Nginx+Php-fpm,于是通过 find / -name nginx.conf,命令找到 Nginx.conf 这个文件。

修改 Nginx.conf 的配置如图:

重启 Nginx 后了。即不存在这个脚本超时的问题了。

8. Mysql 参数及策略

因为 php 主要是与 Mysql 做交互用的多的就是优化索引、分表分库这些思想,可以多参考沈剑老师的一些文章。这里也推荐一个 Mysql 优化的文章。

另外,笔者曾经遇到过一个问题,就是 B2C 商城在商品数据较多时候遇到的加载问题、网站前后台加载的都非常的慢、最终排查下来是 mysql 的配置中有个 buffer 太低,但是需要从 Mysql 中读取出来的数据非常大。

My.cnf 中read_buffer_size = 2M修改为read_buffer_size = 512M (MySQL 读入缓冲区大小)、query_cache_limit = 2M修改为 200M(指定单个查询能够使用的缓冲区大小)后解决该问题。

鉴于此我对 My.cnf 这一块做了一些优化,整体的提升了网站访问的性能。back_log = 600,MySQL 能有的连接数量。max_connections = 1000,MySQL 的最大连接数。

8. 业务分离

如果您有兴致读完了以上的内容并且觉得很无聊,那么笔者这里在分享一个实用的小想法吧,我们可以把业务模块,Redis 缓存模块,Mysql 数据库,图片存储,静态资源等分别放在不同的服务器上(同机房)。

这样不同的业务由不同的服务器处理,可以增加网站系统的整体性能。

9. 开启 Keep-alive

Aapche 下的操作方法:

修改 httpd.conf 中

KeepAlive: Whether or not to allow persistent connections (more than one request per connection). Set to "Off" to deactivate.

Keep-Alive on

MaxKeepAliveRequests: The maximum number of requests to allow during a persistent connection. Set to 0 to allow an unlimited amount. We recommend you leave this number high, for maximum performance.

MaxKeepAliveRequests 0

KeepAliveTimeout: Number of seconds to wait for the next request from the same client on the same connection.

KeepAliveTimeout 15 # 客户端发送 HTTP 请求成功之后,Apache 将不会立刻断开 socket,而是一直监听客户端这一请求,持续时间为 15 秒,如果超过这一时间,Apache 就立即断开 socket。

注意:Apache 的版本为 2.0 以上。

Nginx 下的 nginx.conf 配置

默认情况下,nginx 已经自动开启了对 client 连接的 keep alive 支持(同时 client 发送的 HTTP 请求要求 keep alive)。一般场景可以直接使用,但是对于一些比较特殊的场景,还是有必要调整个别参数(keepalive_timeoutkeepalive_requests)。

第一个参数:设置 keep-alive 客户端连接在服务器端保持开启的超时值(默认 75s);值为 0 会禁用 keep-alive 客户端连接;第二个参数:可选、在响应的 header 域中设置一个值 “Keep-Alive: timeout=time”;通常可以不用设置。

  • 1)keepalive_timeout 默认 75s,一般情况下也够用,对于一些请求比较大的内部服务器通讯的场景,适当加大为 120s 或者 300s;

  • 2)keepalive_requests指令用于设置一个 keep-alive 连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭。默认是 100。

    这个参数的真实含义,是指一个 keep alive 建立之后,nginx 就会为这个连接设置一个计数器,记录这个 keep alive 的长连接上已经接收并处理的客户端请求的数量。

    如果达到这个参数设置的最大值时,则 nginx 会强行关闭这个长连接,逼迫客户端不得不重新建立新的长连接。

大多数情况下当 QPS(每秒请求数)不是很高时,默认值 100 凑合够用。但是,对于一些 QPS 比较高(比如超过 10000QPS,甚至达到 30000,50000 甚至更高) 的场景,默认的 100 就显得太低。

简单计算一下,QPS=10000 时,客户端每秒发送 10000 个请求 (通常建立有多个长连接),每个连接只能最多跑 100 次请求,意味着平均每秒钟就会有 100 个长连接因此被 nginx 关闭。

同样意味着为了保持 QPS,客户端不得不每秒中重新新建 100 个连接。因此,就会发现有大量的TIME_WAIT的 socket 连接(即使此时 keep alive 已经在 client 和 nginx 之间生效)。

因此对于 QPS 较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少TIME_WAIT

更细致的内容我们可以在 chat 交流的时候,好好的交流,谢谢!

近期热文

Web 安全:前端攻击 XSS 深入解析

300万粉丝,全国最大的线上抽奖平台,深度解析

高可用、高性能? 接口设计的 16 个原则

【钓鱼】与【反钓鱼】的技术剖析

快速了解 Java 9 平台模块系统

「阅读原文」看交流实录,你想知道的都在这里