保存长文章(约10万字)的大段编辑时,因Diff瓶颈导致后端出现502/504超时

在编辑并保存超长帖子(约 100,000 个字符)时,我们遇到了后端超时问题。服务器在保存操作期间无响应,导致出现 502/504 错误。前端控制台显示以下错误堆栈:

ajax-error.js:36:15
l ajax-error.js:36
u ajax-error.js:75
d ajax-error.js:84
Ember 41
update rest.js:72
update rest.js:72
save rest.js:115
editPost composer.js:1147
Ember 6

我进行了一些对比测试,结果表明瓶颈在于旧版本与新版本之间的差异计算:

  • 直接将长帖子 A 编辑为长帖子 B 并保存, consistently 触发 502/504 超时。
  • 先清空长帖子,保存一个短占位符(例如 5 个字符),然后粘贴完整的新内容 B 并保存,则能迅速完成。

看来当前的差异计算引擎在处理涉及极长文本且变更比例极高的极端情况时表现不佳。是否有可能添加一个性能回退机制?例如,当文本极长且修改比例很高时,系统可以将其视为“完全重写”,而不是执行详细的逐行差异计算。

团队是否有计划优化大帖子的差异处理,或引入某种优雅降级/保护机制以应对此类场景?另一个想法是先让保存成功,然后在后台异步计算差异。

2 个赞

与此同时,服务器端的 Unicorn 日志捕获到了超时的确切位置,证实该工作进程在处理 Markdown 差异时被终止:

Unicorn worker 收到 USR2 信号,表明即将超时,正在转储主线程的调用栈
config/unicorn.conf.rb:204:in `backtrace'
config/unicorn.conf.rb:204:in `block (2 levels) in reload'
/var/www/discourse/lib/discourse_diff.rb:172:in `[]'
/var/www/discourse/lib/discourse_diff.rb:172:in `tokenize_markdown'
/var/www/discourse/lib/discourse_diff.rb:115:in `side_by_side_markdown'
/var/www/discourse/app/serializers/post_revision_serializer.rb:128:in `body_changes'
... 

通过将 UNICORN_TIMEOUT 修改为 60 或 120,能否解决上述问题?

嘿,

我想我会把这个问题移到 #contribute:bug。10 万字符 非常 不寻常,但无论如何,我认为应该实现某种回退机制。

在 2 月,我添加了 diff_too_complex: “差异过于复杂,无法显示。请尝试查看各个较小的修改。”。如果情况变得过于复杂,我们的差异算法将直接停止运行。

您这里运行的是最新版本吗?它应该能够处理这些情况,除非您的服务器性能非常非常低。