重启虚拟机后,`/admin/upgrade` 页面加载失败,JS 请求失败,部分头像图片 404

背景信息:网站地址为 lot.almost-dead.net,版本为 2.8.0.beta4,托管于 Google Cloud/Compute;我按照官方的基于 Docker 的指南完成了部署。(我精通浏览器前端技术,了解云托管的基本流程,但熟悉的是 AWS 而非 Google Cloud。)

初步原因:我停止并重新启动了一个 VM 实例(试图调整暴露给 Discourse 的环境变量)。

当 VM 恢复运行且网站重新上线后,我注意到 JS 资源加载超时,部分用户头像也无法加载。在管理面板中,“社区健康”区域无法加载;加载动画持续旋转,Chrome 开发者工具的“网络”选项卡显示 /message-bus/.../poll 请求全部失败。升级页面(/admin/upgrade)几乎立即失败,Chrome 显示 ERR_FAILED 错误代码。浏览主题时,我看到 POST 请求失败,错误为 ERR_CONNECTION_REFUSED,由 JS 发起的 GET 请求也失败,错误为 ERR_FAILED。(此测试使用的是已登录管理员账户并保存了 Cookie 的浏览器。)

使用全新的浏览器实例访问网站时,Chrome 显示 ERR_CONNECTION_REFUSED 错误。

我已尝试的解决方法:

  • 服务器端重建 — 执行 sudo ./launcher rebuild app 似乎成功,但网站行为没有任何变化
    • 尝试注释掉插件后重新构建,仍然无变化
  • 安全模式 — 访问 /safe-mode 会立即导致 Chrome 显示 ERR_FAILED 页面

有任何建议吗?

你试过

apt-get update
apt-get upgrade

然后重新构建吗?

刚才试过了,看起来和之前一样。

不,你的网站并没有恢复,而是完全宕机了。你看到的部分内容来自缓存。对于从未访问过该网站的用户来说,它没有任何响应。这可能是网络或防火墙层面的问题,或者是 nginx 未能启动或已崩溃。

好的,这说得通。

一旦我执行 sudo ./launcher enter app,看起来 nginx 已经在运行了……

root@adn-prod-app:/var/www/discourse# ps aux | grep nginx
root       548  0.0  0.0   2156    64 ?        Ss   07:04   0:00 runsv nginx
root       558  0.0  0.1  55236  2524 ?        S    07:04   0:00 nginx: master process /usr/sbin/nginx
www-data   567  0.0  0.2  55996  5068 ?        S    07:04   0:00 nginx: worker process
www-data   568  0.0  0.0  55996  1628 ?        S    07:04   0:00 nginx: worker process
www-data   569  0.0  0.0  55792  1680 ?        S    07:04   0:00 nginx: cache manager process
root     23179  0.0  0.0   6140   884 pts/1    S+   21:23   0:00 grep nginx

我对 Google Cloud 还不够熟悉,不知道在它们的网络/防火墙设置中应该查找什么……我注意到 VM 实例带有 “http-server” 和 “https-server” 标签,并且它们的防火墙系统似乎利用这些标签,为带有这些标签的实例应用内置的 “default-allow-http” 和 “default-allow-https” 规则。这听起来是正确的,而且 nslookup 显示我使用的子域名已解析为 Google 界面中列出的外部 IP 地址,但外部世界仍然无法访问该实例。

我在 /var/discourse/shared/standalone/log/rails/production.log 中看到有关连接 Redis 的错误;有什么方法可以修复吗?

Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL) subscribe failed, reconnecting in 1 second. Call stack /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:384:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:365:in `establish_connection'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:117:in `block in connect'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:330:in `with_reconnect'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:116:in `connect'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:403:in `ensure_connected'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:255:in `block in process'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:342:in `logging'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:254:in `process'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis/client.rb:148:in `call'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-2.3.3/lib/mini_profiler/profiling_methods.rb:85 :in `block in profile_method'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis.rb:959:in `block in get'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis.rb:70:in `block in synchronize'
/usr/local/lib/ruby/2.7.0/monitor.rb:202:in `synchronize'
/usr/local/lib/ruby/2.7.0/monitor.rb:202:in `mon_synchronize'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis.rb:70:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/redis-4.4.0/lib/redis.rb:958:in `get'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/message_bus-3.3.6/lib/message_bus/backends/redis.rb:361:in `process_global_backlog'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/message_bus-3.3.6/lib/message_bus/backends/redis.rb:269:in `block in global_subscribe'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/message_bus-3.3.6/lib/message_bus/backends/redis.rb:282:in `global_subscribe'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/message_bus-3.3.6/lib/message_bus.rb:781:in `global_subscribe_thread'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/message_bus-3.3.6/lib/message_bus.rb:729:in `block in new_subscriber_thread'
Job exception: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL)
Creating scope :open. Overwriting existing method Poll.open.

你好,
虽然可能性不大,但上次我遇到 Redis 错误时,似乎与(或者说属于同一类问题)SSL 证书(缺失?)有关。
也许运行 ./launcher logs app 会有帮助?

啊,这里有一些 nginx 警告,紧接着是一条似乎缺少标识符的消息:Reload error for :

