This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
rejected -

이 제안서는 라우팅 서비스 제안서에 의해 대체되었습니다.

이 문서는 작업 중이며 Cells 설계의 초기 단계를 나타냅니다. 중요한 측면들이 문서화되지 않았지만, 앞으로 추가할 예정입니다. 이는 Cells를 위한 하나의 가능한 아키텍처이며, 구현할 접근 방법을 결정하기 전에 이를 대안과 대조하고자 합니다. 이 문서는 구현하지 않기로 결정한 경우에도 유지될 것이며, 이 접근 방식을 선택하지 않은 이유를 문서화할 수 있도록 합니다.

제안: 라우팅 학습을 사용하는 상태 없는 라우터

gitlab_users, gitlab_routesgitlab_admin 관련 테이블을 분해하여 모든 Cells 간에 공유되고 사용자의 인증 및 요청 라우팅을 모든 셀에 허용할 수 있도록합니다. 셀은 소유하지 않은 리소스에 대한 요청을 받을 수 있지만, 올바른 셀로 다시 리디렉션할 수 있습니다.

라우터는 상태를 갖지 않으며 routes 데이터베이스에서 읽지 않으므로 모든 데이터베이스 상호작용은 여전히 Rails 모놀리스에서 발생합니다. 이 아키텍처는 지역 간 트래픽을 허용하여 지역 간에 데이터베이스를 복제함으로써 지원합니다.

사용자는 셀의 개념에 직접 노출되지 않고 선택한 조직에 따라 다른 데이터를 볼 수 있습니다. 조직(조직)은 응용 프로그램에서 격리를 강화하고 요청이 어떤 셀로 라우팅될지 결정하도록 도와 주는 새 엔터티로 소개될 것입니다. 왜냐하면 조직은 단일 셀에만 존재할 수 있기 때문입니다.

차이점

이 제안서와 요청 버퍼링을 사용하는 제안서와의 주요 차이점은 이 제안서가 사전 항공 API 요청 (/api/v4/internal/cells/learn)을 사용하여 요청 본문을 올바른 셀로 리디렉션하는 데 사용한다는 것입니다. 이는 각 요청이 한 번만 처리되도록 보내지만 URI가 어떤 셀로 리디렉션되어야 하는지를 디코딩하는 데 사용됨을 의미합니다.

다이어그램 요약

사용자 요청이 DNS를 통해 가장 가까운 라우터로 라우팅되고 라우터는 요청을 보낼 셀을 선택하는 방식을 보여줍니다.

graph TD; user((사용자)); dns[DNS]; router_us(라우터); router_eu(라우터); cell_us0{셀 US0}; cell_us1{셀 US1}; cell_eu0{셀 EU0}; cell_eu1{셀 EU1}; user-->dns; dns-->router_us; dns-->router_eu; subgraph 유럽 router_eu-->cell_eu0; router_eu-->cell_eu1; end subgraph 미국 router_us-->cell_us0; router_us-->cell_us1; end

더 자세히

라우터가 실제로 모든 셀에 요청을 보낼 수 있음을 보여줍니다. 사용자는 지리적으로 가장 가까운 라우터를 얻을 것입니다.

graph TD; user((사용자)); dns[DNS]; router_us(라우터); router_eu(라우터); cell_us0{셀 US0}; cell_us1{셀 US1}; cell_eu0{셀 EU0}; cell_eu1{셀 EU1}; user-->dns; dns-->router_us; dns-->router_eu; subgraph 유럽 router_eu-->cell_eu0; router_eu-->cell_eu1; end subgraph 미국 router_us-->cell_us0; router_us-->cell_us1; end router_eu-.->cell_us0; router_eu-.->cell_us1; router_us-.->cell_eu0; router_us-.->cell_eu1;

더 자세한 내용

데이터베이스를 보여줍니다. gitlab_usersgitlab_routes는 미국 지역에만 있지만 다른 지역으로 복제됩니다. 복제는 다이어그램을 읽기가 너무 어렵게하기 때문에 화살표가 없습니다.

