클라이언트 사이드 커넥션 풀
클라이언트 사이드 커넥션 풀 관련 내용을 설명합니다.
클라이언트 사이드 커넥션 풀 # ActiveRecord를 통해 데이터베이스에 접근하는 Ruby 프로세스는 프로세스의 동시성(concurrency)에 따라 커넥션 풀 크기를 자동으로 계산합니다. Ruby on Rails가 데이터베이스 커넥션을 관리하는 방식 때문에, 스레드 수만큼 충분한 커넥션을 확보하는 것이 중요합니다. database.yml 에 ‘pool’ 설정이 있지만, 애플리케이션 스레드 수와 함께 유지·관리해야 하므로 실용적이지 않습니다. 이러한 이유로, 설정된 애플리케이션 스레드 수를 기반으로 데이터베이스 커넥션 풀에서 허용하는 커넥션 수를 재정의(override)합니다. Gitlab::Runtime.max_threads 는 프로세스에 설정된 사용자 대면 애플리케이션 스레드의 수입니다. 데이터베이스 커넥션을 사용하는 보조(auxiliary) 스레드도 있습니다. 애플리케이션이 발전함에 따라 보조 스레드의 정확한 수를 파악하기가 어렵기 때문에, 사용자 대면 스레드 수에 고정된 여유분(headroom)을 추가합니다. 커넥션은 지연 초기화(lazily)되므로 이 수치가 다소 크더라도 괜찮습니다. 커넥션 풀 문제 해결 # 커넥션 풀 사용량은 환경별로 커넥션 풀 포화 대시보드 에서 확인할 수 있습니다. 커넥션 풀이 너무 작으면 애플리케이션에서 ActiveRecord::ConnectionTimeoutError 가 발생합니다. 거의 모든 커넥션이 사용될 때 알림을 받기 때문에, 타임아웃이 발생하기 전에 이 상황을 파악할 수 있습니다. 이 경우 DB_POOL_HEADROOM 환경 변수를 하드코딩된 기본값(10)보다 큰 값으로 설정하여 해결할 수 있습니다. 이 시점에서 예상보다 더 많은 커넥션을 사용하고 있는 원인을 조사해야 합니다. 이를 위해 gitlab_ruby_threads_running_threads 메트릭을 활용할 수 있습니다. 예를 들어, 이 그래프 는 데이터베이스에 연결하는 모든 실행 중인 스레드를 이름별로 표시합니다. puma worker 또는 sidekiq_worker_thread 로 레이블된 스레드는 Gitlab::Runtime.max_threads 를 정의하는 스레드이므로 이미 집계에 포함됩니다. 그 외에 10개를 초과하는 스레드가 실행 중이라면, 기본 여유분을 늘리는 것을 고려할 수 있습니다. 커넥션 라이프사이클 # 웹 요청의 경우, 처음으로 데이터베이스 쿼리가 실행되는 시점에 풀에서 커넥션을 가져옵니다. 커넥션은 요청이 완료된 후 풀로 반환됩니다. 백그라운드 job의 경우, 동작 방식은 매우 유사합니다. 스레드는 첫 번째 쿼리 시 커넥션을 가져오고, job이 완료된 후 반환합니다. 이 동작은 Rails 내부에서 관리됩니다.