데이터베이스 로드 밸런싱
Offering: GitLab Self-Managed
데이터베이스 로드 밸런싱을 사용하면 읽기 전용 쿼리를 여러 PostgreSQL 노드에 분산하여 성능을 향상시킬 수 있습니다. 이 기능은 GitLab Rails 및 Sidekiq에서 기본적으로 제공되며, 외부 의존성 없이 라운드 로빈 방식으로 데이터베이스 읽기 쿼리의 균형을 조정하도록 구성할 수 있습니다:
데이터베이스 로드 밸런싱을 사용하면 읽기 전용 쿼리를 여러 PostgreSQL 노드에 분산하여 성능을 향상시킬 수 있습니다.
이 기능은 GitLab Rails 및 Sidekiq에서 기본적으로 제공되며, 외부 의존성 없이 라운드 로빈 방식으로 데이터베이스 읽기 쿼리의 균형을 조정하도록 구성할 수 있습니다:
소스 코드 보기
@startuml
!theme plain
card "**Internal Load Balancer**" as ilb
skinparam linetype ortho
together {
collections "GitLab Rails x3" as gitlab
collections "Sidekiq x4" as sidekiq
}
collections "Consul x3" as consul
card "Database" as database {
collections "PGBouncer x3\n//Consul//" as pgbouncer
card "PostgreSQL //Primary//\n//Patroni//\n//PgBouncer//\n//Consul//" as postgres_primary
collections "PostgreSQL //Secondary// x2\n//Patroni//\n//PgBouncer//\n//Consul//" as postgres_secondary
pgbouncer --> postgres_primary
postgres_primary .r-> postgres_secondary
}
gitlab --> ilb
gitlab -[hidden]-> pgbouncer
gitlab .[norank]-> postgres_primary
gitlab .[norank]-> postgres_secondary
sidekiq --> ilb
sidekiq -[hidden]-> pgbouncer
sidekiq .[norank]-> postgres_primary
sidekiq .[norank]-> postgres_secondary
ilb --> pgbouncer
consul -r-> pgbouncer
consul .[norank]r-> postgres_primary
consul .[norank]r-> postgres_secondary
@enduml
데이터베이스 로드 밸런싱 활성화 요구 사항#
데이터베이스 로드 밸런싱을 활성화하려면 다음을 확인하세요:
- HA PostgreSQL 설정에 기본을 복제하는 하나 이상의 보조 노드가 있습니다.
- 각 PostgreSQL 노드가 동일한 자격 증명과 동일한 포트로 연결되어 있습니다.
Linux 패키지 설치의 경우 다중 노드 설정을 구성할 때 모든 부하 분산 연결을 풀링하기 위해 각 PostgreSQL 노드에 PgBouncer도 구성해야 합니다.
데이터베이스 로드 밸런싱 구성#
데이터베이스 로드 밸런싱은 다음 두 가지 방법 중 하나로 구성할 수 있습니다:
호스트#
호스트 목록을 구성하려면 균형을 조정하려는 각 환경의 모든 GitLab Rails 및 Sidekiq 노드에서 다음 단계를 수행합니다:
-
/etc/gitlab/gitlab.rb파일을 편집합니다. -
gitlab_rails['db_load_balancing']에서 균형을 조정할 데이터베이스 호스트 배열을 만듭니다. 예를 들어primary.example.com,secondary1.example.com,secondary2.example.com호스트에서 PostgreSQL이 실행되는 환경에서:gitlab_rails['db_load_balancing'] = { 'hosts' => ['primary.example.com', 'secondary1.example.com', 'secondary2.example.com'] }이 호스트들은
gitlab_rails['db_port']로 구성된 동일한 포트에서 접근 가능해야 합니다. -
파일을 저장하고 GitLab을 재구성합니다.
기본 서버를 호스트 목록에 추가하는 것은 선택 사항이지만 권장됩니다. 이렇게 하면 기본 서버가 부하 분산 읽기 쿼리의 대상이 되어 기본 서버가 해당 쿼리를 처리할 용량이 있을 때 시스템 성능이 향상됩니다. 트래픽이 매우 많은 인스턴스는 기본 서버가 읽기 복제본으로 사용될 용량이 없을 수 있습니다. 기본 서버는 이 목록의 존재 여부와 상관없이 쓰기 쿼리에 사용됩니다.
서비스 디스커버리#
서비스 디스커버리를 사용하면 GitLab이 사용할 PostgreSQL 호스트 목록을 자동으로 검색할 수 있습니다. DNS A 레코드를 주기적으로 확인하여 이 레코드에서 반환된 IP를 보조 서버의 주소로 사용합니다. 서비스 디스커버리가 작동하려면 DNS 서버와 보조 서버의 IP 주소가 포함된 A 레코드만 있으면 됩니다.
Linux 패키지 설치를 사용하는 경우 제공된 Consul 서비스가 DNS 서버로 작동하며 postgresql-ha.service.consul 레코드를 통해 PostgreSQL 주소를 반환합니다. 예:
-
각 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' } } -
변경 사항이 적용되도록 파일을 저장하고 GitLab을 재구성합니다.
| 옵션 | 설명 | 기본값 |
|---|---|---|
nameserver |
DNS 레코드 조회에 사용할 네임서버. | localhost |
record |
조회할 레코드. 이 옵션은 서비스 디스커버리가 작동하려면 필수입니다. | |
record_type |
조회할 선택적 레코드 유형. A 또는 SRV 중 하나일 수 있습니다. |
A |
port |
네임서버의 포트. | 8600 |
interval |
DNS 레코드 확인 사이의 최소 시간(초). | 60 |
disconnect_timeout |
호스트 목록이 업데이트된 후 이전 연결이 닫히는 시간(초). | 120 |
use_tcp |
UDP 대신 TCP를 사용하여 DNS 리소스 조회 | false |
max_replica_pools |
각 Rails 프로세스가 연결하는 최대 복제본 수. 이것은 많은 Postgres 복제본과 많은 Rails 프로세스를 실행하는 경우에 유용합니다. 이 한도가 없으면 모든 Rails 프로세스가 기본적으로 모든 복제본에 연결하기 때문입니다. 설정하지 않으면 기본 동작은 무제한입니다. | nil |
record_type이 SRV로 설정된 경우 GitLab은 계속 라운드 로빈 알고리즘을 사용하고 레코드의 weight와 priority를 무시합니다. SRV 레코드는 보통 IP 대신 호스트 이름을 반환하기 때문에 GitLab은 SRV 응답의 추가 섹션에서 반환된 호스트 이름의 IP를 찾아야 합니다. 호스트 이름에 대한 IP를 찾을 수 없으면 GitLab은 구성된 nameserver에 각 호스트 이름에 대한 ANY 레코드를 쿼리하여 A 또는 AAAA 레코드를 찾아야 하며, 결국 IP를 확인할 수 없으면 해당 호스트 이름을 순환에서 제거합니다.
interval 값은 확인 사이의 최소 시간을 지정합니다. A 레코드의 TTL이 이 값보다 큰 경우 서비스 디스커버리는 해당 TTL을 따릅니다. 예를 들어 A 레코드의 TTL이 90초이면 서비스 디스커버리는 A 레코드를 다시 확인하기 전에 최소 90초를 기다립니다.
호스트 목록이 업데이트될 때 이전 연결이 종료되는 데 시간이 걸릴 수 있습니다. disconnect_timeout 설정을 사용하여 모든 이전 데이터베이스 연결을 종료하는 데 걸리는 시간의 상한을 적용할 수 있습니다.
오래된 읽기 처리#
히스토리
- GitLab 14.0에서 GitLab Premium에서 GitLab Free로 이동.
오래된 보조 서버에서 읽는 것을 방지하기 위해 로드 밸런서는 기본 서버와 동기화되어 있는지 확인합니다. 데이터가 충분히 최신이면 보조 서버가 사용되고, 그렇지 않으면 무시됩니다. 이러한 확인의 오버헤드를 줄이기 위해 특정 간격에서만 수행합니다.
이 동작에 영향을 미치는 세 가지 구성 옵션이 있습니다:
| 옵션 | 설명 | 기본값 |
|---|---|---|
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 - 항상 기록되는 컨텍스트 정보. 예:
severity및time.
예:
{"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번 재시도됩니다.
로드 밸런싱을 사용할 때 사용자에게 즉시 오류가 표시되지 않고 데이터베이스 서버를 안전하게 재시작할 수 있어야 합니다.
개발 가이드#
데이터베이스 로드 밸런싱에 대한 자세한 개발 가이드는 개발 문서를 참조하세요.
