{{< details >}}

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: 私有化部署

{{< /details >}}

使用数据库负载均衡,可以将只读查询分布到多个 PostgreSQL 节点上,以提高性能。

这种功能在极狐GitLab Rails 和 Sidekiq 中是原生提供的,它们可以配置为以循环方式均衡数据库读取查询,而无需任何外部依赖:

启用数据库负载均衡的要求

要启用数据库负载均衡,请确保:

  • HA PostgreSQL 设置有一个或多个从节点复制主节点。
  • 每个 PostgreSQL 节点都使用相同的凭证连接,并且端口相同。

对于 Linux 软件包安装,还需要在每个 PostgreSQL 节点上配置 PgBouncer,以便在配置多节点设置时池化所有负载均衡连接。

配置数据库负载均衡

数据库负载均衡可以通过两种方式进行配置:

  • (推荐)主机:PostgreSQL 主机列表。
  • 服务发现:返回 PostgreSQL 主机列表的 DNS 记录。

主机

要配置主机列表,请在您希望均衡的每个环境中的所有极狐GitLab Rails 和 Sidekiq 节点上执行以下步骤:

  1. 编辑 /etc/gitlab/gitlab.rb 文件。
  2. gitlab_rails['db_load_balancing'] 中,创建要均衡的数据库主机数组。例如,在 一个环境中,PostgreSQL 运行在 primary.example.comsecondary1.example.comsecondary2.example.com 主机上:

    gitlab_rails['db_load_balancing'] = { 'hosts' => ['primary.example.com', 'secondary1.example.com', 'secondary2.example.com'] }
    

    这些主机必须在配置了 gitlab_rails['db_port'] 的相同端口上可达。

  3. 保存文件并重新配置极狐GitLab

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

将主节点添加到主机列表中是可选的,但推荐这样做。这使得主节点可以用于负载均衡的读取查询,提高系统性能当主节点有能力处理这些查询时。非常高流量的实例可能没有能力在主节点上作为读取副本。主节点将用于写入查询,无论它是否在此列表中。

{{< /alert >}}

服务发现

服务发现允许极狐GitLab 自动检索要使用的 PostgreSQL 主机列表。它定期检查 DNS A 记录,使用此记录返回的 IP 作为从节点的地址。为了让服务发现正常工作,您只需要一个 DNS 服务器和包含从节点 IP 地址的 A 记录。

使用 Linux 软件包安装时,提供的 Consul 服务作为 DNS 服务器,通过 postgresql-ha.service.consul 记录返回 PostgreSQL 地址。例如:

  1. 在每个极狐GitLab Rails / Sidekiq 节点上,编辑 /etc/gitlab/gitlab.rb 并添加以下内容:

    gitlab_rails['db_load_balancing'] = { 'discover' => {
        'nameserver' => 'localhost'
        'record' => 'postgresql-ha.service.consul'
        'record_type' => 'A'
        'port' => '8600'
        'interval' => '60'
        'disconnect_timeout' => '120'
      }
    }
    
  2. 保存文件并重新配置极狐GitLab以使更改生效。

选项 描述 默认值
nameserver 用于查找 DNS 记录的名称服务器。 localhost
record 要查找的记录。此选项是服务发现正常工作的必需条件。  
record_type 可选的记录类型进行查找。可以是 ASRV A
port 名称服务器的端口。 8600
interval 检查 DNS 记录的最短时间间隔(以秒为单位)。 60
disconnect_timeout 更新主机列表后关闭旧连接的时间(以秒为单位)。 120
use_tcp 使用 TCP 而不是 UDP 查找 DNS 资源 false
max_replica_pools 每个 Rails 进程连接的最大副本数。这在您运行很多 PostgreSQL 副本和很多 Rails 进程时很有用,因为如果不设置此限制,每个 Rails 进程默认连接到每个副本。默认行为是无限制。 nil

如果 record_type 设置为 SRV,那么极狐GitLab继续使用循环算法并忽略记录中的 weightpriority。因为 SRV 记录通常返回主机名而不是 IP,极狐GitLab需要在 SRV 响应的附加部分中查找返回主机名的 IP。如果找不到主机名的 IP,极狐GitLab 需要查询配置的 nameserverANY 记录以查找 AAAAA 记录,最终在无法解析 IP 时将此主机名从轮换中删除。

interval 值指定检查之间的最短时间。如果 A 记录的 TTL 大于该值,则服务发现遵循该 TTL。例如,如果 A 记录的 TTL 为 90 秒,则服务发现至少等待 90 秒后再次检查 A 记录。

当主机列表更新时,可能需要一段时间才能终止旧连接。可以使用 disconnect_timeout 设置来强制终止所有旧数据库连接所需的时间上限。

处理陈旧读取

{{< history >}}

  • 在极狐GitLab 14.0 中,从专业版移动至基础版。

{{< /history >}}

为了防止从过时的从节点读取,负载均衡器检查它是否与主节点同步。如果数据足够新,则使用从节点,否则忽略。为了减少这些检查的开销,我们仅在某些间隔执行它们。

有三个配置选项影响此行为:

选项 描述 默认值
max_replication_difference 从节点在未复制数据一段时间时允许滞后的数据量(以字节为单位)。 8 MB
max_replication_lag_time 从节点允许滞后的最大秒数,然后停止使用它。 60 秒
replica_check_interval 检查从节点状态前必须等待的最小秒数。 60 秒

默认设置应该足以满足大多数用户的需求。

要使用主机列表配置这些选项,请使用以下示例:

gitlab_rails['db_load_balancing'] = {
  'hosts' => ['primary.example.com', 'secondary1.example.com', 'secondary2.example.com'],
  'max_replication_difference' => 16777216, # 16 MB
  'max_replication_lag_time' => 30,
  'replica_check_interval' => 30
}

日志记录

负载均衡器在 database_load_balancing.log 中记录各种事件,例如:

  • 当主机被标记为离线时
  • 当主机重新上线时
  • 当所有从节点都离线时
  • 当由于查询冲突而在不同主机上重试读取时

日志结构为每个条目包含至少一个 JSON 对象:

  • 一个 event 字段用于过滤。
  • 一个可读的 message 字段。
  • 一些事件特定的元数据。例如,db_host
  • 始终记录的上下文信息。例如,severitytime

例如:

{"severity":"INFO","time":"2019-09-02T12:12:01.728Z","correlation_id":"abcdefg","event":"host_online","message":"Host came back online","db_host":"111.222.333.444","db_port":null,"tag":"rails.database_load_balancing","environment":"production","hostname":"web-example-1","fqdn":"gitlab.example.com","path":null,"params":null}

实施细节

平衡查询

只读 SELECT 查询在所有给定的主机之间平衡。其他所有查询(包括事务)都在主节点上执行。诸如 SELECT ... FOR UPDATE 的查询也在主节点上执行。

预处理语句

预处理语句在负载均衡中效果不佳,负载均衡启用时会自动禁用这些语句。这不应影响响应时间。

主节点粘滞

执行写入后,极狐GitLab 会在一定时间内坚持使用主节点,范围限定为执行写入的用户。极狐GitLab在从节点已赶上或 30 秒后恢复使用从节点。

故障转移处理

在故障转移或数据库无响应的情况下,负载均衡器尝试使用下一个可用主机。如果没有从节点可用,则操作在主节点上执行。

如果在写入数据时发生连接错误,则操作将使用指数回退重试最多 3 次。

使用负载均衡时,您应该能够安全地重新启动数据库服务器而不会立即导致错误呈现给用户。