graph TD; user((사용자)); dns[DNS]; router_us(라우터); router_eu(라우터); cell_us0{셀 US0}; cell_us1{셀 US1}; cell_eu0{셀 EU0}; cell_eu1{셀 EU1}; db_gitlab_users[(gitlab_users 기본)]; db_gitlab_routes[(gitlab_routes 기본)]; db_gitlab_users_replica[(gitlab_users 복제)]; db_gitlab_routes_replica[(gitlab_routes 복제)]; db_cell_us0[(gitlab_main/gitlab_ci 셀 US0)]; db_cell_us1[(gitlab_main/gitlab_ci 셀 US1)]; db_cell_eu0[(gitlab_main/gitlab_ci 셀 EU0)]; db_cell_eu1[(gitlab_main/gitlab_ci 셀 EU1)]; user-->dns; dns-->router_us; dns-->router_eu; subgraph 유럽 router_eu-->cell_eu0; router_eu-->cell_eu1; cell_eu0-->db_cell_eu0; cell_eu0-->db_gitlab_users_replica; cell_eu0-->db_gitlab_routes_replica; cell_eu1-->db_gitlab_users_replica; cell_eu1-->db_gitlab_routes_replica; cell_eu1-->db_cell_eu1; end subgraph 미국 router_us-->cell_us0; router_us-->cell_us1; cell_us0-->db_cell_us0; cell_us0-->db_gitlab_users; cell_us0-->db_gitlab_routes; cell_us1-->db_gitlab_users; cell_us1-->db_gitlab_routes; cell_us1-->db_cell_us1; end router_eu-.->cell_us0; router_eu-.->cell_us1; router_us-.->cell_eu0; router_us-.->cell_eu1;

변경 요약

  1. 사용자 데이터 (프로필 설정, 인증 자격 증명, 개인 액세스 토큰을 포함한)와 관련된 테이블은 gitlab_users 스키마로 분해됩니다.
  2. routes 테이블은 gitlab_routes 스키마로 분해됩니다.
  3. application_settings (아마도 다른 몇 개의 인스턴스 수준 테이블)은 gitlab_admin 스키마로 분해됩니다.
  4. routes 테이블에 cell_id 새 열이 추가됩니다.
  5. 새 라우터 서비스는 어느 셀로 요청을 라우팅할지 선택합니다.
  6. 라우터가 새 요청을 받으면 /api/v4/internal/cells/learn?method=GET&path_info=/group-org/project로 보내어 어떤 셀이 처리할 수 있는지 배우도록 합니다.
  7. GitLab에 새로운 개념이 소개될 것입니다. 이는 조직이라고 하며 응용 프로그램에서 격리를 강화하고 어떤 요청이 어느 셀로 라우팅될지를 결정하도록 도와주는 것입니다. 왜냐하면 조직은 단일 셀에만 존재할 수 있기 때문입니다.
  8. 우리는 기존의 모든 엔드포인트가 URI로 라우팅되거나 특정 셀에 대해 고정되도록 요구합니다. 이는 /dashboard와 같은 모호한 엔드포인트를 /organizations/my-organization/-/dashboard와 같이 범위를 지정하도록 변경해야 한다는 것을 의미합니다.
  9. /admin과 같은 엔드포인트는 항상 특정 셀로 라우팅되며, 예를 들어 cell_0입니다.
  10. 각 셀은 /api/v4/internal/cells/learn에 응답하고 각 엔드포인트를 분류할 수 있습니다.
  11. gitlab_usersgitlab_routes에 대한 쓰기는 미국 지역의 기본 PostgreSQL 서버로 전송되지만 동일 지역의 복제본에서 읽을 수 있습니다. 이로 인해 이러한 쓰기에는 지연이 추가될 것이나, 우리는 이러한 쓰기가 GitLab의 나머지 부분에 비해 드물다고 예상합니다.

사전 항공 요청 학습

요청을 처리하는 동안 URI가 디코딩되고 캐시되지 않은 엔드포인트마다 사전 항공 요청이 전송될 것입니다.

GitLab Rails에서 엔드포인트를 요청할 때 라우터는 /api/v4/internal/cells/learn?method=GET&path_info=/gitlab-org/gitlab-test/-/issues와 같은 접두사 일치 및 /api/v4/internal/cells/learn?method=GET&path_info=/-/profile와 같은 정확 일치를 필요로 할 수 있습니다. 이는 각각 /gitlab-org/gitlab-test, /-/profile, /api/v4/internal/cells/learn?method=GET&path_info=/group-org/project와 같은 경로에 대한 정보를 리턴하고 존재하는 엔드포인트와 라우트 가능한 엔터티 (프로젝트와 같은)를 찾을 것입니다. 라우터는 이것을 일시적인 캐시 정보로 처리할 것입니다.

  1. 접두사 일치: /api/v4/internal/cells/learn?method=GET&path_info=/gitlab-org/gitlab-test/-/issues

    {
       "path": "/gitlab-org/gitlab-test",
       "cell": "cell_0",
       "source": "routable"
    }
    
  2. 일부 엔드포인트는 정확 일치가 필요할 수 있습니다: /api/v4/internal/cells/learn?method=GET&path_info=/-/profile

    {
       "path": "/-/profile",
       "cell": "cell_0",
       "source": "fixed",
       "exact": true
    }
    

