读取网关
读取网关是一个额外的仅提供下载服务的 API 进程。它与主 API(写入端)运行在同一台服务器上,使用同一个 PostgreSQL 数据库和同一个存储目录,并与写入端及其他网关共享一份下载预算。
当总下载速率保持在你设定的单一上限以内时,使用网关可以把大量并行下载分摊到多个进程上。网关不复制数据。它读取写入端发布的文件,因此网关永远不会滞后。它也无法保护你免受服务器或磁盘丢失的影响。为此,请参见备份和镜像。
工作原理
- 一个安装实例有一个写入端和最多 15 个读取网关。它们合计最多为 16 个槽位。写入端始终使用槽位 0。每个网关使用自己的槽位,从 1 到槽位总数减一。
- 所有进程使用一个 PostgreSQL 数据库和一个存储目录。网关会检查存储是否存在并属于该数据库。它绝不会创建存储。
- 你为所有进程设定一个总下载速率。每个进程获得相等的固定份额:总数除以槽位数,向下取整。
- 进程通过数据库中的租约持有它的槽位。如果失去租约,它就停止提供新的负载,并且必须重启。这使所有份额之和不超出总数。
写入端保留它的常规职责。它接收上传、控制台、后台物理清理和所有变更。网关从不运行物理清理。
网关拒绝的操作
网关只接受 GET 和 HEAD。所有会改变内容的请求都会收到 HTTP 405,带有响应头 Allow: GET, HEAD 和代码 read_only,即使该密钥拥有写入权限也是如此。这包括登录和自助注册。控制台仅属于写入端,因此网关不提供控制台。
仓库权限在每次读取时都会检查,与写入端相同。会话、个人令牌和服务密钥可在网关上用于读取。
要求
- 同一台服务器。 网关必须能立即看到写入端发布的文件,不能有延迟。使用
rsync或其他异步复制的独立磁盘不适用。尚未认证任何网络文件系统,因此请在同一台服务器上为多个进程使用网关。 - 相同的服务密钥。 为每个进程提供相同的
ARKVORY_KEYS_FILE内容,使文件密钥及其 ID 一致。受管服务密钥存放在数据库中,因此它们自身就是一致的。 - 独立端口。 同一主机上的每个进程都需要自己的
ARKVORY_PORT。 - 文件的只读视图。 如果可以,请为网关以只读方式挂载存储目录。HTTP 拒绝不能替代操作系统权限。请注意,网关仍会写入数据库:租约、存储诊断、个人令牌的最后使用时间,以及保护正在读取的文件的锁。
- 数据库连接。 每个网关需要比
ARKVORY_DATABASE_POOL_SIZE多三个连接。请把它们计入 PostgreSQL 的max_connections。
运行网关
安装程序会注册 API、工作进程(worker)和备份代理。它们不会注册网关,arkvory status 也不会管理网关。你自行启动网关,作为已安装版本 API 程序的又一个实例,使用它自己的环境并在你自己的服务管理器下运行。
所有进程共有的设置,用于总共两个进程、总体 64 MiB/s、单个账户或密钥 16 MiB/s 的情况:
ARKVORY_GATEWAY_SLOTS=2
ARKVORY_SHARED_DOWNLOAD_BYTES_PER_SECOND=67108864
ARKVORY_SHARED_DOWNLOAD_BYTES_PER_SECOND_PER_PRINCIPAL=16777216写入端添加:
ARKVORY_ROLE=api
ARKVORY_GATEWAY_SLOT=0网关添加:
ARKVORY_ROLE=reader
ARKVORY_GATEWAY_SLOT=1
ARKVORY_PORT=8081网关还需要其余 API 设置:同一个数据库的 ARKVORY_DATABASE_URL,指向同一存储的 ARKVORY_DATA_DIR(路径可以不同,存储标识必须匹配)、ARKVORY_KEYS_FILE,以及当网关可以从其他计算机访问时的 HTTPS 设置。参见环境变量。
| 变量 | 规则 |
|---|---|
ARKVORY_GATEWAY_SLOTS | 进程数(包括写入端),2–16 |
ARKVORY_GATEWAY_SLOT | 此进程的槽位,从 0 到槽位总数减一。写入端为 0,网关不为 0 |
ARKVORY_SHARED_DOWNLOAD_BYTES_PER_SECOND | 必需。所有进程的总速率,至少为 65 536 乘以槽位数,最高为每秒 1 TiB |
ARKVORY_SHARED_DOWNLOAD_BYTES_PER_SECOND_PER_PRINCIPAL | 单个账户或密钥在所有进程上的总速率。0 表示无限制。否则范围与上面相同 |
如果你设置了其中任何一个变量,请在每个进程上设置槽位、槽位总数和总速率。无效的值会在启动时停止进程,并给出指明该变量的消息。没有共享下载配置的网关会拒绝启动。
- 决定槽位数和速率。
- 将三个通用变量和写入端自己的两个变量添加到写入端,然后重启写入端。它会将该策略保存到数据库。
- 使用它自己的变量启动网关。如果它的数值与保存的策略不同,它就不会启动。
- 检查每个进程的就绪状态,并在每个进程上测试一次范围下载。参见监控网关。
- 只有在那之后,才把网关加入你的负载均衡器。
有些规则用于保护该配置:
- 网关只有在写入端保存策略之后才能启动。
- 一旦策略存在于数据库中,缺少这些变量的写入端就不会启动。它会以数据库要求共享下载配置的消息停止。
- 你不能在运行中的安装实例上更改速率或槽位数。参见更改配置。
下载预算
每个进程获得 total / slots,向下取整。对单个账户或密钥的速率也是如此。例如,64 MiB/s 和 2 个槽位时,每个进程最多提供 32 MiB/s,一个账户在每个进程中最多获得 8 MiB/s。
- 一个进程不能使用另一个进程的份额。如果两个进程中的一个停止,你只能得到总速率的一半。这使限制简单且可核查。
- 本地设置
ARKVORY_DOWNLOAD_BYTES_PER_SECOND和ARKVORY_DOWNLOAD_BYTES_PER_SECOND_PER_PRINCIPAL可以降低份额,不能提高份额。 - 上传预算留在写入端,因为网关不接收上传。
- 等待传输的队列和活动传输的上限保持在每个进程本地,因此所有进程的容量会相加。
该限制适用于应用程序的负载,并允许少量突发。它不是网卡的限制。参见环境变量。
租约与故障
数据库为一个槽位保留 10 秒。进程每 2 秒续租一次,并在本地最多信任租约 8 秒。已超时的租约绝不会复活,即使迟到的回复到达也是如此。
- 租约丢失。 进程停止发出新的负载,对新的已授权请求以 503 应答,并且需要重启。被中断的下载可以通过重试或范围请求继续。这也适用于写入端。
- 同一槽位重启。 新进程会等待旧保留过期,最长到上一次续租后 10 秒,总计最长 15 秒。如果仍在运行的网关持有该槽位,新进程会以
busy停止。 - 时钟。 租约依赖稳定的时钟。数据库服务器的时钟跳变,或虚拟机暂停,都可能导致进程在租约之外继续提供服务。在这种情况下,请先停止旧进程,再启动替代进程。
- 数据库故障。 数据库是薄弱环节。如果它变得不可达,租约会过期,所有进程都会停止提供负载。
服务器只能通过 TCP keepalive 察觉丢失网络的死进程。在 PostgreSQL 上设置 tcp_keepalives_idle、tcp_keepalives_interval 和 tcp_keepalives_count,例如设为 10、5 和 3 秒,或设置 tcp_user_timeout。没有它们,新的写入端或工作进程可能会等待操作系统较长的默认超时。
监控网关
GET /health/status是公开的,只返回ready、unavailable或draining,当进程无法提供服务时返回 503(丢失槽位或租约、正在排空)。请将它用于你的负载均衡器。GET /health/ready需要密钥。它返回role、writable(在网关上始终为false)、带slot、slots、active和leaseSeconds的sharedDownloads,以及本地传输队列的数量。当槽位丢失时它以 503 应答。对于独立安装实例,sharedDownloads为null。GET /health/live只表明 HTTP 进程在运行。它不能说明网关是否能提供服务。- 每个进程的
GET /health/metrics只显示该进程。请抓取每个网关的指标,并使用进程级的 HTTP 和传输指标。
请分别检查每个进程。writable 为 false 的网关是正常的。参见监控。
路由请求
负载均衡器由你负责。Arkvory 不附带任何均衡器。
- 把所有改变数据的请求以及
/console/发送到写入端。 - 你可以在写入端和网关之间分摊字节读取:针对
/api/v1/repositories/NAME/artifacts/ID/content、.../packages/content和.../asset/content的GET和HEAD。把其他请求留在写入端。 - 传递
Authorization、Range、If-Range和ETag头。以流式方式传输正文,不要缓冲整个文件。不要把客户端重定向到携带密钥的 URL。 - 只有当后端的已认证就绪检查正常时,才把它加入均衡器。
TypeScript SDK 可以通过同一地址后面的另一个健康后端继续被中断的下载。正在运行的 TCP 连接不会在服务器之间迁移。
更改配置
你无法在安装实例运行期间更改速率或槽位数,也无法在策略存在时回到单进程。即使所有网关都已停止,已保存的策略也会阻止无限制启动。
- 停止传入流量。停止写入端、每个网关和工作进程,并确认它们确实已停止。
- 等待数据库中的租约过期。
- 进行备份。参见备份。
- Arkvory 数据库的管理员在一个事务中删除
arkvory_gateway_leases和arkvory_download_policy两个表的所有行。这只会重置协调状态,不会重置目录。 - 使用新设置启动写入端,然后启动网关。
切勿在任何进程可能仍在运行时这样做。
更新也需要同样谨慎。在安装实例更新之前停止每个网关,之后从新版本启动它们。对较新数据库架构继续运行旧代码的网关会将自己报告为未就绪。用于物理清理的离线修复工具也需要停止所有网关。写入端的在线物理清理则不需要。
网关还是镜像
| 读取网关 | 镜像 | |
|---|---|---|
| 它是什么 | 同一台服务器和存储上的更多 API 进程 | 第二个独立的安装实例,带有数据的副本 |
| 数据 | 一份副本,实时读取 | 第二份副本,带延迟拉取 |
| 账户与密钥 | 与写入端相同 | 它自己的 |
| 额外磁盘 | 无 | 有,与仓库所需一样多 |
| 需要 | 同一个数据库和同一个文件系统 | 指向源的 HTTPS 链接和只读密钥 |
| 防范服务器或磁盘丢失 | 否 | 部分:源不可用期间它仍可提供服务,并且你可以切换到它 |
| 用途 | 在单一共享速率限制下进行更多并行下载 | 第二个站点、离用户更近的办公室、备用 |
两者都是备份的补充,而不是替代。
限制
- 所有进程必须共享一台服务器和一个存储目录。不同机器需要经过测试的文件系统,而目前尚未测试过任何文件系统。
- 没有安装程序支持,没有自动故障切换,也没有内置均衡器。
- 一个数据库和一个写入端仍然是单点故障。
- 预算按槽位固定,不会重新分配,也没有优先级调度。
- 你不能在运行中的安装实例上更改策略。