78 lines
4.1 KiB
Markdown
78 lines
4.1 KiB
Markdown
# 服务器负载修复记录(2026-09-01)
|
||
|
||
## 处理结果
|
||
|
||
`www.xxiaw.com` 的 100%“运行堵塞”已解除。数据库慢查询、PHP 深分页和外部连接洪泛均已处理,正常列表页与内容页保持可访问。
|
||
|
||
| 指标 | 处理前 | 最终复测 |
|
||
| --- | ---: | ---: |
|
||
| 1 分钟负载 | 24.52 | 1.84 |
|
||
| CPU 空闲 | 0.2% | 73.2% |
|
||
| 已建立连接 | 2,874 | Web 67 |
|
||
| 80 端口连接 | 2,563 | 已包含在 Web 67 中 |
|
||
| MySQL Threads_running | 40 | 1~2 |
|
||
| 入站流量 | 峰值约 53 Mbps | 1.267 Mbps |
|
||
| `app_games/index3.html` | 高负载下响应迟缓 | HTTP 200,约 0.068 秒 |
|
||
| SQL 注入探针 | — | WAF 返回 403 |
|
||
|
||
BaoTa 的负载圆环使用滚动负载均值,5 分钟和 15 分钟数字会比实时 CPU 更慢回落。
|
||
|
||
## 根因
|
||
|
||
1. 大量住宅代理和爬虫维持慢连接。攻击高峰时约 2,563 条 80 端口连接,但访问日志只有约 1.9 RPS,说明主要压力发生在完整 HTTP 请求形成之前。
|
||
2. 免费 WAF 可以在收到请求后返回 444/403,但无法阻止 TCP 连接本身先占用 Nginx 和内核资源。
|
||
3. `gxl_mysql_news()` 与 `gxl_mysql_down()` 把查询条件数组直接拼接到缓存键,多个栏目实际共用 `news_countArray/down_countArray`。不存在的栏目会误取到其他栏目的总数,随后执行无结果的全索引扫描。
|
||
4. 公开分页没有深度上限。慢日志出现 `LIMIT 63400,20`、`LIMIT 110229,21` 等大偏移查询。
|
||
5. `gxl_tag` 的两个索引不完整,标签查询需要额外扫描和回表。
|
||
|
||
## 已实施的修改
|
||
|
||
### 网络与 Nginx
|
||
|
||
- `keepalive_timeout` 调整为 15 秒。
|
||
- 增加 `client_header_timeout 10s`、`client_body_timeout 15s`、`send_timeout 15s`、`keepalive_requests 100` 和超时连接复位。
|
||
- Nginx 单 IP 并发限制最终调整为 12,超限返回 429。
|
||
- 增加 `worker_shutdown_timeout 30s`,避免 reload 后旧工作进程被长连接长期拖住。
|
||
- 内核 INPUT 链增加 80/443 新连接并发限制:同一 IPv4 来源超过 12 条并发时 TCP reset。
|
||
- 内核规则由 `xxiaw-web-connlimit.service` 持久化,服务状态为 active/enabled,不影响 SSH、BaoTa 和 MySQL 端口。
|
||
- 免费 WAF 保持开启;加入 SemrushBot、DataForSeoBot、AhrefsBot、Bytespider、MJ12bot、DotBot、BLEXBot 等高消耗爬虫特征。
|
||
|
||
### PHP
|
||
|
||
修改文件:`/www/wwwroot/www.xxiaw.com/Lib/Common/Common/con_common.php`
|
||
|
||
- 新闻和下载计数缓存键改为对完整查询条件 `serialize()` 后取 MD5,消除栏目之间的缓存碰撞。
|
||
- 对 0 条结果也缓存,避免无效栏目反复查询 MySQL。
|
||
- 计数为 0 时直接返回,不再继续执行列表 SELECT。
|
||
- 新闻和下载公开分页限制为最多 200 页,异常深分页在生成 OFFSET SQL 前结束。
|
||
- 上线前后均通过 PHP 5.6 `php -l`,采用同目录临时文件和原子替换;未重启 PHP 或 MySQL。
|
||
|
||
### MySQL
|
||
|
||
- 验证 `gxl_news.idx_news_status_addtime` 为 `(news_status, news_addtime)`。
|
||
- 修正 `gxl_tag.idx_tag_sid_name` 为 `(tag_sid, tag_name)`。
|
||
- 新增 `gxl_tag.idx_tag_name_id` 为 `(tag_name, tag_id)`。
|
||
- 全部使用 `ALGORITHM=INPLACE, LOCK=NONE` 在线处理;标签索引变更耗时约 2.16 秒。
|
||
- 对 `gxl_news`、`gxl_tag`、`gxl_down` 执行 `ANALYZE TABLE`,结果均为 OK。
|
||
- PHP 修复后复测窗口未新增慢查询。
|
||
|
||
## 验证
|
||
|
||
- `https://www.xxiaw.com/app_games/index3.html`:HTTP 200。
|
||
- `/down/163006.html` 与 `/tutorial/53849.html`:HTTP 200。
|
||
- 第 9999 页请求约 0.06 秒返回,不再产生大偏移慢查询。
|
||
- SQL 注入测试返回 403,WAF 仍生效。
|
||
- Nginx 配置检查通过,reload 成功。
|
||
- MySQL 线程从 40 个运行线程降至 1~2 个。
|
||
|
||
## 回滚与审计备份
|
||
|
||
- `/www/backup/load-mitigation-20260901-182137`
|
||
- `/www/backup/connlimit-live-20260901-182259`
|
||
- `/www/backup/connlimit-persist-20260901-182406`
|
||
- `/www/backup/db-index-fix-20260901-182812`
|
||
- `/www/backup/php-pagination-fix-20260901-183331`
|
||
- `/www/backup/active-flood-tune-20260901-183711`
|
||
|
||
数据库索引变更前后的 `SHOW CREATE TABLE`、`SHOW INDEX`、`EXPLAIN` 和执行结果保存在 `/www/backup/db-index-fix-20260901-182812`。
|