첫 번째 이터레이션에서 기본 조직의 상세 설명

모든 사용자는 사용자 설정에서 제어할 수 있는 users.default_organization이라는 새 열을 받게 될 것입니다. 우리는 GitLab.com Public 조직이라는 개념을 도입할 것입니다. 기존 사용자는 기본적으로이 조직으로 설정될 것입니다. 이 조직은 사용자가 Cell US0(즉, 원래의 GitLab.com 인스턴스)의 모든 네임스페이스에서 데이터를 볼 수 있도록합니다. 이 동작은 기존 사용자에 대해 보이지 않을 수 있으며, 기존 사용자에게는 별도로 알리지 않고 ‘/dashboard’와 같은 전역 페이지를 보고있는지에 대해 알려주지 않을 수 있습니다.

GitLab.com Public 이외의 기본 조직을 가진 모든 새로운 사용자는 구별되는 사용자 경험을 받게됩니다. 그들은 로드되는 모든 페이지가 항상 단일 조직에 대해 범위가 지정되므로 /dashboard와 같은 전역 페이지를 로드 할 수 없으며, 대신에 /organizations/<DEFAULT_ORGANIZATION>/-/dashboard로 리디렉션 됩니다. 기존 API 및 이와 유사한 사용자에게도 마찬가지일 수 있으며, 이러한 사용자들은 조직에 범위가 지정된 API 만 사용할 수 있을 것입니다.

관리자 영역 설정의 상세 설명

우리는 관리자 영역 설정을 유지하고 동기화하는 것이 괴로울 것으로 믿으며, 이를 피하기 위해 모든 관리자 영역 설정을 gitlab_admin 스키마로 분해하고 공유할 것입니다. 이것은 다른 공유 스키마와 유사하게 안전할 것으로 예상되며, 그 이유는 이러한 설정이 매우 적은 쓰기 트래픽을 받기 때문입니다.

다른 셀이 서로 다른 설정이 필요한 경우(예: Elasticsearch URL) 관련된 application_settings 행에 동적으로 설정할 수 있도록 템플릿 형식을 사용하기로 결정할 것입니다. 대안으로 어려울 경우 per_cell_application_settings이라는 새로운 테이블을 도입할 것이며, 이를 통해 셀 당 1개의 행을 추가해 각 셀 당 다른 설정을 할 수 있도록 할 것입니다. 이것은 여전히 gitlab_admin 스키마의 일부이며, 중앙에서 관리하고 모든 셀에 대해 설정을 동기화하는 것을 단순화합니다.

장점

  1. 라우터는 상태를 유지하지 않으며 많은 지역에 거주할 수 있습니다. 사용자에게 가장 가까운 지역으로 해결하기 위해 Anycast DNS를 사용합니다.
  2. 셀은 잘못된 셀에있는 네임스페이스에 대한 요청을 받을 수 있고 사용자는 여전히 올바른 응답을받을 것이며, 라우터의 캐싱이 다음 요청이 올바른 셀로 전송되도록 보증합니다.
  3. 코드의 대부분은 여전히 gitlab 레일 코드베이스에 있습니다. 라우터는 사실 GitLab URL이 어떻게 구성되는지를 이해할 필요가 없습니다.
  4. gitlab_users, gitlab_routes, gitlab_admin을 읽고 쓰는 책임이 여전히 레일에 있기 때문에, 도메인 모델을 격리시켜 새로운 인터페이스를 구축해야하는 서비스를 추출하는 것에 비해 레일 애플리케이션에 필요한 변경은 최소화될 것입니다.
  5. 별도의 라우팅 서비스와 비교했을 때, 이것은 레일 애플리케이션이 URL을 올바른 셀로 매핑하는 방법에 대한보다 복잡한 규칙을 인코딩하고 기존 API 엔드 포인트에 작동할 수도 있을 것입니다.
  6. 모든 새로운 인프라 (단순히 라우터만)은 선택 사항이며, 단일 셀 Self-Managed형 설치는 심지어 라우터를 실행할 필요가 없으며 다른 새로운 서비스가 없습니다.

