Files
kefu/im/服务器负载修复记录-2026-09-01.md
2026-09-03 08:38:17 +08:00

78 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 服务器负载修复记录(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`。