找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 22|回复: 0

[维护日志] [2026-05-29] [性能] [IndexNow异步推送] - 发帖/编辑卡顿问题修复

[复制链接]
  • 打卡等级:本地老炮

9337

威望

7448

金钱

1万

贡献

管理员

自由的灵魂

积分
107434
主题
5630
回帖
26661
注册时间
2003-4-10
最后登录
2026-10-2
发表于 2026-5-29 22:46:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
[2026-05-29] [性能] [IndexNow异步推送] - 发帖/编辑卡顿问题修复

标签:IndexNow 异步队列 发帖卡顿 性能优化 CLI脚本




1、问题缘起

论坛用户在发帖和编辑帖子时出现严重卡顿,带图片的帖子耗时超过30秒。通过PHP慢日志定位到卡顿点位于 post_editpost.php 第540行的 curl_exec() 调用,目标地址为 https://api.indexnow.org/IndexNow。

进一步排查发现,post_newthread.php 和 post_editpost.php 中均嵌入了同步向 IndexNow 搜索引擎推送 URL 的代码。当 IndexNow API 响应缓慢或超时时,整个发帖/编辑流程被阻塞,直到 curl 请求超时(约30秒)才能继续执行。

相关子问题:
  • 同步推送导致用户体验严重下降
  • 无失败重试机制,一次超时即推送失败
  • 缺少对推送状态的监控和日志




2、解决方案

(1)简要技术分析:
将同步推送改为异步队列模式:发帖/编辑时仅将URL写入队列表,由后台计划任务(Crontab)定期遍历队列并发送HTTP请求,实现发帖流程与推送流程的解耦。

(2)修改、新增文件列表:

操作文件路径说明
修改/www/wwwroot/www.dianbo.org/source/include/post/post_newthread.php发帖时改为异步入队
修改/www/wwwroot/www.dianbo.org/source/include/post/post_editpost.php编辑时改为异步入队
新增/www/wwwroot/www.dianbo.org/api/indexnow_cli.php异步推送CLI处理脚本
新增数据库表 dx_common_indexnow_queue推送队列表


(3)关键代码段:

队列表结构:
  1. CREATE TABLE `dx_common_indexnow_queue` (
  2.   `id` int(11) NOT NULL AUTO_INCREMENT,
  3.   `host` varchar(255) NOT NULL DEFAULT '',
  4.   `key` varchar(255) NOT NULL DEFAULT '',
  5.   `url` varchar(255) NOT NULL DEFAULT '',
  6.   `dateline` int(11) NOT NULL DEFAULT '0',
  7.   `status` tinyint(1) NOT NULL DEFAULT '0',
  8.   `retry` tinyint(1) NOT NULL DEFAULT '0',
  9.   PRIMARY KEY (`id`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
复制代码


发帖文件入队代码(post_newthread.php 第306-324行):
  1. // ========= IndexNow 异步推送(入队) =========
  2. $excluded_fids = array(71, 73);
  3. if (!in_array($_G['fid'], $excluded_fids)) {
  4.     $indexnow_host = "https://www.dianbo.org";
  5.     $indexnow_key = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
  6.     $indexnow_url = "https://www.dianbo.org/thread-" . ($tid ?: $_G['tid']) . "-1-1.html";
  7.     DB::query("INSERT INTO dx_common_indexnow_queue (host, `key`, url, dateline, status, retry) VALUES (" .
  8.         DB::quote($indexnow_host) . ", " .
  9.         DB::quote($indexnow_key) . ", " .
  10.         DB::quote($indexnow_url) . ", " .
  11.         TIMESTAMP . ", 0, 0)");
  12. }
  13. // ========= IndexNow 推送结束 =========
复制代码


CLI 处理脚本(api/indexnow_cli.php 核心部分):
  1. $tasks = DB::fetch_all("SELECT * FROM dx_common_indexnow_queue WHERE status = 0 ORDER BY id ASC LIMIT 5");
  2. foreach ($tasks as $task) {
  3.     $ch = curl_init();
  4.     curl_setopt($ch, CURLOPT_URL, 'https://api.indexnow.org/IndexNow');
  5.     curl_setopt($ch, CURLOPT_POST, true);
  6.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  7.     curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  8.     curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
  9.         'host' => $task['host'],
  10.         'key' => $task['key'],
  11.         'keyLocation' => $task['host'] . '/' . $task['key'] . '.txt',
  12.         'urlList' => [$task['url']]
  13.     ]));
  14.     $response = curl_exec($ch);
  15.     $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  16.     curl_close($ch);
  17.     $status = ($http_code >= 200 && $http_code < 300) ? 1 : 2;
  18.     DB::query("UPDATE dx_common_indexnow_queue SET status = '$status' WHERE id = '{$task['id']}'");
  19. }
复制代码


Crontab 任务:
  1. */5 * * * * /usr/bin/php /www/wwwroot/www.dianbo.org/api/indexnow_cli.php >> /dev/null 2>&1
复制代码





3、最终实现效果

指标优化前优化后
发帖响应时间30+ 秒即时(<1秒)
编辑响应时间30+ 秒即时(<1秒)
IndexNow 推送方式同步阻塞异步队列
失败重试无支持(status=2 可重试)
推送监控无日志日志记录 data/log/indexnow_async.log
版块排除支持(71、73)保留相同逻辑





4、重要技术沉淀(需更新到固化摘要)

建议在 env-base 分支中新增:

  1. 十八、IndexNow 异步推送方案(2026-05-29)

  2. 问题:同步 curl 请求 api.indexnow.org 超时导致发帖卡顿
  3. 解决:队列表 + CLI 脚本 + Crontab 异步处理
  4. 队列表:dx_common_indexnow_queue
  5. CLI脚本:/api/indexnow_cli.php
  6. Crontab:*/5 * * * * /usr/bin/php /www/wwwroot/www.dianbo.org/api/indexnow_cli.php
  7. 排除版块:71、73
  8. 日志位置:/data/log/indexnow_async.log
复制代码


踩坑点:
  • CLI 脚本需要模拟 $_SERVER 环境变量,否则 Discuz! 核心初始化失败
  • IN_DISCUZ 常量在 class_core.php 中已定义,CLI 脚本不应重复定义
  • 使用 DB::quote() 对插入值进行转义,防止SQL注入




5、进一步优化可能性

  • 图片本地化插件异步化:当前转贴图片仍为同步下载,可参照此方案改为队列处理
  • 百度推送异步化:发帖时同步推送百度的代码同样可改为异步队列
  • 队列监控面板:在论坛后台增加队列状态查看功能,便于运维

不懂就搜!点此搜点拨论坛。如果本坛没有,请尝试点此问AI,或跟帖提问。
发帖前注意看置顶帖。
不定期借助AI对点拨论坛陈年老帖进行挖坟回复,打扰勿怪!
点拨网 — 传播知识,启迪智慧
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|点拨论坛 |网站地图

GMT+8, 2026-10-2 04:58 , Processed in 0.048459 second(s), 7 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表