단점

  1. gitlab_users, gitlab_routesgitlab_admin 데이터베이스는 다양한 지역에 복제되어야하며 쓰기는 지역을 횡단해야합니다. 해당 테이블의 쓰기 TPS에 대한 분석을 수행하여이가 실행 가능한지 여부를 결정해야합니다.
  2. 여러 다른 셀에서 데이터베이스에 액세스를 공유하는 것은 모든 셀이 Postgres 스키마 수준에서 결합되어 있음을 의미하며, 이는 데이터베이스 스키마에 대한 변경이 모든 셀의 배포와 함께 신중하게 수행되어야 함을 의미합니다. 이는 우리에게 셀이 우리가 제어하는 API를 가진 공유 서비스로 볼 수있는 아키텍처에 비해 셀이 밀접하게 유사한 버전으로 유지되도록 제한하는 것입니다.
  3. 대부분의 데이터가 올바른 지역에 저장되어 있더라도 다른 지역에서 프록시로 전송 될 수도 있으며 이는 일부 유형의 규정 준수에 문제가 될 수 있습니다.
  4. gitlab_usersgitlab_routes 데이터베이스의 데이터가 모든 지역에 중복으로 저장되어야 할 수 있으며, 이는 일부 유형의 규정 준수에 문제가 될 수 있습니다.
  5. 라우터 캐시는 URL의 다양한 유형 (즉, 롱테일)을 얻으면 매우 커야할 수 있습니다. 이러한 경우 사용자의 쿠키에 2 차 캐싱 수준을 구현하여 자주 액세스하는 페이지가 항상 처음에 올바른 셀로 이동하도록 할 필요가 있을 수 있습니다.
  6. 여러 셀에서 gitlab_usersgitlab_routes에 대한 공유 데이터베이스 액세스는 여러 셀에서 호출되는 서비스를 추출하는 것에 비해 일반적이지 않은 아키텍처 결정입니다.
  7. 아마도 GraphQL URL의 캐시 가능한 요소를 찾지 못할 것으로 생각됩니다. 또한, 기존의 GraphQL 엔드 포인트는 셀이 데이터가있는 셀을 알 수없는 ids에 크게 의존하기 때문에 셀은 어떤 셀이 데이터를 가지고 있는지에 대해 파악할 수 없을 것입니다. 따라서 우리는 아마도 경로에 조직 컨텍스트를 포함하도록 GraphQL 호출을 업데이트해야 할 것입니다. 예시로 /api/organizations/<organization>/graphql와 같습니다.
  8. 이 아키텍처는 구현 된 엔드 포인트가 주어진 셀에서 즉시 액세스 할 수있는 데이터에만 액세스 할 수 있으며 여러 셀에서 정보를 집계할 가능성은 적을 것으로 예상됩니다.
  9. 알려지지 않은 경로는 최신 배포로 전송되며 이는 Cell US0으로 가정되는 최신 셀만이 새로 추가 된 엔드 포인트 만 해석 할 것으로 가정합니다. 이는 가벼우며 성능에 영향을주지 않아야할 /internal/cells/learn에 대한 문제가 아닐 것입니다.

데이터베이스 구성 예시

gitlab_users, gitlab_routesgitlab_admin 데이터베이스를 공유하는 동안 gitlab_maingitlab_ci 전용 데이터베이스를 사용하는 방식은 이미 config/database.yml을 사용하는 방식으로 처리 되어야 합니다. 또한, gitlab_usersgitlab_routes를 위해 단일 US 프라이머리와 전용 EU 복제를 처리해야합니다. 아래는 위에 설명 된 Cell 아키텍처의 데이터베이스 구성 일부의 일부분입니다.

Cell US0:

