동시성 제한
Gitaly를 실행하는 서버를 과부하로부터 보호하기 위해 다음과 같은 작업의 동시성을 제한할 수 있습니다.
- RPCs.
- Pack 객체.
이러한 제한은 고정되어 있을 수도 있고, 적응적으로 설정할 수도 있습니다.
RPC 동시성 제한
리포지터리를 복제하거나 풀링할 때 여러 가지 RPCs가 백그라운드에서 실행됩니다. 특히 Git pack RPCs는 다음과 같습니다.
-
SSHUploadPackWithSidechannel
(Git SSH용). -
PostUploadPackWithSidechannel
(Git HTTP용).
이러한 RPCs는 상당량의 리소스를 소비할 수 있으며, 특히 다음과 같은 상황에서 상당한 영향을 미칠 수 있습니다.
- 예상치 못한 높은 트래픽.
- 최선의 실천 방법을 따르지 않는 대형 리포지터리와 실행 중인 상태.
이러한 시나리오에서 Gitaly 구성 파일의 동시성 제한을 사용하여 Gitaly 서버를 과부하에서 보호할 수 있습니다. 예시:
# in /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
는 요청이 Gitaly에 의해 처리되기 전에 대기열에서 대기할 수 있는 최대 시간입니다. -
max_queue_size
는 대기열(각 RPC 방법당)이 Gitaly에 의해 거부되기 전에 성장할 수 있는 최대 크기입니다.
이러한 제한은 주어진 RPCs의 대기 중 RPC 호출 수를 제한합니다. 이 제한은 리포지터리당 적용됩니다. 위 예시에서:
- Gitaly 서버에서 제공하는 각 리포지터리마다 최대 20개의 동시
PostUploadPackWithSidechannel
및SSHUploadPackWithSidechannel
RPC 호출이 허용됩니다. - 다른 리포지터리의 요청이 20개의 슬롯을 모두 사용한 경우 해당 요청이 대기열에 들어갑니다.
- 대기열에 대기 중인 요청이 1초 이상 지속되면 에러가 발생합니다.
- 대기열이 10을 초과하면 후속 요청이 에러로 거부됩니다.
이 대기열에 대한 동작은 Gitaly 로그와 Prometheus를 사용하여 확인할 수 있습니다. 자세한 정보는 관련 문서를 참조하십시오.
pack-objects 동시성 제한
- 도입됨: GitLab 15.11에서 gitaly_pack_objects_limiting_remote_ip이라는 플래그로 도입됨. 기본적으로 비활성화됨.
- 일반적으로 사용 가능: GitLab 16.0에서 피처 플래그
gitaly_pack_objects_limiting_remote_ip
이 제거됨.
Gitaly는 SSH 및 HTTPS 트래픽을 처리할 때 git-pack-objects
프로세스를 트리거합니다. 이러한 프로세스는 pack-file
을 생성하고, 특히 예상치 못한 높은 트래픽 또는 대형 리포지터리에서 동시에 풀링하는 경우에는 상당한 양의 리소스를 소비할 수 있습니다. GitLab.com에서 우리는 또한 인터넷 연결이 느린 클라이언트에서 문제를 관찰합니다.
Gitaly 서버를 과부하로부터 보호하기 위해 Gitaly 구성 파일에서 pack-objects 동시성 제한을 설정하여 이러한 프로세스를 제한할 수 있습니다.
예시 구성:
# in /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
는 대기열(각 키당)이 Gitaly에 의해 거부되기 전에 성장할 수 있는 최대 크기입니다. -
max_queue_wait
는 요청이 Gitaly에 의해 처리되기 전에 대기열에서 대기할 수 있는 최대 시간입니다.
위 예시에서:
- 각 원격 IP는 Gitaly 노드에서 최대 15개의 동시 pack-objects 프로세스를 진행할 수 있습니다.
- 다른 IP에서 15개의 슬롯을 사용한 요청이 들어오면 해당 요청이 대기열에 들어갑니다.
- 요청이 대기열에서 1분 이상 대기하면 에러로 거부됩니다.
- 대기열이 200을 초과하면 후속 요청이 에러로 거부됩니다.
pack-object 캐시가 활성화된 경우, pack-objects 제한은 캐시가 미스될 경우에만 적용됩니다. 자세한 내용은 Pack-objects 캐시를 참조하십시오.
이 대기열에 대한 동작은 Gitaly 로그 및 Prometheus를 사용하여 확인할 수 있습니다. 자세한 정보는 Monitor Gitaly pack-objects 동시성 제한를 참조하십시오.
적응적 동시성 제한
- 도입됨: GitLab 16.6에서 도입됨.
Gitaly는 두 가지 동시성 제한을 지원합니다.
- RPC 동시성 제한, 이는 각 Gitaly RPC에 대해 리포지터리별 동시 진행 요청의 최대 수를 구성할 수 있습니다.
- Pack-objects 동시성 제한, 이는 IP별 동시 Git 데이터 전송 요청 수를 제한합니다.
이러한 제한이 초과되면 다음 중 하나가 발생합니다.
- 요청이 대기열에 들어갑니다.
- 대기열이 가득 차 있거나 요청이 너무 오래 기다린 경우 요청이 거부됩니다.
이러한 두 가지 동시성 제한은 정적으로 구성할 수 있습니다. 정적 제한은 네 가지 보호 결과를 제공할 수 있지만 몇 가지 문제가 있습니다.
- 정적 제한은 모든 사용 패턴에 적합하지 않습니다. 일괄값이 없습니다. 제한이 너무 낮으면 대형 리포지터리에 부정적인 영향을 미칠 수 있습니다. 제한이 너무 높으면 보호하는 것 자체가 상실됩니다.
- 각 리포지터리의 작업 부하가 시간이 지남에 따라 변하는 경우에도 정적 제한의 합리적인 값을 유지하는 것은 고된 작업입니다.
- 서버가 비워져 있는 상태에서도 요청이 거부될 수 있습니다.
모든 이러한 단점을 극복하고 동시성 제한의 이점을 유지하려면 적응적 동시성 제한을 구성함으로써 가능합니다. 적응적 동시성 제한은 선택적이며 두 동시성 제한 유형을 바탕으로 구축됩니다. 추가 증가/곱셈 감소(AIMD) 알고리즘을 사용합니다. 각 적응 제한은 다음을 수행합니다.
- 일반적인 프로세스 기능 중에 특정 상위 한도까지 점진적으로 증가합니다.
- 호스트 머신에 리소스 문제가 발생하면 빠르게 감소합니다.
이 메커니즘은 기계에 여유 공간을 제공하며 현재 진행 중인 요청을 가속화합니다. Adaptive concurrency limits are optional and build on the two concurrency limiting types. It uses the Additive Increase/Multiplicative Decrease (AIMD) algorithm. Each adaptive limit:
- 격자는 일반적인 프로세스 운영 중도 일정 상위 수준까지 점진적으로 증가합니다.
- 호스트 머신의 상위 cgroup에 메모리 사용량이 90%를 초과하거나 고도로 삭제 가능한 페이지 캐시를 제외한 경우 또는 감시 시간의 50% 이상에서 CPU가 단계적으로 제한될 때 약소, 최대한 한도를 낮춥니다.
그렇지 않은 경우 제한은 일정 상위 한도치까지 하나씩 증가합니다. 이 시스템의 기술적 구현에 대한 자세한 내용은 이 설계안을 참조하십시오.
적응 제한은 각 RPC 또는 pack-objects 캐시에 대해 별도로 활성화됩니다. 그러나 제한은 동시에 조정됩니다.
RPC 동시성을 위한 적응성 활성화
사전 조건:
- 적응 제한은 컨트롤 그룹에 의존하기 때문에, 적응 제한을 사용하기 전에 컨트롤 그룹을 활성화해야 합니다.
다음은 RPC 동시성을 구성하는 예시입니다:
# /etc/gitlab/gitlab.rb에 추가
gitaly['configuration'] = {
# ...
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
는 Gitaly 시작 시 사용할 리포지터리 당 동시성 제한입니다. -
max_limit
는 구성된 RPC의 리포지터리 당 최소 동시성 제한입니다. Gitaly는 현재 제한을 증가시켜 이 수치에 도달할 때까지 증가합니다. -
min_limit
는 구성된 RPC의 리포지터리 당 최소 동시성 제한입니다. 호스트 머신에 리소스 문제가 발생하면, Gitaly는 이 값에 도달할 때까지 제한을 빠르게 줄입니다.
자세한 정보는 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
는 Gitaly 시작 시 사용할 IP 당 동시성 제한입니다. -
max_limit
는 pack-objects의 IP 당 최소 동시성 제한입니다. Gitaly는 현재 제한을 증가시켜 이 수치에 도달할 때까지 증가합니다. -
min_limit
는 pack-objects의 IP 당 최소 동시성 제한입니다. 호스트 머신에 리소스 문제가 발생하면, Gitaly는 이 값에 도달할 때까지 제한을 빠르게 줄입니다.
자세한 정보는 pack-objects 동시성을 참조하세요.