클라이언트 측 연결 풀

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

Ruby on Rails가 데이터베이스 연결을 관리하는 방식 때문에, 최소한 스레드 수와 동일한 수의 연결이 있어야 합니다. database.yml에 ‘pool’ 설정이 있지만, 응용 프로그램 스레드 수와 함께 유지해아 하는 것이 매우 번거로우므로, 우리는 데이터베이스 연결 풀에 허용된 연결 수를 구성된 응용 프로그램 스레드 수에 기반하여 재정의합니다.

Gitlab::Runtime.max_threads는 프로세스에서 구성된 사용자 대면 응용 프로그램 스레드 수입니다. 또한 데이터베이스 연결을 사용하는 보조 스레드도 있습니다. 시간이 지남에 따라 응용 프로그램이 진화함에 따라 보조 스레드 수를 정확하게 계산하는 것이 단순하지 않기 때문에, 우리는 사용자 대면 스레드 수에 고정된 여유를 더합니다. 이 수가 너무 크다면 문제가 없습니다. 왜냐하면 연결은 지연해서 생성되기 때문입니다.

연결 풀 문제 해결

연결 풀 가용성 대시보드에서 환경별로 연결 풀 사용량을 볼 수 있습니다.

연결 풀이 너무 작으면 응용 프로그램에서 ActiveRecord::ConnectionTimeoutError가 발생합니다. 거의 모든 연결이 사용될 때 알림을 받기 때문에 우리는 시간이 지나기 전에 이를 알아야 합니다. 만약 이런 일이 발생하면 DB_POOL_HEADROOM 환경 변수를 hardcoded된 값(10)보다 큰 값으로 설정하여 문제를 해소할 수 있습니다.

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

연결 수명주기

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

백그라운드 작업의 경우, 동작은 매우 유사합니다. 스레드는 첫 번째 쿼리를 위해 연결을 얻고, 작업이 완료되면 연결을 반환합니다.

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