# config/database.yml
production:
  main:
    host: postgres-main.cell-us0.primary.consul
    load_balancing:
      discovery: postgres-main.cell-us0.replicas.consul
  ci:
    host: postgres-ci.cell-us0.primary.consul
    load_balancing:
      discovery: postgres-ci.cell-us0.replicas.consul
  users:
    host: postgres-users-primary.consul
    load_balancing:
      discovery: postgres-users-replicas.us.consul
  routes:
    host: postgres-routes-primary.consul
    load_balancing:
      discovery: postgres-routes-replicas.us.consul
  admin:
    host: postgres-admin-primary.consul
    load_balancing:
      discovery: postgres-admin-replicas.us.consul

Cell EU0:

# config/database.yml
production:
  main:
    host: postgres-main.cell-eu0.primary.consul
    load_balancing:
      discovery: postgres-main.cell-eu0.replicas.consul
  ci:
    host: postgres-ci.cell-eu0.primary.consul
    load_balancing:
      discovery: postgres-ci.cell-eu0.replicas.consul
  users:
    host: postgres-users-primary.consul
    load_balancing:
      discovery: postgres-users-replicas.eu.consul
  routes:
    host: postgres-routes-primary.consul
    load_balancing:
      discovery: postgres-routes-replicas.eu.consul
  admin:
    host: postgres-admin-primary.consul
    load_balancing:
      discovery: postgres-admin-replicas.eu.consul

요청 흐름

  1. gitlab-org는 최상위 네임스페이스이며 Cell US0GitLab.com Public 조직에 있습니다.
  2. my-company는 최상위 네임스페이스이며 Cell EU0my-organization 조직에 있습니다.

my-organization의 구성원인 유료 사용자를 위한 경험

해당 사용자는 기본 조직을 /my-organization으로 설정하고, 이 조직 외의 전역 경로를로드 할 수 없습니다. 다른 프로젝트/네임스페이스를로드 할 수 있지만 페이지 상단에 표시된 MR/Todo/Issue 수는 처음에는 올바르게 채워지지 않을 것입니다. 사용자는 이 제한을 인식하고 있을 것입니다.

