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

在编辑并保存极长帖子(约 10 万个字符)时,我们遇到了后端超时问题。服务器在保存操作期间无响应,导致出现 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 并保存,始终会触发 502/504 超时。
  • 先清空长帖子,保存一个短占位符(例如 5 个字符),然后粘贴完整的新内容 B 并保存,则能迅速完成。

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

团队是否有任何计划来优化大型帖子的差异处理,或为此类场景引入某种优雅降级/保护措施?另一个想法是允许先成功保存,然后在后台异步计算差异。

与此同时,服务器端的 Unicorn 日志捕获了超时的确切时间点,确认了工作进程在处理 Markdown 差异时被终止:

Unicorn worker received USR2 signal indicating it is about to timeout, dumping backtrace for main thread
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: “该差异过于复杂,无法显示。请尝试查看更小的独立编辑。”`。如果情况变得过于复杂,我们的差异算法会直接停止处理。

你这里运行的是最新版本吗?除非你的服务器配置非常非常低,否则它应该能处理这些情况。

我之前用过今年出的早期版本,但刚刚升级到了最新正式版!

升级后,我成功看到了“Diff 过于复杂,无法显示”的提示,说实话,这体验很棒。至少它没有直接崩溃,还允许我继续删除编辑历史。

另外,编辑超长帖子时出现的卡顿/延迟问题似乎也得到了修复。我还不能完全确定,但在上次测试中,它只卡顿了一小会儿,然后就成功处理了编辑后的版本。

我会进一步做更多测试。非常感谢!

太棒了 :+1:

我相信“diff 过于复杂”的阈值是可以调整的,所以如果你觉得有这方面的需求,我们可以一起想办法解决 :+1:(需要考虑的因素很多,所以可能没有一种放之四海而皆准的方案)

我已经多次测试过这一点。即使编辑内容复杂到足以触发“差异过于复杂,无法显示”的提示,帖子也从未再次发布失败。

我相信该问题在最新版本中已完全解决。再次感谢团队的出色工作!