压测是确定系统稳定性的一种测试方法,在系统正常运行范围之外进行,主要测试功能极限和隐患。针对游戏的压测从传统意义上来说就是对网络服务的服务器不断施加“压力”,也就是通过确定一个系统的瓶颈或不能接收的性能点,来获得系统能提供的最大服务级别的测试。主要用来检查游戏服务器的承受能力,包括用户承受能力和流量承受能力。
环境参数
软件环境
$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
$ nginx -v
nginx version: nginx/1.14.1
$ php -v
PHP 7.2.6 (cli) (built: Feb 13 2019 20:01:18) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
$ mysql --version
mysql Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using EditLine wrapper
LNMP优化的手段主要包括
- 文件句柄数量
- PHP 缓存
- Nginx编译
- Nginx pagespeed
- Nginx 缓存
- Nginx 压缩
- Nginx CPU绑定
Nginx
Nginx处理PHP请求的流程
- 接收请求若发现是PHP请求则转入第2步
- 通过
socket
方式连接PHP-FPM
的FastCGI,让PHP-FPM处理请求。 - 获取PHP-FPM处理结果,并附加HTTP报头,返回给客户端。
提高Nginx的PHP并发性
- 调整Nginx的并发连接数
worker_connections 51200;
worker_connections
指令表示每个工作进程允许的最大连接数,也就是每个worker进程能并发处理的最大连接数(包含所有连接数),理论上单台Nginx
服务器的最大连接数为 worker_processes * worker_connections
。
worker_processes auto;
worker_processes
指明了Nginx要开启的进程数量,官方建议开一个就可以了,多开可以减少磁盘IO带来的影响,一般为当前机器CPU核心数量的1到2倍。worker_processes
指令表示Nginx进程数,建议按照CPU数量来指定,一般为它的倍数,例如2个四核CPU则计算为8。
- 调整PHP-FPM的并发连接数
$ sudo find /etc/php/fpm -name * | xargs grep "max_children"
- 调整系统的最大文件数量限制
由于Nginx处理PHP请求的第二步需要通过Socket和PHP-FPM通信,Nginx能够建立的最大Socket数量受到系统最大打开文件数量的限制,Linux默认只有1024。
# 查看当前系统最大打开文件数量
$ ulimit -n
# 将系统最大打开文件数量临时修改为65535,系统重启后会失效。
$ ulimit -n 65535
# 永久修改系统最大打开文件数量
$ vim /etc/security/limits.conf
# * 表示所有用户,noproc表示最大进程数量
* soft noproc 11000
* hard noproc 11000
# * 表示所有用户,nofile表示最大文件打开数量
* soft nofile 65535
* hard nofile 65535
Nginx核心配置
$ vim /usr/local/nginx/conf/nginx.conf
打开Nginx的配置文件,具体配置项目如下:
worker_rlimit_nofile 51200;
-
worker_rlimit_nofile
指令表示一个nginx进程打开文件描述符的最大数量,建议与Linux的ulimit -n
的值保持一致。 - Linux内核下开启文件打开数量为65535,Nginx的
worker_rlimit_nofile
最好与之保持一致。
use epoll;
-
epoll
是多路复用I/O中的一种方式,仅用于Linux2.6+
内核,可大大提高Nginx的性能。
keepalive_timeout 60;
-
keepalive
超时时间
client_header_buffer_size 32k;
-
client_header_buffer_size
表示客户端请求头部的缓冲区大小,可根据系统分页大小来设置,一般请求头大小不超过1KB
。
Ngnix的HTTP配置
# KeepAlive 超时时长
keepalive_timeout 60;
# 客户端请求内容的缓存区大小
client_body_buffer_size 64K;
# 客户端请求头部的缓冲区大小,可以根据系统的分页大小来设置。
client_header_buffer_size 8K;
large_client_header_buffers 4 128K;
# 客户端请求内容的最大值
client_max_body_size 8m;
# 打开文件的缓存,max是指缓存的最大数量,inactive指缓存过期时间。
open_file_cache max=1024 inactive=30s;
# 检查缓存的有效时间
open_file_cache_valid 30s;
# inactive参数的时间内文件的最少使用次数,若超过则保持缓存的打开状态。
open_file_cache_min_uses 1;
# 读取FastCGI返回信息的缓冲数量和大小
fastcgi_buffers 8 32k;
# 读取FastCGI服务器响应头部的缓冲区大小
fastcgi_buffer_size 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
# 连接到后端FastCGI的超时时间
fastcgi_connect_timeout 120;
# 向FastCGI传送请求的超时时间
fastcgi_send_timeout 120;
# 接收FastCGI应答的超时时间
fastcgi_read_timeout 120;
PHP-FPM
$ vim /usr/local/php/etc/php-fpm.conf
# 进程管理方式:动态dynamic、静态static
pm = dynamic
pm
参数指定了进程管理方式:
- 静态方式:在PHP-FPM启动的时候就创建了指定数量的进程,在运行过程中不会再有变化,但并不是真的就永远不变了。
- 动态方式:在运行过程中动态调整,当然也不是无限制的创建新进程,它受到
pm.max_spare_servers
参数的影响。
简单来说,动态方式适合小内存机器,静态方式适用于大内存机器。动态方式,灵活分配进程,比较节省内存,但同时动态创建回收进程对服务器资源也是一种消耗。
# 最大子进程数量,决定了php-fpm的总进程数量。
pm.max_children = 100
pm.start_servers = 30
pm.min_spare_servers = 20
pm.max_spare_servers = 100
# 每个子进程重启之前服务的请求数量,存在内存泄漏时比较有用。
# 最大请求数量,php-fpm进程响应500个并发请求后会自动重启进程。
pm.max_requests = 500
# 请求客户端延迟,表示等待100秒后会自动结束那些没有自动结束的php脚本以释放占用的资源。
request_terminate_timeout = 100
# 打开文件描述符的限制,可使用ulimit -n查看
rlimit_files = 65535
查看php-fpm
日志
$ tail -f /usr/local/var/log/php-fpm.log
[29-Mar-2019 11:16:20] WARNING: [pool www] child 30455 exited on signal 15 (SIGTERM) after 1200.089506 seconds from start
[29-Mar-2019 11:16:20] NOTICE: [pool www] child 31682 started
Webbench
- Webbench是由Lionbridge公司开发的网站压力测试工具
- Webbench标准测试可以展示服务器的两项内容:每秒请求数量、每秒传输数据量
- Webbench最多可模拟3w并发连接
# 下载
$ wget http://blog.zyan.cc/soft/linux/webbench/webbench-1.5.tar.gz
# 解压
$ tar -zxvf webbench-1.5.tar.gz
# 进入文件夹
$ cd webbench-1.5
# 编译安装
$ make && make install
使用说明
$ webbench -c 500 -t 30 http://119.23.16.104:81/api/login/login_te
# 参数说明:-c表示并发数,-t表示时间(秒)
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
# 模拟500个客户端在30秒内向接口发送请求
Benchmarking: GET http://hostname/api/login
500 clients, running 30 sec.
# 每秒钟传输数据量:每分钟平均有22578次请求连接,服务器每秒传输字节为122599。
Speed=22578 pages/min, 122599 bytes/sec.
# 每秒钟相应请求数:在30秒期间请求连接成功为11289次,失败0次。
Requests: 11289 susceed, 0 failed.
MySQL
MySQL默认配置为my.cnf
,系统已提供可选的配置文件。
$ ll /usr/local/mysql/share/mysql/
# 适合1GB~2GB的RAM
my-huge.cnf
# 适合512MB的RAM
my-large.cnf
# 适合32MB~64MB的RAM
my-medium.cnf
# 适合小于64MB的RAM
my-small.cnf
# 适合4G+的RAM
my-innodb-heavy-4G.cnf
硬件负载
在压测期间,可使用top
命令,观察目标服务器上性能变化。
# 查看CPU负载情况
$ top
# 查看内存使用情况
$ free -m
# 查看磁盘IO情况
$ iostat -kx 2
# 查看网络流量情况
# sar -n DEV 2