为了避免让运行极狐 GitLab 的服务器负担过重,你可以限制以下的并发:

  • RPCs。
  • Pack 对象。

这些限制可以是固定的,也可以是自适应的。

{{< alert type=”warning” >}}

在你的环境中启用限制应谨慎进行,并且仅在特定情况下,例如保护不受意外流量影响时进行。当达到限制时,确实会导致断开连接,对用户产生负面影响。为了获得一致和稳定的性能,你应该首先探索其他选项,例如调整节点规格,和审查大型代码库或工作负载。

{{< /alert >}}

限制 RPC 并发

在克隆或拉取代码库时,各种 RPC 在后台运行。特别是 Git pack RPCs:

  • SSHUploadPackWithSidechannel (用于 Git SSH)。
  • PostUploadPackWithSidechannel (用于 Git HTTP)。

这些 RPCs 可以消耗大量资源,在以下情况下可能会产生显著影响:

  • 意外的高流量。
  • 运行针对不遵循最佳实践的大型代码库

你可以使用极狐 GitLab 配置文件中的并发限制来限制这些进程在这些情况下对极狐 GitLab 服务器的影响。例如:

# 在 /etc/gitlab/gitlab.rb 中
gitaly['configuration'] = {
   # ...
   concurrency: [
      {
         rpc: '/gitaly.SmartHTTPService/PostUploadPackWithSidechannel',
         max_per_repo: 20,
         max_queue_wait: '1s',
         max_queue_size: 10,
      },
      {
         rpc: '/gitaly.SSHService/SSHUploadPackWithSidechannel',
         max_per_repo: 20,
         max_queue_wait: '1s',
         max_queue_size: 10,
      },
   ],
}
  • rpc 是设置每个代码库并发限制的 RPC 的名称。
  • max_per_repo 是每个代码库的给定 RPC 的最大在飞 RPC 调用数量。
  • max_queue_wait 是请求可以在并发队列中等待被极狐 GitLab 处理的最长时间。
  • max_queue_size 是并发队列(每个 RPC 方法)在请求被极狐 GitLab 拒绝之前可以增长的最大大小。

这限制了给定 RPCs 的在飞 RPC 调用数量。限制是应用于每个代码库。在上述示例中:

  • 每个由极狐 GitLab 服务器服务的代码库最多可以有 20 个同时进行的 PostUploadPackWithSidechannelSSHUploadPackWithSidechannel RPC 调用。
  • 如果另一个请求进入一个已经用完 20 个插槽的代码库,该请求将被排队。
  • 如果一个请求在队列中等待超过 1 秒,将被拒绝并抛出错误。
  • 如果队列增长超过 10,后续请求将被拒绝并抛出错误。

{{< alert type=”note” >}}

当达到这些限制时,用户会被断开连接。

{{< /alert >}}

你可以使用极狐 GitLab 日志和 Prometheus 观察这个队列的行为。有关更多信息,请参阅相关文档

限制 pack-objects 并发

{{< history >}}

  • 在极狐 GitLab 15.11 中引入,使用名为 gitaly_pack_objects_limiting_remote_ip功能标志默认禁用。
  • 在极狐 GitLab 16.0 中 GA。功能标志 gitaly_pack_objects_limiting_remote_ip 被移除。

{{< /history >}}

极狐 GitLab 在处理 SSH 和 HTTPS 流量以克隆或拉取代码库时触发 git-pack-objects 进程。这些进程生成一个 pack-file,在意外的高流量或并发拉取大型代码库的情况下可能会消耗大量资源。在 JihuLab.com,我们也观察到客户端有慢速互联网连接的问题。

你可以通过在极狐 GitLab 配置文件中设置 pack-objects 并发限制来限制这些进程对极狐 GitLab 服务器的影响。此设置限制每个远程 IP 地址的在飞 pack-object 进程数量。

{{< alert type=”warning” >}}

只有在特定情况下,谨慎启用这些限制,例如保护不受意外流量影响时进行。当达到限制时,这些限制会断开用户连接。为了获得一致和稳定的性能,你应该首先探索其他选项,例如调整节点规格,和审查大型代码库或工作负载。

{{< /alert >}}

示例配置:

# 在 /etc/gitlab/gitlab.rb 中
gitaly['pack_objects_limiting'] = {
   'max_concurrency' => 15,
   'max_queue_length' => 200,
   'max_queue_wait' => '60s',
}
  • max_concurrency 是每个键的最大在飞 pack-object 进程数量。
  • max_queue_length 是并发队列(每个键)在请求被极狐 GitLab 拒绝之前可以增长的最大大小。
  • max_queue_wait 是请求可以在并发队列中等待被极狐 GitLab 处理的最长时间。

在上述示例中:

  • 每个远程 IP 在极狐 GitLab 节点上最多可以有 15 个同时进行的 pack-object 进程。
  • 如果另一个请求从一个已经用完 15 个插槽的 IP 进入,该请求将被排队。
  • 如果一个请求在队列中等待超过 1 分钟,将被拒绝并抛出错误。
  • 如果队列增长超过 200,后续请求将被拒绝并抛出错误。

