自愈
Arkvory 会自动重启失败的服务,并在没有操作员的情况下恢复被中断的工作。本页列出会重启什么、每次恢复需要多长时间,以及哪些问题仍需要您处理。单台服务器不是高可用系统:重启会短暂中断连接,客户端会恢复它们的传输。
会自动重启什么
每个服务都在平台的服务管理器下运行。API、工作进程(worker)和备份代理在无法安全继续时会自行结束自己的进程。随后服务管理器会启动一个新进程。
| 情况 | Linux(systemd) | Windows 服务 | Docker Compose |
|---|---|---|---|
| 崩溃、被终止、内存不足 | 10 秒后重启 | 10 秒后重启 | 容器引擎以逐渐增长的暂停时间重启容器 |
| 未经停止请求而退出,包括退出码为 0 | 重启 | 启动器将该退出转换为退出码 1,10 秒后重启 | 重启 |
| 丢失存储所有权或租约 | 以退出码 1 退出,重启 | 以退出码 1 退出,重启 | 以退出码 1 退出,重启 |
| 主线程卡死 | 看门狗结束进程,重启 | 相同 | 相同 |
| 启动时数据库不可达 | 以退出码 1 退出,每 10 秒重试 | 以退出码 1 退出,每 10 秒重试 | 以退出码 1 退出,以逐渐增长的暂停时间重试 |
| 机器重启 | 服务在 multi-user.target 中已启用 | 自动(延迟启动) | 随容器引擎启动。Docker Desktop:用户登录后 |
| 您停止服务 | 它会保持停止,直到下次启动 | 它会保持停止,直到下次启动 | docker compose stop 会保持停止 |
自行失败的就绪检查不会重启服务。它可能因为进程在停止前排空而失败,也可能因为存储目录的某个文件夹缺失而失败。重启无法修复这些原因。
Windows 服务
图形安装程序和 install.ps1 会注册 Arkvoryapi、Arkvoryworker 和 Arkvorybackup(它们共用账户 NT AUTHORITY\LocalService),以及用于托管数据库的数据库服务 Arkvorydatabase。参见 Windows。
- 启动类型。 API、工作进程(worker)和备份代理使用“自动(延迟启动)”。数据库使用“自动”。延迟启动意味着服务在启动后过一段时间才起来,而不是同一时刻。
- 恢复操作。 发生故障后,Windows 会在 10 秒后重启服务。之后每次故障都重复相同的操作。故障计数器在一小时后重置。当进程以错误代码退出时,恢复操作也会生效。
- 停止超时。 120 秒,以便让正在运行的请求完成。
- 日志。 每个服务的输出都进入
logs\,并在 20 MiB 时轮换,保留 5 个旧文件。
显示某个服务的恢复操作:
sc.exe qfailure Arkvoryapi再次运行图形安装程序会恢复启动类型和恢复操作。您自己停止的服务会保持停止。
Linux systemd 单元
软件包和 install.sh 会创建 arkvory-api、arkvory-worker 和 arkvory-backup,并在数据库由托管时创建 arkvory-database。
Restart=always与RestartSec=10会在每次非您请求的退出后重启 API、工作进程(worker)和备份代理,包括退出码为 0 的情况。StartLimitIntervalSec=0移除了重启尝试次数的限制,因此 systemd 绝不会放弃一个失败的服务。诸如错误设置之类的持续性故障会导致每 10 秒重启一次,直到您修复它。- 数据库单元使用
Restart=on-failure,同样为 10 秒。 TimeoutStopSec=120为正在停止的服务提供两分钟。- 这些单元为
multi-user.target启用。
systemctl is-enabled arkvory-api arkvory-worker arkvory-backup
systemctl status arkvory-api arkvory-worker arkvory-backup原生服务仅支持 systemd。在使用其他 init 系统的系统上,请使用 Docker Compose。
Docker Compose
项目 proanima-arkvory 的所有服务都使用 restart: unless-stopped。一次性步骤 initialize 和 migrate 不会重启。
- API 容器有健康检查:每 10 秒使用健康密钥请求
/health/ready,启动等待期为 20 秒。不健康的容器会被标记,但不会由 Docker 重启。工作进程(worker)在启动时会等待健康的 API。 - 容器有 120 秒的时间停止。
- 容器引擎必须在启动时启动。在 Linux 上检查
systemctl is-enabled docker。Arkvory 不会更改该引擎。 - Windows 上的 Docker Desktop 是单个用户的应用程序。在用户登录并且 Docker Desktop 启动之前,不会运行任何容器。请开启 登录时启动 Docker Desktop。安装程序和
arkvory status会在它关闭时发出警告。对于必须在无登录情况下启动的服务器,请使用原生 Windows 服务。
卡死后重启
进程可能在不结束的情况下停止工作:无限循环、阻塞调用或原生代码中的卡死。服务管理器看不到这种情况,因为进程仍然存在。因此 API、工作进程(worker)和备份代理各自都有一个看门狗。
- 主线程每秒递增一次计数器。
- 第二个线程每秒检查一次该计数器。
- 当计数器连续
ARKVORY_WATCHDOG_SECONDS次检查(默认 60)都没有变化时,看门狗会向标准错误写入带字段stalledSeconds的记录process.stalled,并结束进程。 - 服务管理器会像崩溃后一样重启该进程。
看门狗统计的是自己的滴答次数,而不是时钟时间。当主机休眠或虚拟机暂停时,两个线程都会停止,唤醒后也不会凭空判定为卡死。因此一次卡死最多耗时 60 秒,再加上 10 秒的重启时间。
ARKVORY_WATCHDOG_SECONDS 接受 10 到 3600。值 0 会关闭看门狗。仅在调试器暂停进程时使用它,因为暂停超过该限制的进程会被重启。长时间的阻塞操作也算作卡死。如果看门狗本身无法启动,服务会写入 process.watchdog_failed 并在没有它的情况下继续运行。托管的 PostgreSQL 没有看门狗。它的服务管理器会在崩溃后重启它。参见环境变量。
数据库会话或存储所有权丢失
API 通过一个数据库会话来证明自己是存储目录的唯一写入者。该会话每 2 秒检查一次,未在 8 秒内应答的检查即视为丢失。工作进程(worker)以相同方式证明其角色。所有权绝不会在正在运行的进程内部恢复,因为可能有第二个进程已经接管。
当所有权丢失时(例如在 PostgreSQL 重启之后),进程会:
- 写入
api.ownership_lost或worker.ownership_lost, - 停止接受工作并取消传输,
- 以退出码 1 退出。
服务管理器会启动一个新进程,它会从头重新检查所有内容。当数据库不可用时,新进程无法启动,API 会每 10 秒退出并重启一次,直到 PostgreSQL 应答。这是预期行为。与此同时,客户端会得到带 Retry-After 的 503 unavailable。正在运行的备份代理在数据库不可用时不会退出。它会记录错误,并在其轮询间隔(默认 15 秒)之后重试。
进行中的工作会怎样
崩溃会中断打开的连接。已确认的数据会保留。接下来会发生什么取决于工作的类型。
| 工作 | 重启之后 |
|---|---|
| 下载 | 客户端通过范围请求续传。SDK 和命令行客户端会自行完成 |
| 分片上传 | 已记录的分片保留在服务器上。客户端询问存在哪些分片,并发送缺失的分片。会话自创建起保持打开 7 天 |
| 单请求上传整个文件 | 客户端从第一个字节重新发送文件 |
| 由工作进程完成上传 | 见下文 |
| 备份 | 见下文 |
| 镜像同步 | 工作进程在每次应用更改后保存其位置,并从第一个缺失的分片开始复制文件。失败后它会等待 2 秒,并在尝试之间翻倍,最多到 5 分钟 |
| 更新 | 安装程序保留其锁和日志。它不会自行继续。参见故障排查 |
SDK 和命令行客户端会有限次数地重试网络故障以及 408、429、502、503 和 504 应答。其他客户端需要自己的重试机制。参见传输。
完成作业。 大型上传由工作进程(worker)完成(SDK 和命令行客户端从 16 GiB 起会这样做)。工作进程对作业持有 30 秒的租约,并每 2 秒续租一次。当工作进程崩溃时,租约会在 30 秒内到期,重启后的工作进程会再次接手该作业。一个作业最多运行 5 次。失败后它会等待 2 秒,并翻倍直到 60 秒。以下错误会立即结束作业:forbidden、invalid_input、integrity_mismatch 和 not_found。用尽所有尝试的作业会得到记录 completion.attempts_exhausted。再次请求完成同一上传会将作业重新排队。完成过程会检查已存储的字节,因此重复执行是安全的。
同一数据库上的第二个工作进程(worker)作为待机(worker.standby)等待,并每 5 秒检查第一个是否已消失。
备份代理。 代理持有 60 秒的租约(ARKVORY_BACKUP_LEASE_SECONDS),并每 20 秒续租一次。崩溃后,另一个代理或重启后的代理会在租约到期时接手,因此备份最多等待一分钟。被中断的作业会使用相同的键再次运行,最多 5 次。新的捕获会释放已死者的锁。警告 agent_offline 会在 2 分钟没有心跳后出现。在更新期间,安装程序会先停止代理,正在运行的备份会以 interrupted 结束并被重新排队。
速率限制。 按地址的登录计数器存在于进程中,重启时重置。账户的退避在数据库中并会保留。
启动时的检查
每个进程在提供服务之前都会检查其环境。检查失败会以退出码 1 结束进程,并输出一行 startup.failed(API)或 worker.unavailable(工作进程)。reason 会在不含机密的情况下指明原因。
| 进程 | 检查内容 |
|---|---|
| API | 每项设置都有有效值;消息会指明变量名,绝不显示其值。密钥文件可作为 JSON 读取,最大 1 MiB。内置 TLS:证书和密钥可读、匹配且未过期;不会回退到 HTTP。存储目录可写。数据库能够应答,并具有本版本的所有迁移,且没有来自更新版本的迁移。存储目录中的文件 storage-id 与数据库中存储的身份一致。没有其他写入者持有该数据库 |
| 工作进程 | 相同的设置、数据库、存储身份,以及单工作进程的锁。第二个工作进程会作为待机等待 |
| 备份代理 | 存储身份、模式编号,以及备份存储不与存储目录重叠。缺失或未挂载的备份存储不是致命错误。代理会将其报告为警告 |
更新之后,安装程序会等待连续三次成功的就绪应答,以及一个正在运行的工作进程(worker)。然后它会等待大约 90 秒,以获取备份代理的心跳。代理缺失只是警告,绝不会回滚更新。
仍需您处理的情况
自愈涵盖进程的故障。以下情况需要操作员:
- 持续性故障。 错误的设置、不可达的数据库、磁盘写满或错误的权限会让服务每 10 秒重启一次却不成功。请阅读
startup.failed并修复原因。参见故障排查。 - 失败的更新。 被中断的更新会保留其锁和日志,直到您运行
recover。 - 损坏的备份。
verify_failed和vault_unavailable需要人工处理。代理会让备份存储保持不变。 - 证书。 Arkvory 无需重启即可读取续期后的证书文件(默认每 300 秒),但您的工具必须续期它们。
- 已停止的服务。 您停止的服务会保持停止。
- 平台。 Docker 必须在启动时启动。PostgreSQL 主版本、Node.js 和操作系统由您更新。
- 服务器或磁盘丢失。 没有故障切换。请从备份恢复。参见备份。