几天前(我说是刚更新到 Discourse 2.5 beta 5 之后,并在 beta 6 中持续出现,但这可能只是巧合),YouTube 视频的嵌入功能间歇性失效。
在几小时无法工作后,它又自动恢复正常嵌入。
但从昨天起,该功能完全停止工作。
我在论坛日志中没有发现任何可疑的具体错误。
这是否可能是超时问题?有没有办法专门调查这个问题?
提前感谢!
几天前(我说是刚更新到 Discourse 2.5 beta 5 之后,并在 beta 6 中持续出现,但这可能只是巧合),YouTube 视频的嵌入功能间歇性失效。
在几小时无法工作后,它又自动恢复正常嵌入。
但从昨天起,该功能完全停止工作。
我在论坛日志中没有发现任何可疑的具体错误。
这是否可能是超时问题?有没有办法专门调查这个问题?
提前感谢!
浏览器无法告知单框失败的真正原因。您需要尝试从服务器发起类似的请求。
我理解你的建议,但是:
如果我简单地重复 GET 请求(按预期传递 headers 等信息)到 /onebox?url=…,我只会得到 404 错误 HTML。
如果我在服务器上重复 onebox 发出的请求,从 youtube_onebox.rb 的 Ruby 代码中复制,即 curl 'https://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=Xl-PTTeRsik',针对某个未嵌入的视频,它似乎可以完美运行。
该调用实际返回:
{"author_name":"AstronautiCAST","version":"1.0","height":270,"author_url":"https:\/\/www.youtube.com\/user\/AstronautiCAST","provider_name":"YouTube","provider_url":"https:\/\/www.youtube.com\/","thumbnail_height":360,"width":480,"html":"\u003ciframe width=\"480\" height=\"270\" src=\"https:\/\/www.youtube.com\/embed\/Xl-PTTeRsik?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen\u003e\u003c\/iframe\u003e","type":"video","thumbnail_width":480,"title":"Loading cargo into HTV-9 Konutori","thumbnail_url":"https:\/\/i.ytimg.com\/vi\/Xl-PTTeRsik\/hqdefault.jpg"}root@fait-2020:/var/discourse#
其中包含了 onebox 嵌入所需的所有内容。
我不明白这是怎么回事 ![]()
@Falco 非常抱歉打扰您,但 YouTube 视频嵌入功能的缺失严重影响了我们论坛的用户体验。
昨天我尝试了多种方法,例如阅读源代码(以了解在什么阶段、何种条件下会触发 onebox 返回 404 错误),甚至将当前生产环境的论坛克隆到一个全新的 Digital Ocean 服务器上。
阅读代码并没有太大帮助,主要是因为我对该平台的了解有限。
这里还有一个问题悬而未决:onebox 的处理过程是否有日志记录?如果能了解导致 onebox 放弃并返回 404 的具体错误,将会非常有帮助。
克隆 Droplet 的初衷是检查生产服务器的 IP 是否被 YouTube 屏蔽,同时排查是否与我们使用的域名有关。
然而,即使 IP 地址和域名都已更改,YouTube 视频嵌入功能仍然无法正常工作。
我真心希望能有人建议至少一种方法来追踪 onebox 的具体行为。
我已经找到了根本原因:YouTube 封禁了我们的 IP,但具体原因尚不清楚,因为事发时我们并未进行大规模重新生成(rebake)或类似操作。
请问 @Falco 或 @codinghorror:安装 2.5.0beta 5 或 6 是否触发了任何重新生成操作,从而超出了请求限制?
没有,我们最近没有添加任何重新渲染的内容。这听起来像是 YouTube 的变动,因为其他用户也抱怨了同样的问题。
感谢大家的回复。
不过我仍然不太明白,为什么当我模仿 Onebox 引擎发出的请求时(至少我预期会是这样,是 @Falco 吗?),我得到的却是包含正确响应的 JSON 数据,而不是 429 错误。
在按照我的截图执行请求之前,Onebox 是否还发出了另一个请求并收到了 429 错误?该请求如下:
curl 'https://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=Xl-PTTeRsik'
不用说,这些请求都是从运行 Discourse 的同一台服务器发出的(因此具有相同的外出 IP 地址)。
单个 curl 命令不太可能触发速率限制?
试试连续快速执行多个?或者在重复的 Bash 脚本中运行?(但不要太多,否则可能会被封禁)
好吧,仅仅尝试用一条包含 YouTube 链接的帖子重新生成,就会让 onebox 返回 404 错误……
经过一个周末的故障排查,发现了一个有趣的现象。
@Falco 或 @codinghorror,或许你们可以关注一下这个问题?
目前,在阅读 youtube_onebox.rb 的源代码时,我发现它支持从以下三种 URL 中提取视频 ID:
http://youtu.be/<videoid>https://www.youtube.com/embed/<videoid>https://www.youtube.com/watch?v=<videoid>尝试对格式为 1 和 3 的链接进行 onebox 处理时均失败,onebox 返回 404 错误(我认为这可能与我们的 IP 被屏蔽有关)。
但当我尝试嵌入格式为 2 的链接时,却能正常工作!
我在想,这是否与 这篇帖子 中解释的情况有关。
如果能了解 onebox 的内部工作机制(例如它向 YouTube 发起了哪些具体调用),并配合日志记录,将会非常有帮助……
回来给这个帖子做个收尾。
昨天 YouTube 解除了我们的封禁,我们已恢复正常运营。
不过,有几点我认为还是值得探讨一下:
/embed/ 类型的 URL 不知何故从未停止工作,即使在被封禁期间也是如此。)感谢所有回答我那些惊慌失措的问题的朋友们!![]()
完全赞同!!!(这是一个非常好的建议,我之前也提到过)
我想这里的部分挑战在于,如果目标页面返回的网页中没有 og 标签,Onebox 将无法判断这是否是由于某种重定向导致的。不过,这种情况可以被记录(例如:“ONEBOX:未找到 og 标签”),所有导致 Onebox 显示为空白的所有错误都应该被记录。
tl;dr 我想补充一点,我们这里似乎遇到了相同的问题。如果由于最近的某些变更导致存在速率限制问题,那么我认为其他用户在迁移、重新烘焙帖子时,或者仅仅因为论坛非常繁忙时,也会开始遇到这个问题。事实是,onebox 看似静默失败,这意味着这些问题直到用户开始抱怨缺少 YouTube onebox 时才会显现出来。
我们当前使用的是 2.6.0.beta 1 版本。
用户收到了关于非安全内容的警告。经过调查,Chrome 似乎在抱怨来自 HTTP 站点链接的图片。因此,我将 Discourse 配置为下载所有图片/媒体并通过 HTTPS 提供服务。
更改该设置后,这意味着需要对历史帖子进行重新烘焙。自那次重新烘焙以来,之前被 onebox 化的大量 YouTube 视频现在又变回了链接 URL。
我们有一个包含 10,000 条回复的线程,其中全是 YouTube 视频回复,且所有帖子都显示为 URL 而非 onebox。
在重新烘焙过程中,所有排队作业都正常处理,因此并非有作业卡在已删除作业的队列中。
我没有看到 @marcozambi 描述的那些错误消息,但我相信我们也触发了速率限制。
为了支持这一速率限制理论,我编写了一段小程序来重新烘焙帖子,该程序在某个线程的前 80 多个 YouTube 视频中成功实现了 onebox 化,但随后无法转换剩余的視頻。
此时,即使编辑帖子、进行小幅修改并重新保存,也无法强制 URL 被 onebox“展开”。与此同时,所有队列均为空,或者正如我所预期的那样,只有少量作业被即时处理。
在 30 分钟内多次尝试重新运行该代码,均无法强制对这些链接进行 onebox 化。我认为 80 并非一个神奇的数字,这只是我们可用配额所能支持的数量。
@marcozambi 提到,当其他链接失败时,使用 /embed/ 格式的 YouTube 链接可以正常工作,因此我修改了代码,使用正则表达式搜索并替换 YouTube 链接,将其转换为 /embed/ 格式。
代码生效了。
但再次运行代码仅重新烘焙帖子时,却无法将其转换为 onebox 表示形式。
我的计划是尝试创建一个任务,将大型线程中的所有 YouTube 链接转换为 /embed/ YouTube 格式。如果该方案失败或我们触发了更高的速率限制,我将查看 @merefield 的 Onebox Assistant。
我稍后会发布更新。
好的,确实有些奇怪的情况正在发生,看起来与速率限制有关。
我不确定我们是因为进行了大规模的重建(rebake)而被列入“惩罚名单”导致被速率限制,还是我们触发了其他人也会遇到的限制。
YouTube 视频的 Oneboxing(一键嵌入)似乎存在限制,一旦达到该限制,Oneboxing 就会静默失败。
出于显而易见的原因,我认为必须对此进行修改,特别是对于那些进行迁移或重建的人来说,他们可能完全不知道大量未展开或曾经展开的 Onebox 现在已变成了普通 URL。
@marcozambi 在上面提到,当其他格式因(推测是)速率限制问题而失败时,包含 /embed/ 的视频 ID 格式的 YouTube URL 仍然有效。
以下视频很好地说明了这一现象。
在录制此屏幕录像时,队列中没有积压的任务,论坛整体运行良好。
在此视频之前,YouTube 链接已开始无法被 OneBox 展开。
您将看到的是一个撰写窗口,其中 Onebox 无法展开 https://youtu.be/<video-id> 格式的 YouTube 链接。
随后我将格式更改为 https://youtube.com/embed/<video-id>,Onebox 成功展开了它。
然后我再次尝试原始格式,结果失败了。
在录制此视频期间,我追踪了浏览器控制台和网络标签页。我意识到问题肯定出在我们的服务器与 YouTube 之间,而不是我的浏览器与我们的服务器之间,但我仍将其附在下面,以防它们有用。
(抱歉图片有些缩小——希望放大后能看清)
以下是 Onebox 成功时的网络追踪记录。
我并不能完全信服 /embed/ 格式的链接在此处是万能药。我认为这似乎是一条拥有独立速率限制的路线:当 https://youtu.be/<video-id> 路线触及限制时,https://youtube.com/embed/<video-id> 路线则拥有另一套独立的限制。两者均受限的证据来自我编写的一个实用工具,该工具用于更改一个包含 1 万条帖子、其中 99% 为 YouTube 视频回复的巨型帖子线程中的 YouTube 嵌入格式。此时,Onebox 已经无法展开 https://youtu.be/<video-id> 格式的链接。我的工具将 YouTube 视频 URL 更改为 https://youtube.com/embed/<video-id> 格式,并对该线程的前 3000 条帖子进行了处理。它在前 1108 条帖子中运行良好,随后虽然成功更改了接下来约 1900 条帖子的格式,但 Onebox 并未展开它们。在此期间,生成了大量任务(我的代码使用了 post.revise),所有任务均无错误或重试地处理完毕。据我观察,任务处理在某个阶段似乎急剧加速。我猜测这可能是因为 Onebox 代码迅速从 YouTube 收到了某种错误,但我并未计时,也可能是其他多种原因。我很乐意提供更详细的证据,但如果不对 Onebox gem 进行仪器化,我不确定自己能做些什么。我是一名黑客而非 Ruby 专家,但我很乐意遵循一些高层指导。
从服务器命令行使用相同的用户代理执行一些简短的重复 curl 脚本,可能有助于隔离速率限制问题。
同意该变通方法可能有效,仅仅是因为它触发了独立的计数。
这里有一些更多的结果。请注意,下面的帖子中包含许多假设——基于对实际情况缺乏了解。
我会在该帖子之后补充我对当前情况的看法以及应该采取的措施。
感谢你的回复,Robert。
需要注意的是,当我尝试时,使用 /watch 路由对视频进行 Oneboxing(即生成预览卡片)一直失败(至今仍然如此),因此我不需要循环来强制其失败。
因此,我做出的一个假设是:Onebox 使用的 user-agent 是 Discourse Forum Onebox v2.6.0.beta1,依据是以下代码:
我随机选择了一个视频,并尝试使用 curl 读取其响应头。
我是在线上站点的 Docker 容器内执行此操作的,得到了以下响应。
命令
curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://m.youtube.com/watch?v=s0ONj4TG0UA"
响应:
curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://m.youtube.com/watch?v=s0ONj4TG0UA"
HTTP/2 303
content-length: 0
p3p: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en-GB for more info."
cache-control: no-cache
x-frame-options: SAMEORIGIN
content-type: text/html; charset=utf-8
location: https://www.youtube.com/watch?v=s0ONj4TG0UA&app=desktop
accept-ch-lifetime: 2592000
x-content-type-options: nosniff
accept-ch: DPR
expires: Tue, 27 Apr 1971 19:44:06 GMT
strict-transport-security: max-age=31536000
date: Fri, 07 Aug 2020 11:35:21 GMT
server: YouTube Frontend Proxy
x-xss-protection: 0
set-cookie: VISITOR_INFO1_LIVE=rcVTSJn81Ck; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:35:20 GMT; httponly; samesite=None
set-cookie: YSC=cFXIPerzT3Y; path=/; domain=.youtube.com; secure; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:05:20 GMT
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
因此,我收到了一个 303 重定向响应,重定向到 location 头中指定的 URL:https://www.youtube.com/watch?v=s0ONj4TG0UA&app=desktop。
这仅仅是在 URL 后附加了 &app=desktop。
命令
curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://www.youtube.com/watch?v=s0ONj4TG0UA&app=desktop"
响应
HTTP/2 429
x-content-type-options: nosniff
expires: Tue, 27 Apr 1971 19:44:06 GMT
x-frame-options: SAMEORIGIN
cache-control: no-cache
p3p: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en-GB for more info."
accept-ch-lifetime: 2592000
content-type: text/html; charset=utf-8
accept-ch: DPR
strict-transport-security: max-age=31536000
content-length: 48982
date: Fri, 07 Aug 2020 11:46:00 GMT
server: YouTube Frontend Proxy
x-xss-protection: 0
set-cookie: VISITOR_INFO1_LIVE=VQwNuouhq-s; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:46:00 GMT; httponly; samesite=None
set-cookie: YSC=8IRfPRFRY6c; path=/; domain=.youtube.com; secure; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:16:00 GMT
set-cookie: VISITOR_INFO1_LIVE=VQwNuouhq-s; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:46:00 GMT; httponly; samesite=None
set-cookie: YSC=8IRfPRFRY6c; path=/; domain=.youtube.com; secure; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:16:00 GMT
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
因此,我收到了一个 429“请求过多”的响应码,但没有收到 retry-after 头——直接停止,没有任何协商余地。
无论如何,如果 Onebox 看到的是这种情况,它要么忽略了该响应,要么至少我不知道如果它被记录了,应该去哪里查找。
虽然单个 429 响应可能是合理的行为,但在极短时间内收到大量 429 响应是绝不能被忽视的。
为了完整性,我立即尝试获取同一个视频,但这次使用 /embed/ 路由。
命令
curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://www.youtube.com/embed/s0ONj4TG0UA"
响应
HTTP/2 200
accept-ch-lifetime: 2592000
content-type: text/html; charset=utf-8
expires: Tue, 27 Apr 1971 19:44:06 GMT
x-content-type-options: nosniff
cache-control: no-cache
p3p: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en-GB for more info."
strict-transport-security: max-age=31536000
accept-ch: DPR
date: Fri, 07 Aug 2020 11:55:29 GMT
server: YouTube Frontend Proxy
x-xss-protection: 0
set-cookie: VISITOR_INFO1_LIVE=PNE6x6djF00; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:55:29 GMT; httponly; samesite=None
set-cookie: VISITOR_INFO1_LIVE=PNE6x6djF00; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:55:29 GMT; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:25:29 GMT
set-cookie: YSC=pDW-hdbauK8; path=/; domain=.youtube.com; secure; httponly; samesite=None
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
accept-ranges: none
vary: Accept-Encoding
200 - 成功。
不确定这是否有意义,但……默认情况下是否启用了 lazy-yt 嵌入插件?我在开发环境中注意到了它。
它似乎对 YouTube Oneboxer 的 to_html 方法进行了猴子补丁(monkey patch)。
我不知道这是否重要,但原始 Onebox 的 to_html 方法返回的是 /embed/ URL 格式:
而 lazy-yt 插件使用的是 /watch?v= URL 格式。
我还能做些什么来证明存在一个需要关注的问题吗?下一篇文章将解释我认为的根本原因。