$ sudo ./launcher logs app
run-parts: 正在执行 /etc/runit/1.d/00-ensure-links
run-parts: 正在执行 /etc/runit/1.d/00-fix-var-logs
run-parts: 正在执行 /etc/runit/1.d/01-cleanup-web-pids
run-parts: 正在执行 /etc/runit/1.d/anacron
run-parts: 正在执行 /etc/runit/1.d/cleanup-pids
清理过期的 PID 文件
run-parts: 正在执行 /etc/runit/1.d/copy-env
run-parts: 正在执行 /etc/runit/1.d/letsencrypt
[2021 年 9 月 14 日 星期二 10:44:41 PM UTC] 域名未变更。
[2021 年 9 月 14 日 星期二 10:44:41 PM UTC] 跳过,下次续期时间为:2021 年 10 月 5 日 星期二 00:05:09 UTC
[2021 年 9 月 14 日 星期二 10:44:41 PM UTC] 添加 '--force' 以强制续期。
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 正在安装密钥到:/shared/ssl/lot.almost-dead.net.key
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 正在安装完整证书链到:/shared/ssl/lot.almost-dead.net.cer
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 运行重载命令:sv reload nginx
警告:nginx: 无法打开 supervise/ok:文件不存在
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 重载错误 for :
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 域名未变更。
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 跳过,下次续期时间为:2021 年 10 月 4 日 星期一 00:06:04 UTC
[2021 年 9 月 14 日 星期二 10:44:42 PM UTC] 添加 '--force' 以强制续期。
[2021 年 9 月 14 日 星期二 10:44:43 PM UTC] 正在安装密钥到:/shared/ssl/lot.almost-dead.net_ecc.key
[2021 年 9 月 14 日 星期二 10:44:43 PM UTC] 正在安装完整证书链到:/shared/ssl/lot.almost-dead.net_ecc.cer
[2021 年 9 月 14 日 星期二 10:44:43 PM UTC] 运行重载命令:sv reload nginx
警告:nginx: 无法打开 supervise/ok:文件不存在
[2021 年 9 月 14 日 星期二 10:44:43 PM UTC] 重载错误 for :
runsvdir 已启动,PID 为 546
ok: run: redis: (pid 554) 0 秒
ok: run: postgres: (pid 560) 0 秒
chgrp: 无效的用户组:'syslog'
supervisor pid: 558 unicorn pid: 579
正在关闭
run-parts: 正在执行 /etc/runit/3.d/01-nginx
ok: down: nginx: 1 秒,通常状态为 up
run-parts: 正在执行 /etc/runit/3.d/02-unicorn
(558) 正在退出
ok: down: unicorn: 0 秒,通常状态为 up
run-parts: 正在执行 /etc/runit/3.d/10-redis
ok: down: redis: 0 秒,通常状态为 up
run-parts: 正在执行 /etc/runit/3.d/99-postgres
ok: down: postgres: 0 秒,通常状态为 up
ok: down: nginx: 3 秒,通常状态为 up
ok: down: postgres: 1 秒,通常状态为 up
ok: down: redis: 2 秒,通常状态为 up
ok: down: cron: 0 秒,通常状态为 up
ok: down: unicorn: 2 秒,通常状态为 up
ok: down: rsyslog: 0 秒,通常状态为 up
run-parts: 正在执行 /etc/runit/1.d/00-ensure-links
run-parts: 正在执行 /etc/runit/1.d/00-fix-var-logs
run-parts: 正在执行 /etc/runit/1.d/01-cleanup-web-pids
run-parts: 正在执行 /etc/runit/1.d/anacron
run-parts: 正在执行 /etc/runit/1.d/cleanup-pids
清理过期的 PID 文件
run-parts: 正在执行 /etc/runit/1.d/copy-env
run-parts: 正在执行 /etc/runit/1.d/letsencrypt
[2021 年 9 月 14 日 星期二 10:54:00 PM UTC] 域名未变更。
[2021 年 9 月 14 日 星期二 10:54:00 PM UTC] 跳过,下次续期时间为:2021 年 10 月 5 日 星期二 00:05:09 UTC
[2021 年 9 月 14 日 星期二 10:54:00 PM UTC] 添加 '--force' 以强制续期。
[2021 年 9 月 14 日 星期二 10:54:00 PM UTC] 正在安装密钥到:/shared/ssl/lot.almost-dead.net.key
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 正在安装完整证书链到:/shared/ssl/lot.almost-dead.net.cer
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 运行重载命令:sv reload nginx
fail: nginx: runsv 未运行
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 重载错误 for :
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 域名未变更。
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 跳过,下次续期时间为:2021 年 10 月 4 日 星期一 00:06:04 UTC
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 添加 '--force' 以强制续期。
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 正在安装密钥到:/shared/ssl/lot.almost-dead.net_ecc.key
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 正在安装完整证书链到:/shared/ssl/lot.almost-dead.net_ecc.cer
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 运行重载命令:sv reload nginx
fail: nginx: runsv 未运行
[2021 年 9 月 14 日 星期二 10:54:01 PM UTC] 重载错误 for :
runsvdir 已启动,PID 为 539
ok: run: redis: (pid 549) 0 秒
ok: run: postgres: (pid 555) 0 秒
chgrp: 无效的用户组:'syslog'
supervisor pid: 551 unicorn pid: 579
$

不确定原因,但它们是否可能缺失了?

我在应用里看到了这些……

root@adn-prod-app:/var/www/discourse# ls -l /shared/ssl/
total 24
-rw-r--r-- 1 root root 5950 Sep 14 22:54 lot.almost-dead.net.cer
-rw-r--r-- 1 root root 5329 Sep 14 22:54 lot.almost-dead.net_ecc.cer
-rw------- 1 root root  302 Sep 14 22:54 lot.almost-dead.net_ecc.key
-rw------- 1 root root 3243 Sep 14 22:54 lot.almost-dead.net.key

:facepalm: 看来我的问题在于虚拟机重启后获得了不同的 IP 地址,我需要修改 A 记录以指向新地址。

网站已恢复,感谢倾听!