Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
accepted | - |
Cells: 라우팅 서비스
이 문서는 Cells에서 사용되는 라우팅 서비스의 설계 목표와 아키텍처를 설명합니다. 라우팅 서비스가 아키텍처에 어떻게 들어맞는지에 대한 더 나은 이해를 위해 인프라 아키텍처를 참조하십시오.
목표
라우팅 레이어는 모든 Cells가 별도의 도메인으로 이동하는 대신 단일 도메인(예: gitlab.com
) 하에 제공되는 일관된 사용자 경험을 제공하는 데 목적이 있습니다.
사용자는 https://gitlab.com
을 사용하여 Cell을 활성화한 GitLab에 액세스할 수 있을 것입니다. URL 액세스에 따라 특정 정보를 제공할 수 있는 올바른 Cell로 투명하게 프록시됩니다. 예를 들어:
-
https://gitlab.com/users/sign_in
로 가는 모든 요청은 모든 Cells로 무작위로 분산됩니다. -
https://gitlab.com/gitlab-org/gitlab/-/tree/master
로 가는 모든 요청은 항상 예를 들어 Cell 5로 직접 이동합니다. -
https://gitlab.com/my-username/my-project
로 가는 모든 요청은 항상 Cell 1로 이동합니다.
-
기술.
우리는 라우팅 서비스가 어떤 기술로 작성될지 결정합니다. 선택은 최상의 성능을 나타내는 언어와 라우팅 레이어의 예상되는 방법과 배치 위치에 따라 달립니다. 서비스를 멀티 클라우드로 만들어야 하는 경우 CDN 제공업체에 배포해야 할 수도 있습니다. 이후, 서비스는 CDN 제공업체와 호환되는 기술을 사용하여 작성해야 할 것입니다.
-
Cell 탐지.
라우팅 서비스는 모든 Cells의 상태를 탐지하고 모니터링할 수 있어야 합니다.
-
사용자는 단일 도메인을 통해 여러 Cells와 상호 작용할 수 있어야 합니다.
라우팅 서비스는 액세스하는 자원에 따라서 모든 요청을 Cells로 지능적으로 라우팅할 것입니다.
-
라우터 엔드포인트 분류.
상태가 없는 라우팅 서비스는 하나의 Cells에서 엔드포인트에 대한 정보를 검색하고 캐시할 것입니다. 우리는 들어오는 요청(지문)을 정확하게 설명할 수 있는 프로토콜을 구현해야 하며 이를 통해 한 Cells로 분류할 수 있고 그 결과를 캐시할 수 있어야 합니다. 또한 부정적인 캐시와 캐시 퇴출 메커니즘을 구현해야 할 것입니다.
-
GraphQL 및 다른 애매한 엔드포인트.
대부분의 엔드포인트는 조직을 위한 고유한 샤딩 키를 가지고 있습니다. 몇몇 엔드포인트는 사용 중에 애매하거나(샤딩 키가 페이로드 안에 깊숙이 저장되어 있는 경우) 샤딩 키가 애매합니다. 이러한 경우,
/api/graphql
과 같은 엔드포인트를 어떻게 처리할지 결정해야 합니다. -
소규모.
라우팅 서비스는 설정 및 규칙에 따라 동작하는 비즈니스 로직을 구현하지 않으며, 최대 프로젝트 소스 코드 크기는 초기 단계에서 테스트를 포함하여 1,000줄입니다. 이 한정 된 이유는 특별한 로직을 가지지 않도록 하고 몇 일 안에 다른 기술로 다시 작성할 수 있도록 하는 것입니다.
요구 사항
요구 사항 | 설명 | 우선 순위 |
---|---|---|
탐지 | 모든 Cells의 상태를 탐지하고 모니터링할 수 있어야 함 | 높음 |
보안 | 인가된 Cells만 라우팅 되어야 함 | 높음 |
단일 도메인 | 예: GitLab.com | 높음 |
캐싱 | 성능을 위해 라우팅 정보를 캐시할 수 있어야 함 | 높음 |
낮은 대기 시간 | 50ms 이상의 증가된 대기 시간 | 높음 |
경로 기반 | 경로를 기준으로 라우팅 결정을 내릴 수 있어야 함 | 높음 |
복잡성 | 라우팅 서비스는 설정에 따라 동작하고 소규모여야 함 | 높음 |
롤링 | 라우팅 서비스는 혼합 버전으로 실행 중인 Cells와 작동해야 함 | 높음 |
기능 플래그 | 기능을 켜거나 끌 수 있으며 %를 롤아웃할 수 있어야 함 | 높음 |
점진적 롤아웃 | 변경을 천천히 롤아웃할 수 있어야 함 | 중간 |
상태 없음 | 데이터베이스가 필요하지 않고 Cells가 모든 라우팅 정보를 제공해야 함 | 중간 |
시크릿 기반 | 시크릿에 기반하여 라우팅 결정을 내릴 수 있어야 함 | 중간 |
관측 가능성 | 기존의 관측 도구를 사용할 수 있어야 함 | 낮음 |
자체 관리형 | 자체 관리형에서 최종적으로 사용될 수 있어야 함 | 낮음 |
지역별 | 요청을 다른 지역으로 라우팅할 수 있어야 함 | 낮음 |
낮은 대기 시간
라우팅 서비스의 대상 대기 시간은 50ms 미만이어야 합니다.
긴급도: 높음
요청을 살펴보면 p50에서 큰 여건이 없습니다. 추가로 50ms가 있는 것으로 우리는 여전히 p95 수준에서 SLO에 포함됩니다.
응용 프로그램에는 3개의 주요 진입점이 있습니다; web
, api
, git
.
각 서비스는 apdex 표준을 사용하여 지연 기반의 서비스 수준 지표(SLI)를 기반으로 한 SLI를 할당받습니다.
이러한 SLI에 대한 해당 서비스 수준 목표(SLO)는 대량의 요청에 대해 낮은 대기 시간을 요구합니다.
이러한 서비스 앞에 라우팅 레이어를 추가하여 SLI에 영향을 미치지 않도록 하는 것이 중요합니다.
라우팅 레이어는 이러한 서비스를 위한 프록시이며, 우리는 전체 요청 흐름에 대한 포괄적인 SLI 모니터링 시스템이 없기 때문에 (에지 네트워크 및 로드 밸런서와 같은 구성 요소를 포함한) 우리는 web
, git
, 및 api
의 SLI를 대상으로 사용합니다.
우리가 사용하는 주요 SLI는 rails requests입니다.
요청 긴급도에 따라 여러 만족
대상(apdex)이 있습니다:
긴급도 | 시간 (ms) |
---|---|
:높음
| 250 ms |
:중간
| 500 ms |
:기본
| 1000 ms |
:낮음
| 5000 ms |
분석
우리가 headroom을 계산하는 방법은 다음과 같습니다.
\mathrm{Headroom}\ {ms} = \mathrm{Satisfied}\ {ms} - \mathrm{Duration}\ {ms}
web
:
목표 지속 시간 | 백분위수 | Headroom |
---|---|---|
5000 ms | p99 | 4000 ms |
5000 ms | p95 | 4500 ms |
5000 ms | p90 | 4600 ms |
5000 ms | p50 | 4900 ms |
1000 ms | p99 | 500 ms |
1000 ms | p95 | 740 ms |
1000 ms | p90 | 840 ms |
1000 ms | p50 | 900 ms |
500 ms | p99 | 0 ms |
500 ms | p95 | 60 ms |
500 ms | p90 | 100 ms |
500 ms | p50 | 400 ms |
250 ms | p99 | 140 ms |
250 ms | p95 | 170 ms |
250 ms | p90 | 180 ms |
250 ms | p50 | 200 ms |
Analysis was done in https://gitlab.com/gitlab-org/gitlab/-/issues/432934#note_1667993089
api
:
목표 지속 시간 | 백분위수 | Headroom |
---|---|---|
5000 ms | p99 | 3500 ms |
5000 ms | p95 | 4300 ms |
5000 ms | p90 | 4600 ms |
5000 ms | p50 | 4900 ms |
1000 ms | p99 | 440 ms |
1000 ms | p95 | 750 ms |
1000 ms | p90 | 830 ms |
1000 ms | p50 | 950 ms |
500 ms | p99 | 450 ms |
500 ms | p95 | 480 ms |
500 ms | p90 | 490 ms |
500 ms | p50 | 490 ms |
250 ms | p99 | 90 ms |
250 ms | p95 | 170 ms |
250 ms | p90 | 210 ms |
250 ms | p50 | 230 ms |
Analysis was done in https://gitlab.com/gitlab-org/gitlab/-/issues/432934#note_1669995479
git
:
목표 지속 시간 | 백분위수 | Headroom |
---|---|---|
5000 ms | p99 | 3760 ms |
5000 ms | p95 | 4280 ms |
5000 ms | p90 | 4430 ms |
5000 ms | p50 | 4900 ms |
1000 ms | p99 | 500 ms |
1000 ms | p95 | 750 ms |
1000 ms | p90 | 800 ms |
1000 ms | p50 | 900 ms |
500 ms | p99 | 280 ms |
500 ms | p95 | 370 ms |
500 ms | p90 | 400 ms |
500 ms | p50 | 430 ms |
250 ms | p99 | 200 ms |
250 ms | p95 | 230 ms |
250 ms | p90 | 240 ms |
250 ms | p50 | 240 ms |
Analysis was done in https://gitlab.com/gitlab-org/gitlab/-/issues/432934#note_1671385680
비목표
아직 정의되지 않음.
제안
Routing Service는 다음 설계 지침을 구현합니다.
- 간단함:
- 라우팅 서비스는 요청을 버퍼링하지 않습니다.
- 라우팅 서비스는 요청 헤더에 따라 단일 Cell에만 프록시를 제공할 수 있습니다.
- 무상태성:
- 라우팅 서비스에는 영구 저장소가 없습니다.
- 라우팅 서비스는 다중 레벨 캐시를 사용합니다: 인메모리, 외부 공유 캐시.
- 제로 트러스트:
- 라우팅 서비스는 프록시화되는 각 요청에 서명합니다.
- 신뢰는 JWT 토큰 또는 상호 인증 체계를 사용하여 설정됩니다.
- 제로 트러스트 모델을 준수한다면 셀은 공개 인터넷을 통해 사용할 수 있습니다.
- 구성 기반:
- 라우팅 서비스는 정적 Cell 목록으로 구성됩니다.
- 라우팅 서비스 구성은 서비스 배포의 일부로 적용됩니다.
- 규칙 기반:
- 라우팅 서비스는 모든 Cell에서 수집된 라우팅 규칙과 함께 배포됩니다.
- 라우팅 서비스는 GitLab의 다른 버전에서 생성된 규칙 목록을 지원합니다.
- 규칙에는 헤더, 헤더 내용 또는 경로 내용과 일치시킬 수 있는 임의의 기준을 매칭하는 기능이 있습니다.
- 중립적:
- 라우팅 서비스는 조직과 같은 고수준 개념을 인식하지 않습니다.
- 분류는 규칙에서 제공된 명세에 따라 수행되어 샤딩 키를 찾습니다.
- 샤딩 키 결과가 캐시됩니다.
- 캐시된 단일 샤딩 키는 많은 유사한 요청을 처리하는 데 사용됩니다.
다음 다이어그램은 사용자 요청이 DNS를 통해 클라우드플레어 워커로 배포된 라우팅 서비스 및 라우터를 통해 요청을 전송할 셀을 선택하는 방법을 보여줍니다.
라우팅 규칙
각 Cell은 라우팅 서비스에서 사용될 사전 컴파일된 라우팅 규칙 목록을 발행합니다.
- 라우팅 규칙에는 요청 디코딩 방법, 샤딩 키 확인 및 라우팅 결정 방법 등이 기술됩니다.
- 라우팅 규칙은 라우팅 서비스를 배포하는 동안 컴파일됩니다.
- 배포 프로세스는 라우팅 서비스 구성에 포함된 각 Cell에서 라우팅 규칙의 최신 버전을 가져옵니다.
- 컴파일 프로세스는 모든 Cell의 라우팅 규칙을 병합합니다.
- 충돌하는 규칙으로 인해 라우팅 서비스의 컴파일/시작이 방지됩니다.
- 각 라우팅 규칙 항목은 병합을 용이하게 하기 위한 고유 식별자가 있습니다.
- 변경되는 규칙 목록은 새로 추가된 대부분의 엔드포인트가 이전 라우트 규칙을 이미 준수하도록 기대하기 때문에 자주 발생하지 않아야 합니다.
- 구성에서 배포 시 라우팅 규칙을 가져와야 하는 Cells가 기술됩니다.
- 발행된 라우팅 규칙은 비밀을 기반으로 라우팅 결정을 내릴 수 있습니다. 예를 들어 세션 쿠키나 인증 토큰에
c100-
접두어가 있다면 모든 요청은 특정 Cell로 전달해야 합니다. - Cell은
/api/v4/internal/cells/route_rules.json
에 라우팅 규칙을 발행합니다. - Cell에 의해 발행된 규칙은 해당 Cell이 처리할 수 있는 엔드포인트만 포함합니다.
- Cell은 sharding key에 기반한 동적 분류를 수행해야 하는 경우
/api/v4/internal/cells/classify
을 호출하도록 라우팅 규칙을 구성할 수 있습니다. - 라우팅 규칙은 정적으로 컴파일되어 소스 코드로 변환되어서는 규칙의 비용이 비싼 파싱 및 평가를 회피할 수 있는 것이 이상적입니다.
라우팅 규칙 JSON 구조는 모든 매처를 기술합니다.
{
"rules": [
{
"id": "<고유 식별자>",
"cookies": {
"<cookie_name>": {
"prefix": "<일치하는 접두어>",
"match_regex": "<정규식 일치>"
},
"<cookie_name2>": {
"prefix": "<일치하는 접두어>",
"match_regex": "<정규식 일치>"
}
},
"headers": {
"<header_name>": {
"prefix": "<일치하는 접두어>",
"match_regex": "<정규식 일치>"
},
"<header_name2>": {
"prefix": "<일치하는 접두어>",
"match_regex": "<정규식 일치>"
},
},
"path": {
"prefix": "<일치하는 접두어>",
"match_regex": "<정규식 일치>"
},
"method": ["<수락된 방법 목록>"],
// 모든 규칙이 일치하는 경우에는 어떤 것이 승리하는지 정의
"priority": 1000,
// 요청을 수락하고 해당하는 Cell로 프록시
"action": "proxy",
// 정규식 일치 그룹에 기반하여 요청 분류
"action": "classify",
"classify": {
"keys": ["일치하는 정규식 캡처 그룹 목록"]
}
}
]
}
세션 쿠키와 비밀을 기반으로 라우팅 결정을 내리는 Cell 100에 의해 발행된 라우팅 규칙 예시입니다. 라우팅 규칙이 비밀 기반이기 때문에 높은 우선순위를 갖고 다른 모든 매처보다 우선하여야 합니다.
{
"rules": [
{
"id": "t4mkd5ndsk58si6uwwz7rdavil9m2hpq",
"cookies": {
"_gitlab_session": {
"prefix": "c100-" // `c100-`로 접두어가 있는 `_gitlab_session`를 허용
}
},
"action": "proxy",
"priority": 1000
},
{
"id": "jcshae4d4dtykt8byd6zw1ecccl5dkts",
"headers": {
"GITLAB_TOKEN": {
"prefix": "C100_" // `C100_`로 접두어가 있는 `GITLAB_TOKEN`를 허용
}
},
"action": "proxy",
"priority": 1000
}
]
}
모든 Cell에 의해 발행된 라우팅 규칙으로 경로에 의해 라우팅 결정을 내리는 예시입니다.
{
"rules": [
{
"id": "c9scvaiwj51a75kzoh917uwtnw8z4ebl",
"path": {
"prefix": "/api/v4/projects/", // 룰 일치를 빠르게하기 위해 접두어 사용
"match_regex": "^/api/v4/projects/(?<project_id_or_path_encoded>[^/]+)(/.*)?$"
},
"action": "classify",
"classify": {
"keys": ["project_id_or_path_encoded"]
}
}
]
}
분류
각 셀은 분류 엔드포인트를 구현합니다.
- 분류 엔드포인트는
/api/v4/internal/cells/classify
에 있습니다. (또는 gRPC 엔드포인트). - 분류 엔드포인트는 샤딩 키 목록을 허용합니다. 샤딩 키는 셀에 의해 제공된 라우팅 규칙에 따라 요청에서 디코딩됩니다.
- 엔드포인트는 유사한 요청에 대해 매번 분류하는 대신 캐시를 오염시키기 위해 다른 등가 샤딩 키를 반환합니다. 이렇게 함으로써 모든 유사한 요청이 매번 분류하는 시간을 절약할 수 있습니다.
- 라우팅 서비스는 셀의 상태를 추적하고 셀의 가중치, 상태 또는 정의된 기준에 따라 분류 요청을 발행합니다. 가중치는 어떤 셀이 샤딩 키의 분류를 선호하는지 나타낼 것입니다.
- 라우팅 서비스는
classify
호출을 합리적인 시간 동안 다시 시도합니다. 셀이classify
를 계속 실패할 경우 셀이 건강하지 않다는 것을 나타냅니다. -
classify
결과는 반환된action
과 관계없이 캐시됩니다. 거부된 분류는 캐시되어 찾을 수 없는 샤딩 키에 대한 과도한 요청을 방지합니다. - 캐시된 응답은
만료
및새로고침
으로 정의된 시간 동안 유지됩니다.-
만료
는 아이템이 사용되지 않는 한 캐시에서 제거되는 시간을 정의합니다. -
새로고침
은 사용된 경우 아이템이 다시 분류되어야 하는 시간을 정의합니다. - 새로고침은 요청이 분류된 경우 지연 없이 서비스될 수 있도록 비동기적으로 수행됩니다. 캐시가 항상 핫하고 최신 상태임을 보장하기 위해 새로고침이 수행됩니다.
-
위 예에서:
- 라우터는
/api/v4/projects/1000/issues
에 대한 요청을 수신합니다. - 이 요청에 대해 위의
rule
을 선택하여project_id_or_path_encoded
의classify
를 요청합니다. -
project_id_or_path_encoded
를 디코딩하면1000
이 됩니다. - 캐시를 확인하여
project_id_or_path_encoded=1000
이 어떤 셀과 연결되어 있는지 확인합니다. - 캐시에서 셀을 찾지 못한 경우
/api/v4/internal/cells/classify
에 요청을 전송합니다. - Rails는 주어진 프로젝트를 보유한 셀 및 캐시에 넣어야 하는 리소스에 대한 다른 등가 샤딩 키를 응답합니다.
- 라우팅 서비스는 구성에서 지정된 기간 또는 응답에 대해 캐시합니다.
# POST /api/v4/internal/cells/classify
## 요청:
{
"metadata": {
"rule_id": "c9scvaiwj51a75kzoh917uwtnw8z4ebl",
"headers": {
"all_request_headers": "value"
},
"method": "GET",
"path": "/api/v4/projects/100/issues"
},
"keys": {
"project_id_or_path_encoded": 100
}
}
## 응답:
{
"action": "proxy",
"proxy": {
"name": "cell_1",
"url": "https://cell1.gitlab.com"
},
"ttl": "10 minutes",
"matched_keys": [ // 캐시에 넣어야 할 모든 등가 키 목록
{ "project_id_or_path_encoded": 100 },
{ "project_id_or_path_encoded": "gitlab-org%2Fgitlab" },
{ "project_full_path": "gitlab-org/gitlab" },
{ "namespace_full_path": "gitlab-org" },
{ "namespace_id": 10 },
{ "organization_full_path": "gitlab-inc" },
{ "organization_id": 50 },
]
}
아래 코드는 샤딩 키를 찾지 못했을 때 부정적인 응답을 나타냅니다:
# POST /api/v4/internal/cells/classify
## 요청:
{
"metadata": {
"rule_id": "c9scvaiwj51a75kzoh917uwtnw8z4ebl",
"headers": {
"all_request_headers": "value"
},
"method": "GET",
"path": "/api/v4/projects/100/issues"
},
"keys": {
"project_id_or_path_encoded": 100
}
}
## 응답:
{
"action": "reject",
"reject": {
"http_status": 404
},
"cache": {
"refresh": "10 minutes",
"expiry": "10 minutes"
},
"matched_keys": [ // 캐시에 넣어야 할 모든 등가 키 목록
{ "project_id_or_path_encoded": 100 },
]
}
구성
라우팅 서비스는 다음과 유사한 구성을 사용할 것입니다:
[[cells]]
name=cell_1
url=https://cell1.gitlab.com
key=ABC123
classify_weight=100
[[cells]]
name=cell_2
url=https://cell2.gitlab.com
key=CDE123
classify_weight=1
[cache.memory.classify]
refresh_time=10 minutes
expiry_time=1 hour
[cache.external.classify]
refresh_time=30 minutes
expiry_time=6 hour
이는 다음과 같은 정적 셀 목록을 제공하는 것이 수용 가능하다고 가정합니다:
- 정적: 동적으로 프로비저닝 및 비 프로비저닝되는 셀은 거의 없을 것입니다.
- 충분히 좋음: 우리는 최대 100개의 셀까지도 관리할 수 있습니다.
- 간단: 서비스에서 강력한 서비스 검색을 구현할 필요가 없으며, 이 목록이 항상 철저하다는 것을 보장할 수 있습니다.
이 구성은 모든 셀, URL, 제로 트러스트 키 및 가중치를 설명하며,
요청이 얼마동안 캐시되어야 하는지를 정의합니다. classify_weight
는 셀이 다른 셀보다 얼마나 자주 분류 요청을 받아야 하는지 정의합니다.
요청 흐름
- 두 개의 셀이 있습니다.
-
gitlab-org
는 최상위 네임스페이스이며GitLab.com Public
조직의Cell US0
에 있습니다. -
my-company
는 최상위 네임스페이스이며my-organization
조직의Cell EU0
에 있습니다.
정적 라우팅 수행하도록 라우터 구성
- Cell US0는 모든 공개 프로젝트를 지원합니다.
- 셀은 모든 비밀 및 세션 쿠키를
eu0_
와 같은 접두사로 생성하도록 구성됩니다.- 개인 액세스 토큰은 조직에 대해 스코프가 지정되며, 그 조직이 단일 셀의 일부인 경우에만 생성된 PAT는 셀 식별자가 접두어로 붙습니다.
- 세션 쿠키는 사용 중인 조직을 인코딩하며, 그 조직이 단일 셀의 일부인 경우에만 생성된 세션 쿠키는 셀 식별자가 접두어로 붙습니다.
- Cell EU0는 비공개 조직, 그룹 및 프로젝트만 허용합니다.
- Cell US0는 명시적으로 접두어가 붙지 않는 이상 모든 요청의 대상 셀입니다.
Cell US0:
{
"rules": [
{
"id": "tjh147se67wadjzum7onwqiad2b75uft",
"path": {
"prefix": "/"
},
"action": "proxy",
"priority": 1
}
]
}
Cell EU0:
{
"rules": [
{
"id": "t4mkd5ndsk58si6uwwz7rdavil9m2hpq",
"cookies": {
"_gitlab_session": {
"prefix": "eu0_"
}
},
"path": {
"prefix": "/"
},
"action": "proxy",
"priority": 1000
},
{
"id": "jcshae4d4dtykt8byd6zw1ecccl5dkts",
"headers": {
"GITLAB_TOKEN": {
"prefix": "eu0_"
}
},
"path": {
"prefix": "/"
},
"action": "proxy",
"priority": 1000
}
]
}
Cell EU0
에 로그인한 채 /my-company/my-project
로 이동
- 사용자가 조직을
my-company
로 전환했기 때문에 해당 세션 쿠키는eu0_
로 접두어가 붙습니다. - 사용자가
/my-company/my-project
요청을 보내면 세션 쿠키가eu0_
로 접두어가 붙었기 때문에 이는 Cell EU0로 이동합니다. -
Cell EU0
은 올바른 응답을 반환합니다.
로그인하지 않은 채 /my-company/my-project
로 이동
- 사용자가
/my-company/my-project
로 이동하면 세션 쿠키가 없으므로 요청이Cell US0
로 전달됩니다. - 사용자가 로그인합니다.
- GitLab은 사용자의 기본 조직이
my-company
임을 인식하고, 사용자가my-company
와 상호 작용해야 함을 나타내기 위해eu0_
로 접두어가 붙은 세션 쿠키를 할당합니다. - 사용자가 다시
/my-company/my-project
로 요청을 보내면 이제 세션 쿠키가Cell EU0
로 프록시되는데, 이 때 올바른 응답이 반환됩니다.
마지막 단계 이후 /gitlab-org/gitlab
로 이동
사용자는 /my-company/my-project
를 방문하며, 세션 쿠키가 없기 때문에 요청이 Cell US0
로 전달됩니다.
분류에 따라 동적 라우팅 수행하도록 구성된 라우터
셀은 요청을 분류할 수 있는 라우트 규칙을 게시합니다.
셀 US0 및 EU0:
{
"rules": [
{
"id": "tjh147se67wadjzum7onwqiad2b75uft",
"path": {
"prefix": "/",
"regex": "^/(?top_level_group)[^/]+(/.*)?$",
},
"action": "classify",
"classify": {
"keys": ["top_level_group"]
}
},
{
"id": "jcshae4d4dtykt8byd6zw1ecccl5dkts",
"path": {
"prefix": "/"
},
"action": "proxy"
}
]
}
Cell EU0에 로그인한 상태로 /my-company/my-project
로 이동
-
/my-company/my-project/
를 방문합니다. - 라우터가 샤딩 키
top_level_group=my-company
를 디코딩합니다. - 라우터는 해당 샤딩 키가 캐시되어 있는지 확인합니다.
- 이 캐시에 없기 때문에 분류 요청이 랜덤 셀로
/classify
로 전송됩니다. - 분류의 응답이 캐시됩니다.
- 그런 후 해당 요청은 분류로부터 반환된 셀로 프록시됩니다.
로그인하지 않은 상태로 /my-company/my-project
로 이동
-
/my-company/my-project/
를 방문합니다. - 라우터가 샤딩 키
top_level_group=my-company
를 디코딩합니다. - 라우터는 해당 샤딩 키가 캐시되어 있는지 확인합니다.
- 이 캐시에 없기 때문에 분류 요청이 랜덤 셀로
/classify
로 전송됩니다. - 분류의 응답이 캐시됩니다.
- 그런 후 해당 요청은 분류로부터 반환된 셀로 프록시됩니다.
- 프로젝트가 비공개이므로 사용자는 로그인하도록 리디렉션됩니다.
- 모든 셀에서 처리되어야 하는 로그인 항목이 정의되어 있으므로, 랜덤 셀로 프록시됩니다.
- 사용자는 로그인한 후 다시
/my-company/my-project/
를 방문합니다. -
top_level_group=my-company
는 올바른 셀로 프록시됩니다.
마지막 단계 이후 /gitlab-org/gitlab
로 이동합니다
-
/gitlab-org
이(가) 캐시에서 찾을 수 없기 때문에, 분류된 후에 올바른 셀로 방향이 지정될 것입니다.
성능 및 신뢰성 고려사항
- 각 셀이 모든 샤딩 키를 분류할 수 있는 것으로 예상됩니다.
- 필요한 모든 데이터를 보유하고 있을 경우, 클러스터 전체 데이터 제공자가 분류를 수행할 수도 있습니다.
- 게시된 라우팅 규칙을 통해 정적 기준을 정의할 수 있으며, 라우팅 결정을 비밀번호만으로 만들 수 있습니다. 이에 따라, 라우팅 서비스는 요청 처리에 대한 지연시간을 추가하지 않으면서 더 높은 신뢰성을 제공합니다.
- 새로운 샤딩 키를 학습하는 경우에는 벌칙이 있을 것으로 예상됩니다. 그러나 다층 캐시가 샤딩 키의 낮은 기수로 인해 매우 높은 캐시 히트 비율을 제공할 것으로 예상되며, 샤딩 키는 사실상 자원(조직, 그룹 또는 프로젝트)으로 매핑되며 이 중 한정된 양이 있습니다.
대안
요청 버퍼링
상태 없는 라우터(Requests Buffering을 사용한)은 Cell이 X-Gitlab-Cell-Redirect
로 답변하여 요청을 다른 Cell로 리디렉션하는 방법을 설명합니다:
- 이 방법은 매우 메모리 집약적인 전체 요청(헤더 + 본문)을 버퍼링해야 하는 필요에 기반합니다.
- 이 제안은 서로 다른 버전의 셀이 실행될 수 있는 혼합 배포를 쉽게 처리할 수 있는 방법을 제공하지 않습니다.
- 이 제안은 디코딩된 샤딩 키가 아닌 요청을 기반으로 하기 때문에, 더 많은 정보를 캐싱해야 할 가능성이 높습니다.
요청 학습
상태 없는 라우터(Routes Learning을 사용한)은 이 문서와 유사한 접근 방식을 설명합니다. 단, 루트 규칙 및 분류가 사전 체크로 /api/v4/internal/cells/learn
형식으로 일괄적으로 수행됩니다:
- 이는 전체 루트 학습을 동적으로 만들어 셀의 가용성에 의존합니다.
- 이 제안은 서로 다른 버전의 셀이 실행될 수 있는 혼합 배포를 쉽게 처리할 수 있는 방법을 제공하지 않습니다.
- 이 제안은 디코딩된 샤딩 키가 아닌 요청을 기반으로 하기 때문에, 더 많은 정보를 캐싱해야 할 가능성이 높습니다.
FAQ
- 라우팅 서비스는 규칙 세트를 어떻게, 언제 컴파일하게 되나요?
정의되지 않았습니다.