클라이언트 측 연결 풀

루비 프로세스는 ActiveRecord를 통해 데이터베이스에 액세스하며, 동시성에 기반하여 프로세스별로 연결 풀 크기를 자동으로 계산합니다.

Ruby on Rails가 데이터베이스 연결을 관리하는 방식 때문에, 애플리케이션 스레드 수만큼 이상의 연결이 있어야 합니다. database.yml에 ‘pool’ 설정이 있지만, 애플리케이션 스레드 수와 함께 유지해야 하기 때문에 매우 실용적이지 않습니다. 이러한 이유로, 데이터베이스 연결 풀에서 허용된 연결 수를 구성된 애플리케이션 스레드 수에 기반하여 재정의합니다.

Gitlab::Runtime.max_threads는 프로세스가 구성된 사용자 대면 애플리케이션 스레드 수입니다. 또한 데이터베이스 연결을 사용하는 보조 스레드도 있습니다. 시간이 지남에 따라 애플리케이션이 어떻게 발전하느냐에 따라 보조 스레드의 수를 정확하게 계산하기 어렵기 때문에, 사용자 대면 스레드 수에 고정된 여유를 추가합니다. 연결은 게으르게 생성되기 때문에 이 수가 너무 크더라도 상관없습니다.

연결 풀 문제 해결

연결 풀 사용량은 각 환경별로 연결 풀 포화 대시보드에서 확인할 수 있습니다.

만약 연결 풀 크기가 너무 작다면, 이는 응용프로그램에서 ActiveRecord::ConnectionTimeoutError로 나타날 것입니다. 거의 모든 연결이 사용될 때 경고가 발생하기 때문에, 이 전에 알고 있어야 합니다. 이 경우, DB_POOL_HEADROOM 환경 변수를 하드코딩된 값(10)보다 크게 설정하여 문제를 해결할 수 있습니다.

이 시점에서 예상보다 더 많은 연결을 사용하는 원인을 조사해야 합니다. 이를 위해 gitlab_ruby_threads_running_threads 메트릭을 사용할 수 있습니다. 예를 들어, 이 그래프는 데이터베이스에 연결하는 모든 실행 중인 스레드를 이름별로 보여줍니다. puma worker 또는 sidekiq_worker_thread로 레이블이 지정된 스레드는 Gitlab::Runtime.max_threads를 정의하는 스레드이므로 고려됩니다. 다른 10개 이상의 스레드가 실행 중인 경우, 기본적인 여유를 늘리는 것을 고려할 수 있습니다.

연결 수명주기

웹 요청의 경우, 데이터베이스 쿼리가 처음 실행될 때 풀에서 연결을 얻습니다. 요청이 완료되면 연결은 풀로 반환됩니다.

백그라운드 작업의 경우, 이 동작은 매우 비슷합니다. 스레드는 첫 번째 쿼리를 위해 연결을 얻고, 작업이 완료된 후에 반환됩니다.

이는 Rails에서 내부적으로 관리됩니다.