애플리케이션 제한 개발
GitLab v19.2요약
이 문서는 GitLab에 애플리케이션 제한을 추가하려는 기여자를 위한 개발 가이드입니다. 우선, 정보를 수집하고 다양한 GitLab 티어에 설정된 여러 제한 사항을 결정해야 합니다. 애플리케이션 제한 도입에 관한 가이드가 있습니다.
이 문서는 GitLab에 애플리케이션 제한을 추가하려는 기여자를 위한 개발 가이드입니다.
문서화#
우선, 정보를 수집하고 다양한 GitLab 티어에 설정된 여러 제한 사항을 결정해야 합니다. 다른 기여자들과 협력하여 해당 제한 사항을 문서화하고 공유하세요.
애플리케이션 제한 도입에 관한 가이드가 있습니다.
플랜 제한 구현#
plan_limits 테이블은 **셀 범위 구성(cell-scoped configuration)**입니다. 각 셀은 자체 테이블 사본을 가지며,
제한 사항은 셀 간에 마이그레이션되지 않습니다. 새로운 셀은 각 제한에 대한 칼럼 기본값으로 시작하고,
관리자는 관리자 Plan Limits API를 통해 셀별로 제한을 조정합니다.
이 때문에 모든 새로운 플랜 제한은 반드시 해당 API를 통해 설정 가능해야 합니다.
그렇지 않으면 새로운 제한이 각 셀에서 칼럼 기본값만 취할 수 있습니다.
셀 간에 일관성을 유지해야 하는 플랜 제한은 도입하지 마세요.
plan_limits는 셀 로컬이므로 동기화 상태를 유지할 방법이 없습니다.
데이터베이스 플랜 제한 삽입#
plan_limits 테이블에 새 칼럼을 만들고 제한 값을 삽입합니다.
두 개의 별도 마이그레이션 스크립트 파일을 만드는 것을 권장합니다.
- 원하는 제한을 나타내는 null이 아닌 기본값을 가진 새 칼럼을
plan_limits테이블에 추가합니다:
add_column(:plan_limits, :project_hooks, :integer, default: 100, null: false)
0으로 설정된 플랜 제한 항목은 제한이 활성화되어 있지 않음을 의미합니다.
이 설정은 특수하고 문서화된 상황에서만 사용해야 합니다.
- (선택 사항)
create_or_update_plan_limit마이그레이션 헬퍼를 사용하여 각 레벨을 원하는 제한으로 세부 조정하는 데이터베이스 마이그레이션을 만듭니다. 이 마이그레이션의 플랜은 GitLab.com의 플랜과 일치해야 합니다. 플랜이 누락되면 해당 플랜의 고객은 기본 제한(0, 즉 무제한일 수 있음)을 받게 됩니다.
예시:
class InsertProjectHooksPlanLimits < Gitlab::Database::Migration[2.1]
def up
create_or_update_plan_limit('project_hooks', 'default', 0)
create_or_update_plan_limit('project_hooks', 'free', 10)
create_or_update_plan_limit('project_hooks', 'premium', 30)
create_or_update_plan_limit('project_hooks', 'premium_trial', 30)
create_or_update_plan_limit('project_hooks', 'ultimate', 100)
create_or_update_plan_limit('project_hooks', 'ultimate_trial', 100)
create_or_update_plan_limit('project_hooks', 'ultimate_trial_paid_customer', 100)
create_or_update_plan_limit('project_hooks', 'opensource', 100)
end
def down
create_or_update_plan_limit('project_hooks', 'default', 0)
create_or_update_plan_limit('project_hooks', 'free', 0)
create_or_update_plan_limit('project_hooks', 'premium', 0)
create_or_update_plan_limit('project_hooks', 'premium_trial', 0)
create_or_update_plan_limit('project_hooks', 'ultimate', 0)
create_or_update_plan_limit('project_hooks', 'ultimate_trial', 0)
create_or_update_plan_limit('project_hooks', 'ultimate_trial_paid_customer', 0)
create_or_update_plan_limit('project_hooks', 'opensource', 0)
end
end
일부 플랜은 GitLab.com에만 존재합니다. 존재하지 않는 플랜에 대해서는 no-op입니다.
마이그레이션을 GitLab.com에만 적용하고 다른 인스턴스는 기본 제한을 사용하도록 하려면,
#up 및 #down 메서드의 시작 부분에 return unless Gitlab.com?을 추가하여
다른 인스턴스에서 마이그레이션이 no-op이 되도록 합니다.
- 관리자 Plan Limits API를 통해 새 칼럼을 노출합니다:
PUT /application/plan_limits에 optional 파라미터로 추가하세요
(lib/api/admin/plan_limits.rb).
관리자가 셀별로 제한을 조정할 수 있습니다.
-
응답 엔티티에 추가하세요 (
lib/api/entities/plan_limit.rb). 제한 값을 다시 읽을 수 있습니다. -
Plan Limits API 페이지에 해당 속성을 문서화하세요.
플랜 제한 유효성 검사#
현재 제한 가져오기#
현재 제한에 대한 접근은 프로젝트 또는 네임스페이스를 통해 수행할 수 있습니다:
project.actual_limits.project_hooks
현재 제한 확인#
현재 제한이 초과되는지 확인하는 메서드 PlanLimits#exceeded?가 있습니다.
ActiveRecord 객체 또는 Integer를 사용할 수 있습니다.
레코드 수가 정의된 제한을 초과하지 않도록 합니다:
project.actual_limits.exceeded?(:project_hooks, ProjectHook.where(project: project))
숫자가 정의된 제한을 초과하지 않도록 합니다:
project.actual_limits.exceeded?(:project_hooks, 10)
Limitable concern#
Limitable concern은
모델이 제한을 초과하지 않도록 유효성을 검사하는 데 사용할 수 있습니다.
현재 모델의 레코드 수가 정의된 제한을 초과하지 않도록 합니다.
유효성을 검사 중인 객체의 제한 범위와, 제한 이름이 복수화된 모델 이름과 다른 경우 제한 이름을 지정해야 합니다.
class ProjectHook
include Limitable
self.limit_name = 'project_hooks' # Optional as ProjectHook corresponds with project_hooks
self.limit_scope = :project
end
모델을 테스트하려면 공유 예시를 포함하면 됩니다.
it_behaves_like 'includes Limitable concern' do
subject { build(:project_hook, project: create(:project)) }
end
인스턴스 범위 제한 테스트#
인스턴스 범위 기능은 항상 default 플랜을 사용합니다.
인스턴스 범위 기능에는 라이선스가 할당되지 않기 때문입니다.
class InstanceVariable
include Limitable
self.limit_name = 'instance_variables' # Optional as InstanceVariable corresponds with instance_variables
self.limit_scope = Limitable::GLOBAL_SCOPE
end
구독 플랜#
GitLab Self-Managed:
default: 모든 사용자.
GitLab.com:
-
default: 시스템 전체 기능. -
free: Free 구독을 가진 네임스페이스 및 프로젝트. -
premium: Premium 구독을 가진 네임스페이스 및 프로젝트. -
premium_trial: Premium Trial 구독을 가진 네임스페이스 및 프로젝트. -
ultimate: Ultimate 구독을 가진 네임스페이스 및 프로젝트. -
ultimate_trial: Ultimate Trial 구독을 가진 네임스페이스 및 프로젝트. -
ultimate_trial_paid_customer: 30일 동안 Ultimate를 체험 중인 Premium 구독의 네임스페이스 및 프로젝트. -
opensource: GitLab Open Source 프로그램 회원인 네임스페이스 및 프로젝트.
GitLab.com에는 구독이 없는 early_adopter 플랜이 있습니다.
test 환경에는 플랜이 없습니다.
Rack::Attack을 사용한 속도 제한 구현#
Rack::Attack 미들웨어를 사용하여 Rack 요청을 스로틀합니다.
Rails 컨트롤러, Grape 엔드포인트 및 다른 Rack 요청에 적용됩니다.
새 스로틀을 추가하는 프로세스는 대략 다음과 같습니다:
-
ApplicationSetting모델의 rate_limits JSONB 칼럼에 새 필드를 추가합니다. -
rate_limits 칼럼의 JSON 스키마 검증기를 업데이트합니다.
-
Gitlab::RackAttack과Gitlab::RackAttack::Request를 확장하여 새 속도 제한을 구성하고, 원하는 요청에 적용합니다. -
app/views/admin/application_settings/_ip_limits.html.haml의 Admin 영역 폼에 새 설정을 추가합니다. -
사용자 및 IP 속도 제한 및 애플리케이션 설정 API에 새 설정을 문서화합니다.
-
GitLab.com의 속도 제한을 구성하고 GitLab.com의 속도 제한에 문서화합니다.
구현 세부 사항은 다음 이슈를 참조하세요:
Gitlab::ApplicationRateLimiter를 사용한 속도 제한 구현#
이 모듈은 특정 작업을 스로틀하는 데 사용할 수 있는 사용자 정의 속도 제한기를 구현합니다.
미들웨어 수준에서 동작하는 Rack::Attack 및 Rack::Throttle과 달리,
컨트롤러 또는 API 수준에서 사용할 수 있습니다.
컨트롤러에서 사용하려면 CheckRateLimit concern을 참조하세요.
코드의 다른 부분에서는 Gitlab::ApplicationRateLimiter 모듈을 직접 호출할 수 있습니다.
다음 속도 제한 아키텍처#
2022년 5월부터 미래 지향적인 속도 제한 아키텍처를 사용하는 애플리케이션 제한 프레임워크의 다음 이터레이션 작업을 시작했습니다.
새로운 요구 사항을 정의하고 다음 아키텍처를 설계하는 작업을 진행 중입니다. 새로운 제한을 추가하기 위한 새 기능이 필요한 경우, 지금 바로 구현하는 대신 속도 제한 아키텍처 워킹 그룹에 기여하는 것을 고려하세요.
다음 이터레이션의 속도 제한 아키텍처에 구축하고자 하는 기능의 예시:
-
네임스페이스별 / 플랜별로 제한을 정의하고 재정의할 수 있도록 합니다.
-
구현된 제한과 기본값에 관한 문서를 자동으로 생성합니다.
-
검색하고 탐색할 수 있는 단일 장소에 제한을 정의합니다.
-
소프트 및 하드 제한, 제한에 근접할 때 사용자에게 알림을 지원합니다.