scavin
(scavin)
1
我建议为内置的 [details] 功能添加一个最大嵌套深度限制,或者引入一个站点设置,允许管理员配置此限制。
问题描述
最近,我论坛上的一个用户创建了一篇包含 24 层嵌套 [details] 部分 的帖子。
这导致了几个问题:
- 浏览器性能: 用户报告说,展开多个层级会导致 Firefox 变得极其缓慢或无响应。
- Markdown 端点超时: 访问该主题的
.md 端点变得极其缓慢。我们观察到请求耗时分别为 19.8 秒和 31.1 秒。
- 服务器错误: Markdown 端点有时返回“Oops”错误页面。Discourse 日志在 Markdown 转换期间也显示了 Pitchfork 工作进程超时警告。
- 潜在的资源耗尽: 由于搜索引擎和 AI 爬虫频繁请求
.md 端点,深度嵌套的帖子可能会反复触发昂贵的处理过程并消耗服务器资源。
在删除问题帖子后,Markdown 端点返回 HTTP 200,响应时间约为 1.7 秒。
受影响的主题为:
https://meta.appinn.net/t/topic/87672
(问题回复已被移除。)
建议的改进
我认为以下任一措施都会很有用:
- 将
[details] 的嵌套限制在合理的深度,例如 2 或 3 层。
- 添加一个站点设置,例如
details_max_nesting_depth,允许管理员配置最大嵌套深度。
为了向后兼容,该设置的默认值可以设为无限制,同时允许管理员在需要时强制实施限制。
如果用户超过配置的限制,Discourse 可以拒绝该帖子并显示清晰的验证消息。
临时解决方案:一个插件
我创建了一个小插件,将 [details] 的嵌套限制为最多 2 层:
GitHub - scavin/discourse-details-depth-limit · GitHub
该插件在服务器端验证帖子,并拒绝包含超过两层嵌套可折叠部分的帖子。
我已在本地 Discourse 开发环境中成功测试了该插件。
对于遇到类似问题的管理员,在官方解决方案可用之前,此插件可作为一个临时解决方案。
我认为,在内置的 Details 插件中提供可配置的限制,将是防止意外或过度嵌套的有用保障措施。
2 个赞
Ethsim2
(Ethan )
2
你好 @scavin,感谢你的报告以及提供的复现细节。
我一直在调查你描述的 Markdown 端点变慢的问题,并在 MarkdownEndpoint::CookedProcessor#replace_details 中发现了一个问题:嵌套的 <details> 元素被反复转换,导致处理时间呈指数级增长。
我已在上游提交了一个包含修复方案的草稿 PR:
在八层嵌套的情况下,该修复将递归转换次数从 255 次减少到 8 次,在我的本地基准测试中实现了约 31 倍的提速。该 PR 已通过 GitHub CI 的初始检查。
同时,我也正在内置的 Details 插件中开发你提议的 details_max_nesting_depth 站点设置,使用 0 表示无限制嵌套,以保留现有行为。初始实现已经完成,但集成测试仍在进行中。
性能修复解决了服务器端的 Markdown 转换问题;可配置的深度限制将提供额外的保护,特别是针对浏览器端的性能。
欢迎你对该提议的设置提供反馈,并告知是将其包含在同一个 PR 中还是单独提交更好。
1 个赞
scavin
(scavin)
3
感谢快速排查并修复!
我认为将它们拆分为两个 PR 会更好,这样性能修复就可以独立审查和合并,而无需等待新配置项。
我也支持可配置的深度限制,默认值设为 0 以保持向后兼容性。
Ethsim2
(Ethan )
4
谢谢 @scavin。我能看出将它们分开的好处,尽管这两处更改都针对的是你报告的同一个根本问题,而且现在都已实现并通过 CI 测试。我在所有 PR 上都启用了维护者编辑权限,所以我很乐意遵循 Discourse 团队的偏好,无论是将这两个提交放在一起审查,还是将它们分开。
1 个赞