当 pack-object 缓存启用时,pack-objects 限制仅在缓存未命中时生效。有关更多信息,请参阅Pack-objects 缓存

你可以使用极狐 GitLab 日志和 Prometheus 观察这个队列的行为。有关更多信息,请参阅监控极狐 GitLab pack-objects 并发限制

自适应并发限制

{{< history >}}

  • 在极狐 GitLab 16.6 中引入。

{{< /history >}}

极狐 GitLab 支持两种并发限制:

  • RPC 并发限制,允许你为每个极狐 GitLab RPC 配置最大同时在飞请求数量。限制是按 RPC 和代码库范围划分的。
  • Pack-objects 并发限制,限制按 IP 的并发 Git 数据传输请求数量。

如果超过此限制,则:

  • 请求被放入队列。
  • 如果队列已满或请求在队列中停留时间过长,请求被拒绝。

这两种并发限制可以静态配置。虽然静态限制可以产生良好的保护效果,但它们有一些缺点:

  • 静态限制不适用于所有使用模式。没有万能值。如果限制过低,大型代码库会受到负面影响。如果限制过高,保护基本上失效。
  • 维护并发限制的合理值很繁琐,特别是当每个代码库的工作负载随时间变化时。
  • 请求可能会被拒绝,即使服务器处于空闲状态,因为速率没有考虑服务器的负载。

你可以通过配置自适应并发限制来克服所有这些缺点并保持并发限制的好处。自适应并发限制是可选的,构建在两种并发限制类型之上。它使用加法增加/乘法减少 (AIMD) 算法。每个自适应限制:

  • 在典型进程运行期间逐渐增加到某个上限。
  • 当主机机器出现资源问题时迅速减少。

这种机制为机器提供了一些“呼吸”的空间,并加快了当前在飞请求。

图表显示了极狐 GitLab 自适应并发限制根据系统资源使用情况调整,遵循 AIMD 算法

自适应限制器每 30 秒校准一次限制:

  • 直到达到上限,限制增加一。
  • 当顶级 cgroup 的内存使用超过 90%(不包括易驱逐页面缓存),或 CPU 在观察时间的 50% 或以上受到限制时,限制减少一半。

否则,限制增加一,直到达到上限。

自适应限制是为每个 RPC 或 pack-objects 缓存单独启用的。然而,限制在同一时间校准。

启用 RPC 并发的自适应性

前提条件:

  • 因为自适应限制依赖于控制组,在使用自适应限制之前必须启用控制组。

以下是为 RPC 并发配置自适应限制的示例:

# 在 /etc/gitlab/gitlab.rb 中
gitaly['configuration'] = {
    # ...
    cgroups: {
        # 启用控制组支持所需的最低配置。
        repositories: {
            count: 1
        },
    },
    concurrency: [
        {
            rpc: '/gitaly.SmartHTTPService/PostUploadPackWithSidechannel',
            max_queue_wait: '1s',
            max_queue_size: 10,
            adaptive: true,
            min_limit: 10,
            initial_limit: 20,
            max_limit: 40
        },
        {
            rpc: '/gitaly.SSHService/SSHUploadPackWithSidechannel',
            max_queue_wait: '10s',
            max_queue_size: 20,
            adaptive: true,
            min_limit: 10,
            initial_limit: 50,
            max_limit: 100
        },
   ],
}

在此示例中:

  • adaptive 设置是否启用自适应性。如果设置,则忽略 max_per_repo 值,转而使用以下配置。
  • initial_limit 是极狐 GitLab 启动时使用的每代码库并发限制。
  • max_limit 是配置的 RPC 的每代码库并发限制的最大值。极狐 GitLab 增加当前限制,直到达到此值。
  • min_limit 是配置的 RPC 的每代码库并发限制的最小值。当主机机器出现资源问题时,极狐 GitLab 快速减少限制,直到达到此值。

有关更多信息,请参阅RPC 并发

启用 pack-objects 并发的自适应性

前提条件:

  • 因为自适应限制依赖于控制组,在使用自适应限制之前必须启用控制组。

以下是为 pack-objects 并发配置自适应限制的示例:

# 在 /etc/gitlab/gitlab.rb 中
gitaly['pack_objects_limiting'] = {
   'max_queue_length' => 200,
   'max_queue_wait' => '60s',
   'adaptive' => true,
   'min_limit' => 10,
   'initial_limit' => 20,
   'max_limit' => 40
}

在此示例中:

  • adaptive 设置是否启用自适应性。如果设置,则忽略 max_concurrency 的值,转而使用以下配置。
  • initial_limit 是极狐 GitLab 启动时使用的每 IP 并发限制。
  • max_limit 是 pack-objects 的每 IP 并发限制的最大值。极狐 GitLab 增加当前限制,直到达到此值。
  • min_limit 是 pack-objects 的每 IP 并发限制的最小值。当主机机器出现资源问题时,极狐 GitLab 快速减少限制,直到达到此值。

有关更多信息,请参阅pack-objects 并发