Nginx代理缓存配置

Nginx代理缓存配置

引言

反向代理每次都回源取页面,后端压力大、首屏慢。Nginx自带proxy_cache,把后端响应存到本地磁盘,命中时直接返回,既减轻源站又加快响应,适合静态资源和不常变的页面。

定义缓存区

http块里先声明缓存目录和大小:

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m max_size=1g inactive=7d;
  • keys_zone=mycache:10m 是缓存名和索引内存;
  • max_size=1g 磁盘上限;
  • inactive=7d 7天没访问自动清理。

代理站点启用缓存

server或location块:

location / {
    proxy_cache mycache;
    proxy_cache_key $host$uri$is_args$args;
    proxy_cache_valid 200 304 1h;
    proxy_cache_valid 404 1m;
    proxy_cache_methods GET HEAD;
    proxy_pass http://backend;
}

200/304缓存1小时,404只存1分钟。

命中状态标识

加响应头方便排查:

add_header X-Cache-Status $upstream_cache_status;

HIT命中、MISS未命中、EXPIRED过期、BYPASS绕过。

绕过缓存的场景

登录后动态内容不缓存:

proxy_no_cache $http_cookie;
proxy_cache_bypass $http_cookie;

带cookie时不读不写缓存。

主动清除缓存

# 配置删除接口需要第三方模块或手动删目录
rm -rf /data/nginx/cache/*

更新内容后清对应目录,或按URL前缀匹配删除。

注意事项

  • 缓存目录要先mkdir并给nginx读写权限;
  • 带POST的接口不要缓存;
  • 频繁变动的页面缓存时间设短或不缓存;
  • 缓存键要带参数,避免不同query串内容;
  • 配置改完nginx -t校验再reload;
  • 大文件下载用分片缓存更稳妥。

总结

proxy_cache_path在http块定义缓存区,location里proxy_cache启用、proxy_cache_valid设有效期、proxy_cache_key拼缓存键,用X-Cache-Status看命中。静态和低频页面开缓存扛压力,动态登录内容用cookie绕过,更新后及时清理。


emer 发布于  2026-10-19 07:29 

Nginx静态缓存配置

Nginx静态缓存配置

引言

CSS、JS、图片、字体这类不变的静态资源,每次都回源取一遍浪费带宽和时间。用Nginx给静态资源加浏览器缓存响应头,让浏览器本地留存,第二次访问直接读本地,首屏和重复访问速度明显提升。

配置示例

在server或location块中:

location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff2?)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

参数说明

  • expires 30d:设置缓存30天,浏览器本地留存;
  • Cache-Control public:允许中间缓存(CDN、代理);
  • immutable:文件内容不变,缓存期内不再发条件请求;
  • access_log off:静态资源不记访问日志,减少IO。

带版本号更新

静态文件内容更新后,旧缓存会导致用户看到老文件。常用办法是文件名带哈希或版本,如app.[hash].js,内容一变文件名就变,浏览器当成新文件重新下载:

# 配合构建工具输出的带hash文件名,缓存可拉长到一年
expires 1y;

动态文件不要长缓存

HTML页面、接口响应要短缓存或不缓存,避免用户看到过期页面:

location / {
    add_header Cache-Control "no-cache";
}

验证方法

浏览器F12网络面板看响应头:Cache-Control、Expires,再看状态码,二次访问200 from disk/memory cache即生效。

注意事项

  • 缓存过期时间按资源稳定性设置,图片长、HTML短;
  • 更新静态资源靠改文件名版本号,而不是缩短缓存;
  • 不要给动态接口、登录页面加public长缓存;
  • 改配置后nginx -t检查再reload。

总结

Nginx静态缓存用expires加Cache-Control给css/js/图片设置本地缓存,稳定资源配合版本号长缓存,动态页面不缓存。浏览器F12验证响应头,平衡访问速度与内容新鲜度。


emer 发布于  2026-10-18 07:31 

Nginx开启Gzip压缩

Nginx开启Gzip压缩

引言

HTML、CSS、JS、JSON这类文本资源直接传输体积大,首屏慢。Nginx开启Gzip后,服务端先压缩再发送,浏览器解压,通常文本体积能减少60%以上,是零成本提升访问速度的手段。

配置示例

在http块或server块加入:

gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";

参数说明

  • gzip on:开关;
  • gzip_min_length:小于1k不压缩,避免小文件压缩得不偿失;
  • gzip_comp_level:压缩等级1-9,6比较均衡,太高CPU占用大;
  • gzip_types:指定压缩的MIME类型,text/html默认自带;
  • gzip_vary on:响应加Vary:Accept-Encoding,避免缓存问题;
  • gzip_disable:兼容老旧IE浏览器。

生效验证

改完执行nginx -t检查语法,再reload。浏览器F12网络面板看响应头Content-Encoding:gzip即生效。

注意事项

  • 图片、视频、PDF本身已压缩,不要再gzip,浪费CPU;
  • 压缩等级不要盲目拉满,大文件压缩吃CPU;
  • 静态资源可在CDN层提前压缩;
  • 配合Brotli现代压缩效果更好,需Nginx额外模块支持。

总结

Gzip是文本类资源提速标配,开启后配置类型、大小阈值、合理压缩等级,reload生效,用响应头验证。不压缩图片视频,平衡传输体积与服务器CPU。


emer 发布于  2026-10-18 07:27 

PHP FPM进程过多导致服务器卡顿优化

前言

PHP FPM进程太多,把服务器内存吃满,网站卡顿甚至502?本文讲怎么优化PHP FPM进程数。

一、为什么FPM进程多会卡

PHP FPM每处理一个请求,就开一个进程。

进程开多了:

  • 内存占满
  • CPU切换不过来
  • 服务器卡顿
  • 甚至OOM被杀

二、查看当前进程数

查看PHP FPM进程

ps aux | grep php-fpm

数一下有多少个进程。

看每个进程占多少内存

ps aux | grep php-fpm | awk '{print $6/1024 "MB"}'

算一下总内存

ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/1024 "MB"}'

三、FPM配置文件在哪

CentOS

/etc/php-fpm.d/www.conf

或者:

/etc/php/7.4/fpm/pool.d/www.conf

Ubuntu

/etc/php/7.4/fpm/pool.d/www.conf

四、进程管理模式

PHP FPM有三种进程管理模式:

1. static(静态)

固定进程数,启动就开这么多。

pm = static
pm.max_children = 50

2. dynamic(动态)

默认模式,按需开进程。

pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35

3. ondemand

没人访问的时候不开进程,来了请求才开。

pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s

五、怎么算合适的进程数

公式

pm.max_children = 可用内存 / 每个进程平均内存

例子

  • 服务器2G内存
  • 系统和其他服务占1G
  • 剩下1G给PHP
  • 每个PHP进程平均占40M
pm.max_children = 1024 / 40 ≈ 25

所以设25个进程差不多。

别设太大

设太大了,内存不够用,就会OOM。

六、推荐配置

小服务器(1G内存)

pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5

中服务器(2-4G内存)

pm = dynamic
pm.max_children = 30
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20

大服务器(8G以上)

pm = dynamic
pm.max_children = 80
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 40

七、其他优化参数

request_terminate_timeout

单个请求最长执行时间,超时就杀掉。

request_terminate_timeout = 30s

slow log

慢日志,看看哪个请求慢。

slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 10s

php_admin_value[memory_limit]

每个PHP进程的内存限制。

php_admin_value[memory_limit] = 128M

八、改完配置重载

systemctl reload php-fpm

或者:

systemctl restart php-fpm

九、验证效果

看进程数

ps aux | grep php-fpm | wc -l

看内存

free -h

看负载

top

十、常见坑

坑1:max_children设太大

比如2G内存设了100个进程,内存直接爆。

解决: 按上面的公式算,别拍脑袋。

坑2:改完配置不生效

忘了重载。

解决:

systemctl reload php-fpm

坑3:进程数一直涨

有慢请求,占着进程不放。

检查:

request_terminate_timeout = 30s

设个超时,超时就杀。

坑4:502 Bad Gateway

进程都忙不过来,Nginx连不上FPM。

解决: 加max_children,或者优化慢请求。

坑5:用了static模式

static固定进程数,不用就浪费内存。

推荐: 用dynamic或ondemand。

十一、排查步骤

第一步:看是不是FPM进程多

ps aux | grep php-fpm | wc -l

第二步:看内存够不够

free -h

第三步:看有没有慢请求

tail -f /var/log/php-fpm/slow.log

第四步:调整配置

改www.conf里的pm.max_children等参数。

第五步:重载验证

systemctl reload php-fpm

总结

记住:

  1. 进程数别设太大,按内存算
  2. 公式:可用内存 / 每个进程平均内存
  3. 推荐用dynamic模式
  4. 设个request_terminate_timeout,防慢请求占着进程
  5. 改完记得reload

推荐配置:

pm = dynamic
pm.max_children = 30
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
request_terminate_timeout = 30s

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-8 08:29 

MySQL 性能优化实战

MySQL 性能优化实战

数据库慢是网站性能的大问题,这篇讲实战优化方法,从几个方面下手。

1. 慢查询排查

先找到慢SQL,再优化。

开启慢查询日志:

-- 查看是否开启
SHOW VARIABLES LIKE 'slow_query_log%';

-- 开启慢查询
SET GLOBAL slow_query_log = ON;

-- 设置慢查询阈值(秒)
SET GLOBAL long_query_time = 1;

用 explain 分析:

EXPLAIN SELECT * FROM users WHERE name = '张三';

重点看:

  • type:有没有用到索引(ref/const 好,ALL 全表扫描坏)
  • key:实际用的索引
  • rows:扫描行数

2. 索引优化

建索引原则:

  • where 条件经常用的字段建索引
  • 联合索引最左前缀原则
  • 避免建太多索引,影响写入

查看索引:

SHOW INDEX FROM users;

建索引:

-- 普通索引
CREATE INDEX idx_name ON users(name);

-- 联合索引
CREATE INDEX idx_name_age ON users(name, age);

-- 唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);

3. SQL 优化

**不要 SELECT ***

-- 坏
SELECT * FROM users WHERE id = 1;

-- 好
SELECT id, name, email FROM users WHERE id = 1;

避免 LIKE 前导模糊:

-- 坏(用不到索引)
SELECT * FROM users WHERE name LIKE '%张%';

-- 好(能用索引)
SELECT * FROM users WHERE name LIKE '张%';

大表分页优化:

-- 坏(深度分页慢)
SELECT * FROM users LIMIT 100000, 10;

-- 好(子查询先定位)
SELECT * FROM users 
WHERE id >= (SELECT id FROM users LIMIT 100000, 1) 
LIMIT 10;

4. 表结构优化

  • 用合适的数据类型(能用 int 就别用 bigint)
  • 字段尽量 NOT NULL
  • 大表分表分库

5. 配置优化

my.cnf 常用配置:

# 缓冲池大小(内存的 70%)
innodb_buffer_pool_size = 1G

# 连接数
max_connections = 500

# 慢查询日志
slow_query_log = 1
long_query_time = 1

6. 总结

MySQL 优化三步走:

  1. 找慢SQL: 慢查询日志 + explain
  2. 加索引: where 条件字段
  3. 优化SQL: 不写 SELECT *,避免全表扫描

数据库优化不是一蹴而就,要持续监控和调整。


emer 发布于  2026-10-7 07:14 

Redis 缓存雪崩解决

Redis 缓存雪崩解决方案

缓存雪崩是 Redis 最常见的线上事故之一,搞懂怎么预防,关键时刻能救命。

1. 什么是缓存雪崩

大量缓存同时过期,或者 Redis 整个挂了,所有请求都打到数据库,数据库瞬间压力爆炸,直接崩溃。

就像雪崩一样,一层压一层,全完了。

2. 和缓存穿透、击穿的区别

穿透:查不存在的数据,缓存挡不住,一直打数据库。

击穿:一个热点 key 突然过期,瞬间大量请求打数据库。

雪崩:大量 key 同时过期,或者 Redis 挂了,整个数据库被打垮。

3. 解决方案一:过期时间加随机值

最常用的方法。不要所有 key 都设一样的过期时间,在基础时间上加随机数:

// 不好:所有 key 都 1 小时过期
$redis->setex('product:1', 3600, $data);

// 好:基础 1 小时,加 0-600 秒随机
$ttl = 3600 + rand(0, 600);
$redis->setex('product:1', $ttl, $data);

这样过期时间分散开,不会一起失效。

4. 解决方案二:热点数据永不过期

热点数据不要主动设过期,后台异步更新:

// 商品详情这种热点数据,不设过期
$redis->set('product:1', $data);

// 后台定时任务更新
// 不依赖过期时间,由程序控制刷新

5. 解决方案三:Redis 高可用

Redis 自己要高可用,不能单点:

  • 主从架构 + 哨兵,主挂了自动切从
  • Redis Cluster 集群,分片存储,一个节点挂了不影响全局
# Redis Sentinel 哨兵配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000

6. 解决方案四:熔断降级

数据库撑不住的时候,要能自动降级:

  • 限流:用令牌桶、漏桶算法,限制请求量
  • 降级:返回默认数据或者"系统繁忙"
  • 熔断:数据库连续报错多了,直接不访问数据库

常用工具:Sentinel、Hystrix。

7. 解决方案五:多级缓存

不要只靠 Redis 一层缓存:

用户请求 → 浏览器缓存 → CDN → Nginx 本地缓存 → Redis → 数据库

多级缓存,就算 Redis 挂了,前面还有 Nginx 缓存挡着。

8. 应急处理

真出问题了怎么办:

  1. 先限流,别让数据库被打死
  2. 恢复 Redis 服务
  3. 重新预热热点数据
  4. 慢慢放开流量

总结

缓存雪崩解决方案:

  • 过期时间加随机值,别一起失效
  • 热点数据永不过期,后台更新
  • Redis 做高可用集群
  • 加熔断限流兜底
  • 多级缓存层层防护

记住这几点,缓存雪崩就不怕了。


emer 发布于  2026-10-6 07:39 

MySQL性能优化实战,从这几个方面下手

前言

做网站开发或者运维的同学肯定都遇到过这种情况:网站越来越慢,数据库CPU占用越来越高,用户体验越来越差。这时候怎么办?很多同学一上来就说:加机器!加内存!其实这是最笨的方法。

MySQL性能优化是一个系统工程,要从多个方面下手:SQL、索引、表结构、配置参数、架构。很多时候,不用加机器,只要优化一下SQL和索引,性能就能提升好几倍。

这篇文章就把MySQL性能优化的完整思路整理出来,从定位问题到SQL优化、表结构优化、参数优化、架构优化,一步一步讲清楚。看完之后你就知道遇到性能问题应该从哪里下手了。

一、优化之前先定位问题

很多同学一上来就瞎优化,优化了半天也不知道有没有效果。正确的做法是:先定位问题,再针对性优化。

怎么定位慢SQL

1. 开启慢查询日志

MySQL的慢查询日志可以记录所有执行慢的SQL。先把慢查询日志开了,看看哪些SQL慢。

# my.cnf里配置
slow_query_log = 1
long_query_time = 1   # 超过1秒的SQL记录下来
slow_query_log_file = /var/log/mysql/slow.log

2. 用explain分析慢SQL

找到慢SQL之后,用explain看看它的执行计划,看看有没有走索引,是不是全表扫描。

3. 看数据库的状态

用下面的命令看看数据库当前的状态:

SHOW GLOBAL STATUS;

重点关注这几个指标:

  • Slow_queries:慢查询的数量
  • Threads_connected:当前连接数
  • Innodb_row_reads:读了多少行数据
  • Innodb_data_reads:读了多少数据

二、SQL和索引优化

这是最常用、也是性价比最高的优化方式。很多时候,加个索引,SQL性能就能提升几十倍。

1. 加合适的索引

哪些字段要加索引

  • WHERE条件里经常用到的字段
  • 表连接的字段
  • ORDER BY、GROUP BY的字段
  • 区分度高的字段

索引的注意点

  • 不要加太多索引,索引也占空间,而且插入更新的时候要维护索引
  • 联合索引要注意最左前缀原则
  • 尽量不要在索引字段上做函数操作,不然索引会失效

2. 避免索引失效的情况

常见的索引失效场景:

  • WHERE条件里对索引字段做函数操作
  • WHERE条件里用了!=、<>、NOT IN
  • LIKE以%开头
  • 联合索引不满足最左前缀
  • 字段类型不匹配(比如字符串字段用数字去查)

3. 优化SQL写法

不要用SELECT *

只查需要的字段,不要查所有字段。这样不仅减少数据传输,还能用到覆盖索引。

避免大分页

比如LIMIT 100000, 10,这种越往后越慢。优化方法:用上次的最大id来查。

避免在WHERE里做计算

比如WHERE age + 1 = 18,这样索引会失效。应该写成WHERE age = 17。

小表驱动大表

联表查询的时候,小表在前,大表在后,性能更好。

三、表结构优化

1. 选择合适的数据类型

  • 能用数字类型就不要用字符串
  • 能用短的就不要用长的,比如用TINYINT不要用INT
  • 时间类型用DATETIME或者TIMESTAMP,不要用字符串存时间

2. 避免太多字段

一张表不要有太多字段,字段太多的话,数据页能放的行就少,IO次数就多。不常用的字段可以拆到另一张表里。

3. 适当加冗余字段

有些字段虽然可以联表查出来,但是如果经常用到,可以考虑加冗余字段,减少联表查询。

4. 大表做归档

如果表里有很多历史数据,但是查询的时候很少用到,可以把历史数据归档到另一张表里,主表只保留最近的数据。这样主表数据量小了,查询就快了。

四、配置参数优化

MySQL的默认配置很多都不是最优的,需要根据自己的服务器配置调一下。

1. innodb_buffer_pool_size

这个是InnoDB的缓冲池大小,是最重要的参数。一般设置成服务器内存的50%~70%。如果你的服务器内存是16G,那这个参数就设成8G~10G。

这个参数设大了,很多数据和索引都能在内存里,就不用读磁盘了,性能会好很多。

2. innodb_log_file_size

这个是redo log的大小,一般设成256M~1G。这个参数影响写性能,太小的话会频繁刷盘。

3. max_connections

最大连接数,根据你的业务量调整,一般设成500~1000就够了。不要设太大,不然每个连接都占内存,反而会拖慢性能。

4. query_cache

MySQL 8.0已经把查询缓存去掉了,因为查询缓存的命中率不高,而且维护成本很高。如果是老版本的MySQL,建议把查询缓存关了。

五、架构层面优化

如果SQL和索引都优化过了,还是不行,那就要从架构层面下手了。

1. 读写分离

主库写,从库读,把读的压力分散到多个从库上。大部分网站都是读多写少,读写分离效果很明显。

2. 加缓存

把热点数据放到Redis里,直接从Redis读,不用查数据库。这是提升性能最明显的方式。

3. 分库分表

单表数据量太大了,到了千万级甚至亿级,那就分库分表,把数据分散到多个表或者多个数据库里。

4. 用更好的硬件

如果前面的优化都做了,还是不够,那只能加硬件了。比如用SSD代替机械硬盘,数据库的性能瓶颈很多时候都是磁盘IO。SSD的IOPS比机械硬盘高几个数量级,提升非常明显。

常见坑

坑1:上来就加机器,不优化SQL

很多同学一遇到性能问题就说:加机器!加内存!其实很多时候都是SQL写的烂,没加索引,优化一下SQL性能就能提升好几倍。加机器是最后手段,不是第一选择。

坑2:索引加了很多,但是都没用到

很多同学觉得索引加的越多越好,结果加了一堆索引,真正查询的时候一个都没用到。加索引之前要先explain一下,看看是不是真的能用到。

坑3:以为加了索引就一定快

很多同学以为只要加了索引,查询就一定快。其实不是,如果索引字段的区分度很低,比如性别只有男和女,那加了索引也没用,优化器可能还是会选择全表扫描。

坑4:调参数瞎调

很多同学看了网上的优化文章,把一堆参数往自己服务器上套,结果把数据库搞出问题了。调参数一定要一点点调,调完观察效果,不要一下子改一堆参数。

坑5:不做监控

很多同学数据库出问题了才知道性能差,平时根本没监控。一定要做监控,比如慢查询数量、CPU使用率、连接数这些指标,提前发现问题。

总结

MySQL性能优化的思路和步骤:

  1. 先定位问题:开慢查询日志,找到慢SQL
  2. SQL和索引优化:加合适的索引,优化SQL写法,这是性价比最高的
  3. 表结构优化:选合适的数据类型,大表归档,适当加冗余字段
  4. 配置参数优化:重点调innodb_buffer_pool_size
  5. 架构层面优化:读写分离、加缓存、分库分表
  6. 最后才是加硬件:比如用SSD、加内存

记住:性能优化是一个系统工程,要从多个方面下手。不要指望一招就能解决所有问题,先从最简单、最容易见效的地方下手,比如加索引、优化SQL,然后再一步步深入。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 08:57 

Nginx配置gzip压缩,提高网站加载速度

前言

网站加载慢,很大原因是没开压缩。CSS、JS 文件动辄几百 KB,开了 gzip 之后能压缩到原来的 1/3,加载速度提升明显。本文就讲一下怎么在 Nginx 里配置 gzip 压缩。

为什么要开 gzip

举个例子:

  • 一个 CSS 文件原始大小 100KB
  • 开了 gzip 之后变成 20KB
  • 传输体积减少 80%

浏览器收到压缩内容后自动解压,用户无感知。

基础配置

在 nginx.conf 的 http 块里加上:

http {
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
    gzip_min_length 1k;
    gzip_comp_level 6;
    gzip_vary on;
}

配置项说明

gzip on:
开启 gzip 压缩。

gzip_types:
哪些类型的文件需要压缩。

  • text/plain:文本
  • text/css:CSS
  • application/json:JSON
  • application/javascript:JS
  • image/svg+xml:SVG 图片

gzip_min_length:
小于 1KB 的文件不压缩(压缩本身也占 CPU,小文件不值得压)。

gzip_comp_level:
压缩级别,1 到 9,6 比较合适(越大压得越狠,但越占 CPU)。

gzip_vary on:
给响应头加 Vary: Accept-Encoding,告诉 CDN 和缓存,这个内容是压缩过的。

完整示例

http {
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
    gzip_min_length 1k;
    gzip_comp_level 6;
    gzip_vary on;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
}

检查并重载

nginx -t
systemctl reload nginx

验证 gzip 是否生效

用 curl 测试

curl -H "Accept-Encoding: gzip" -I https://www.example.com

如果返回头里有:

Content-Encoding: gzip

说明 gzip 生效了。

用浏览器 F12 测试

打开浏览器 F12 → Network → 点一个 JS/CSS 文件 → Response Headers,看有没有 Content-Encoding: gzip。

注意事项

不要压缩图片

JPG、PNG 这些图片本身已经是压缩过的,再压 gzip 没什么效果,还浪费 CPU。所以 gzip_types 里不要加 image/jpeg、image/png 这些。

不要压缩太小的文件

太小的文件(比如小于 1KB)压缩完反而可能变大,所以用 gzip_min_length 过滤掉。

压缩级别不要太高

gzip_comp_level 设到 9 没意义,压不了多少,CPU 占用还高。6 就够了。

常见坑

坑1:开了 gzip 但没生效

配置写了,但浏览器看到的还是没压缩的。

排查:

  1. 看文件大小是不是小于 gzip_min_length
  2. 看 gzip_types 里有没有包含这种类型
  3. 看浏览器请求头里有没有 Accept-Encoding: gzip

坑2:HTML 没压缩

只压缩了 CSS 和 JS,HTML 没压缩。

原因: gzip_types 里没写 text/html。

注意: text/html 是默认就压缩的,不用写在 gzip_types 里。

坑3:CDN 缓存了没压缩的版本

开了 gzip,但 CDN 上缓存的还是旧的没压缩的文件。

解决: 清一下 CDN 缓存,或者等 CDN 自动更新。

总结

gzip 配置很简单,就几行:

配置项 推荐值 作用
gzip on 开启压缩
gzip_types text/css application/javascript ... 压缩哪些文件
gzip_min_length 1k 小于多少不压
gzip_comp_level 6 压缩级别
gzip_vary on 加 Vary 头

开了 gzip 网站加载速度立马快一截,零成本优化,一定要开。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:59 

PHP 性能优化:从代码到部署的完整指南

前言

PHP 性能优化是每个 PHP 开发者都绕不开的话题。很多人觉得 PHP 性能差,但实际上通过合理的优化,PHP 应用完全可以达到很高的性能水平。本文从代码层面到部署层面,带你完整梳理 PHP 性能优化的思路。

一、代码层面优化

1. 避免在循环中做数据库查询

// 慢:循环中查询数据库
foreach ($users as $user) {
    $order = $db->query("SELECT * FROM orders WHERE user_id = {$user['id']}");
}

// 快:一次性查询,然后用数组映射
$userIds = array_column($users, 'id');
$orders = $db->query("SELECT * FROM orders WHERE user_id IN (" . implode(',', $userIds) . ")")->fetchAll();
$orderMap = array_column($orders, null, 'user_id');

2. 用生成器处理大数据

// 慢:一次性加载所有数据到内存
$users = $db->query("SELECT * FROM big_table")->fetchAll();

// 快:用生成器逐行处理
function getUsers() {
    $stmt = $pdo->query("SELECT * FROM big_table");
    while ($row = $stmt->fetch()) {
        yield $row;
    }
}

3. 字符串拼接 vs implode

// 慢:频繁拼接字符串
$str = '';
foreach ($items as $item) {
    $str .= $item . ',';
}

// 快:用数组收集最后拼接
$parts = [];
foreach ($items as $item) {
    $parts[] = $item;
}
$str = implode(',', $parts);

二、PHP 配置优化

1. OPcache 必开

OPcache 是 PHP 性能提升最大的一个扩展,没有之一。

; php.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1

开启 OPcache 后,PHP 脚本会被编译成字节码缓存起来,避免每次请求都重新编译。性能提升通常在 2-5 倍。

2. 合理设置内存限制

memory_limit = 256M

不要设置太大,也不要太小。根据你的应用实际情况调整。

三、数据库优化

1. 开启慢查询日志

slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1

找出慢查询,然后针对性优化。

2. 使用持久化连接要谨慎

// 不一定更快,可能反而更慢
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass', [
    PDO::ATTR_PERSISTENT => true
]);

持久化连接在高并发场景下可能导致连接耗尽,要根据实际情况测试。

四、部署层面优化

1. 使用 PHP-FPM 优化

; php-fpm/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30

根据服务器内存调整 max_children,每个 PHP-FPM 进程大约占用 20-40MB 内存。

2. Nginx 开启 gzip

gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;

3. 静态文件 CDN 加速

把图片、CSS、JS 等静态资源放到 CDN 上,减轻服务器压力。

五、性能监控工具

  • Xdebug:代码性能分析,找出瓶颈函数
  • Blackfire:更专业的性能分析工具
  • New Relic:APM 应用性能监控
  • ab / wrk:压力测试工具

总结

PHP 性能优化的核心思路:

  1. 先找出瓶颈在哪里,不要盲目优化
  2. 代码层面:减少数据库查询、减少内存占用
  3. 配置层面:OPcache 必开
  4. 部署层面:PHP-FPM、Nginx、数据库都要调优
  5. 用工具量化优化效果

性能优化是一个持续迭代的过程,不要指望一次性优化到位。每次做一点,慢慢积累。


emer 发布于  2026-10-4 09:55 
'); })();