로그인한 상태에서 /my-company/my-project로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 라우터 캐시 없이 /my-company/my-project를 요청하면, 라우터는 무작위로 Cell EU1을 선택합니다.
  3. /internal/cells/learnCell EU1로 전송되고, 해당 리소스가 Cell EU0에 있는 것으로 응답합니다.
  4. Cell EU0이 올바른 응답을 반환합니다.
  5. 이제 라우터는 /my-company/*와 일치하는 모든 요청 경로를 Cell EU0로 이동해야한다는 것을 캐시하고 기억합니다.
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_eu1 as Cell EU1 user->>router_eu: GET /my-company/my-project router_eu->>cell_eu1: /api/v4/internal/cells/learn?method=GET&path_info=/my-company/my-project cell_eu1->>router_eu: {path: "/my-company", cell: "cell_eu0", source: "routable"} router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: <h1>My Project...

로그아웃한 상태에서 /my-company/my-project로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 라우터는 아직 /my-company/*를 캐시하지 않았으므로 무작위로 Cell EU1을 선택합니다.
  3. /internal/cells/learnCell EU1로 전송되고, 해당 리소스가 Cell EU0에 있는 것으로 응답합니다.
  4. Cell EU0이 로그인 플로우를 통해 리디렉션합니다.
  5. 사용자는 /users/sign_in을 요청하고, 임의의 셀을 사용하여 /internal/cells/learn을 실행합니다.
  6. Cell EU1은 고정 경로로 cell_0을 응답합니다.
  7. 로그인 후 사용자가 캐시되고 Cell EU0에 저장된 /my-company/my-project을 요청합니다.
  8. Cell EU0은 올바른 응답을 반환합니다.
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_eu1 as Cell EU1 user->>router_eu: GET /my-company/my-project router_eu->>cell_eu1: /api/v4/internal/cells/learn?method=GET&path_info=/my-company/my-project cell_eu1->>router_eu: {path: "/my-company", cell: "cell_eu0", source: "routable"} router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: 302 /users/sign_in?redirect=/my-company/my-project user->>router_eu: GET /users/sign_in?redirect=/my-company/my-project router_eu->>cell_eu1: /api/v4/internal/cells/learn?method=GET&path_info=/users/sign_in cell_eu1->>router_eu: {path: "/users", cell: "cell_eu0", source: "fixed"} router_eu->>cell_eu0: GET /users/sign_in?redirect=/my-company/my-project cell_eu0-->>user: <h1>Sign in... user->>router_eu: POST /users/sign_in?redirect=/my-company/my-project router_eu->>cell_eu0: POST /users/sign_in?redirect=/my-company/my-project cell_eu0->>user: 302 /my-company/my-project user->>router_eu: GET /my-company/my-project router_eu->>cell_eu0: GET /my-company/my-project router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: <h1>My Project...

마지막 단계 이후 /my-company/my-other-project로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 라우터 캐시에 이제 /my-company/* => Cell EU0이 있는 경우, 라우터는 Cell EU0을 선택합니다.
  3. Cell EU0은 캐시 헤더와 함께 올바른 응답을 반환합니다.
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_eu1 as Cell EU1 user->>router_eu: GET /my-company/my-project router_eu->>cell_eu0: GET /my-company/my-project cell_eu0->>user: <h1>My Project...

마지막 단계 이후 /gitlab-org/gitlab로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 이 URL에 대한 캐시된 값이 없으므로, 라우터가 무작위로 Cell EU0을 선택합니다.
  3. Cell EU0이 라우터를 Cell US0로 리디렉션합니다.
  4. Cell US0이 캐시 헤더와 함께 올바른 응답을 반환합니다.
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 participant cell_us0 as Cell US0 user->>router_eu: GET /gitlab-org/gitlab router_eu->>cell_eu0: /api/v4/internal/cells/learn?method=GET&path_info=/gitlab-org/gitlab cell_eu0->>router_eu: {path: "/gitlab-org", cell: "cell_us0", source: "routable"} router_eu->>cell_us0: GET /gitlab-org/gitlab cell_us0->>user: <h1>GitLab.org...

이 경우 사용자가 “기본 조직”이 아니기 때문에 TODO 카운터에는 일반적인 할 일이 포함되지 않을 것입니다. 우리는 UI 상에 이를 강조할 수 있습니다. 나중에 일부 iteration은 그들을 위해 기본 조직에서 해당 정보를 가져올 수 있을 것입니다.

/로 이동

  1. 사용자는 유럽에 있으므로 DNS가 유럽의 라우터로 해석됩니다.
  2. 라우터는 / 경로에 대한 캐시를 가지고 있지 않습니다(Rails는 특별히 이 경로를 캐시하도록 지시하지 않습니다).
  3. 라우터는 임의로 Cell EU0을 선택합니다.
  4. Rails 애플리케이션은 사용자의 기본 조직이 /my-organization임을 알고 있으므로, 사용자를 /organizations/my-organization/-/dashboard로 리디렉션합니다.
  5. 라우터는 /organizations/my-organization/*에 대한 캐시 값을 가지고 있으므로 요청을 POD EU0로 보냅니다.
  6. Cell EU0은 UI 상에서 명확히 조직으로 범위가 설정된 오늘의 대시보드 보기인 /organizations/my-organization/-/dashboard을 제공합니다.
  7. 사용자는 (선택적으로) 페이지 상에 기본 조직에서만 데이터가 표시된다는 메시지를 볼 수 있으며, 조직을 변경할 수 있다는 안내를 받을 수 있습니다.
sequenceDiagram participant user as User participant router_eu as Router EU participant cell_eu0 as Cell EU0 user->>router_eu: GET / router_eu->>cell_eu0: GET / cell_eu0->>user: 302 /organizations/my-organization/-/dashboard user->>router: GET /organizations/my-organization/-/dashboard router->>cell_eu0: GET /organizations/my-organization/-/dashboard cell_eu0->>user: <h1>My Company Dashboard... X-Gitlab-Cell-Cache={path_prefix:/organizations/my-organization/}

/대시보드로 이동

위와 같이, Rails 응용프로그램은 이미 /를 대시보드 페이지로 리디렉션하기 때문에 사용자는 /organizations/my-organization/-/dashboard에 도착하게 됩니다.

/not-my-company/not-my-project로 이동한 경우(그러나 해당 프로젝트/그룹은 비공개이므로 액세스할 수 없음)

  1. 사용자가 유럽에 있으므로 DNS는 유럽의 라우터로 해석됩니다.
  2. 라우터는 /not-my-companyCell US1에 있는 것을 알기 때문에 해당 요청을 해당 셀로 보냅니다.
  3. 사용자는 액세스 권한이 없기 때문에 Cell US1에서 404를 반환합니다.
sequenceDiagram participant user as 사용자 participant router_eu as 라우터 EU participant cell_us1 as 셀 US1 user->>router_eu: GET /not-my-company/not-my-project router_eu->>cell_us1: GET /not-my-company/not-my-project cell_us1->>user: 404

새 최상위 네임스페이스 생성

사용자는 네임스페이스를 어떤 조직에 속하게 할지 선택하도록 요청받게 됩니다. my-organization을 선택하면, 해당 네임스페이스는 my-organization의 모든 다른 네임스페이스가 있는 셀에 위치하게 됩니다. 아무것도 선택하지 않으면 기본적으로 GitLab.com Public으로 설정되며 사용자에게 현재 조직과는 독립적이라는 것이 명확하게 표시됩니다.

/gitlab-org의 구성원인 GitLab 팀 구성원 환경

그러한 사용자는 레거시 사용자로 간주되며 기본 조직이 GitLab.com Public으로 설정됩니다. 이는 실제로 존재하지 않는 “메타” 조직이며, Rails 응용프로그램은 이 조직을 해석하여 /dashboard와 같이 레거시 글로벌 기능을 사용할 수 있도록 제공됩니다. 이뿐만 아니라 Rails 백엔드는 /dashboard와 같이 애매한 경로의 기본 셀을 Cell US0으로 렌더링하도록 알고 있습니다. 마지막으로 사용자는 /my-organization과 같은 다른 셀의 조직으로 이동할 수 있지만 이 경우 사용자는 일부 데이터가 누락될 수 있다는 메시지가 표시됩니다(MRs/이슈/할 일 수 등).

로그인하지 않은 채 /gitlab-org/gitlab로 이동하는 경우

  1. 사용자가 미국에 있으므로 DNS는 미국의 라우터로 해석됩니다.
  2. 라우터는 /gitlab-orgCell US0에 있는 것을 알기 때문에 해당 셀로 해당 요청을 보냅니다.
  3. Cell US0은 응답을 제공합니다.
sequenceDiagram participant user as 사용자 participant router_us as 라우터 US participant cell_us0 as 셀 US0 user->>router_us: GET /gitlab-org/gitlab router_us->>cell_us0: GET /gitlab-org/gitlab cell_us0->>user: <h1>GitLab.org...

/로 이동하는 경우

  1. 사용자가 미국에 있으므로 DNS는 미국의 라우터로 해석됩니다.
  2. 라우터는 / 경로에 대한 캐시를 보유하고 있지 않습니다(rails가 이 경로를 캐시하도록 지시하지 않은 경우)
  3. 라우터는 Cell US1을 무작위로 선택합니다.
  4. Rails 응용프로그램은 사용자의 기본 조직이 GitLab.com Public임을 알고 있으므로 사용자를 /dashboards로 리디렉션합니다(레거시 사용자만 /dashboard를 보려고 볼 수 있음)
  5. 라우터는 /dashboard 경로에 대한 캐시를 보유하고 있지 않습니다(rails가 이 경로를 캐시하도록 지시하지 않은 경우)
  6. 라우터는 Cell US1을 무작위로 선택합니다.
  7. Rails 응용프로그램은 사용자의 기본 조직이 GitLab.com Public임을 알고 있으므로 사용자가 /dashboards를 불러올 수 있게 합니다(레거시 사용자만 /dashboard 전역 뷰를 볼 수 있음) 그리고 Cell US0으로 리디렉션합니다
  8. Cell US0은 현재의 전역 뷰 대시보드 페이지 /dashboard를 제공합니다.
sequenceDiagram participant user as 사용자 participant router_us as 라우터 US participant cell_us0 as 셀 US0 participant cell_us1 as 셀 US1 user->>router_us: GET / router_us->>cell_us1: GET / cell_us1->>user: 302 /dashboard user->>router_us: GET /dashboard router_us->>cell_us1: /api/v4/internal/cells/learn?method=GET&path_info=/dashboard cell_us1->>router_us: {path: "/dashboard", cell: "cell_us0", source: "routable"} router_us->>cell_us0: GET /dashboard cell_us0->>user: <h1>Dashboard...

/my-company/my-other-project로 로그인한 상태에서 이동하는 경우(그러나 해당 프로젝트는 비공개이므로 액세스할 수 없음)

404가 발생합니다.

인증되지 않은 사용자의 경험

로그인한 사용자와 유사한 흐름을 갖지만 /dashboard와 같은 전역 경로는 로그인 페이지로 리디렉션됩니다. 왜냐하면 기본 조직을 선택할 수 있는 조직이 없기 때문입니다.

새 고객이 가입하는 경우

이들은 이미 조직의 일부인지 물어보거나 만들고자 하는지 물어보게 됩니다. 둘 다 선택하지 않으면 기본적으로 GitLab.com Public 조직으로 이동하게 됩니다.

조직을 한 셀에서 다른 셀로 이동하는 경우

TODO

URL에서 네임스페이스를 포함하지 않는 GraphQL/API 요청

TODO

검색 표시줄에서의 자동 완성 제안 기능(최근 이슈/MR을 기억함)

TODO

전역 검색

TODO

관리자

/admin 페이지 로드

  1. /adminCell US0에 잠겨 있습니다.
  2. /admin의 일부 엔드포인트(예: 관리자 내 프로젝트)는 셀에 스코프가 지정되어 있으며 사용자는 드롭다운에서 올바른 엔드포인트를 선택해야 합니다. 결과적으로 /admin/cells/cell_0/projects와 같은 엔드포인트가 생성됩니다.

포스트그레SQL에서의 관리자 영역 설정은 발산을 피하기 위해 모든 셀 간에 공유되지만 URL 및 UI에 어떤 셀이 관리자 영역 페이지를 제공하는지 명확하게 표시되며 이러한 페이지에서 동적 데이터가 생성되고 제공될 것이기 때문에 전달원은 특정 셀을 보고 여기에서 데이터를 보고 싶어할 수 있습니다.

해결해야 할 더 많은 기술적인 문제들

모든 셀 간 사용자 세션 복제하기

현재 사용자 세션은 Redis에 저장되지만 각 셀은 고유의 Redis 인스턴스를 가지고 있습니다. 이미 세션에 대해 전용 Redis 인스턴스를 사용하고 있기 때문에 gitlab_users 포스트그레SQL 데이터베이스와 마찬가지로 이를 모든 셀과 공유하는 것을 고려할 수 있습니다. 그러나 고려해야 할 중요한 사항은 대부분의 경우 세션을 대부분 동일한 지역에서 가져오고 싶어하기 때문에 지연 시간입니다.

다른 대안은 사용자 세션이 모든 세션 데이터를 인코딩하는 JWT 페이로드로 이동하는 것일 수 있지만 이 접근 방식에도 단점이 있습니다. 예를 들어, 사용자 세션이 JWT에 의해 제어되기 때문에 사용자의 비밀번호 변경 또는 기타 이유로 세션 만료를 하는 것이 어려울 수 있습니다.

셀 간 데이터 이동하는 방법은 무엇인가

셀 간의 데이터 이동은 모든 데이터 스토어를 고려해야 합니다:

  1. 포스트그레SQL
  2. 공유상태 Redis
  3. Gitaly
  4. Elasticsearch

러너를 모든 셀 간에 공유해야 하는가?

우리에게는 두 가지 옵션이 있고 어떤 것이 더 간단한지 결정해야 합니다:

  1. 러너 등록 및 큐잉 테이블을 분해하여 모든 셀 간에 공유합니다. 이는 확장성에 영향을 미칠 수 있으며 이는 그룹/프로젝트 러너를 포함할 수 있으므로 이는 확장성에 대한 우려가 있습니다(높은 트래픽 테이블로서 이것은 공유해야 함).
  2. 러너가 각 셀당 등록되며, 아마도 각 셀에 별도의 러너 fllet가 있거나 많은 셀에 동일한 러너를 등록하거나 이는 큐잉에 대한 영향을 일으킬 수 있습니다.

모순이 없는 유일한 ID를 보장하는 방법

이 프로젝트는 적어도 네임스페이스와 프로젝트가 모든 셀에서 유일한 ID를 가진다고 가정합니다. 많은 요청이 ID를 기반으로 경로 지정되어야 하기 때문입니다. 이러한 테이블은 서로 다른 데이터베이스에 걸쳐 있으므로 유일한 ID를 보장하기 위해서는 새로운 해결책이 필요합니다. 고유한 ID가 필요한 다른 테이블들도 있을 것이며 GraphQL 및 기타 API에 대한 경로 지정 및 기타 설계 목표에 따라 기본 키를 모든 테이블에 대해 고유하게 하고 싶은지가 결정될 수 있습니다.