클라이언트 측 연결 풀
Ruby 프로세스는 ActiveRecord를 통해 데이터베이스에 액세스할 때
동시성에 따라 프로세스의 연결 풀 크기를 자동으로 계산합니다.
루비 온 레일스가 데이터베이스 연결을 관리하는 방법 때문에
우리가 가지고 있는 스레드 수만큼 연결을 보유하는 것이 중요합니다.
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 내부에서 관리됩니다.