[Error] PoolCluster : Error: Pool is closed.
TypeORM 을 사용하다 마주치는 Poll is closed 오류
  • Backend

시작하기

AWS의 RDS를 사용하다보면 (꼭 AWS가 아니더라도 그럴 것이다.) RDS 의 버전이 어떠한 이유로 강제 업데이트 되는 경우가 있다.
경우에 따라 AWS는 보안 패치 또는 기능 업데이트와 같은 이유로 RDS 인스턴스를 강제로 업데이트할 수 있다. 이러한 경우 AWS는 고객에게 미리 알린 후 인스턴스가 업데이트되는 날짜와 시간을 제공하고 업데이트가 완료되면 인스턴스는 자동으로 다시 시작되어 업데이트된 버전으로 업그레이드된다.

image

(aws 에서 rds가 새로운 버전으로 패치되고 재시작된 로그기록)

이 경우 대부분은 문제가 없지만 TypeORM 을 사용하는경우 장애가 발생할 수 있다. image

그림과 같이 db.foo.rds.amazonaws.com RDS 의 엔드포인트는 변하지 않은 상태에서 DB Instance 만 바뀌는 경우가 된다. 이런경우 TypeORM 에서 DB 연결 Pool을 사용하고있는 경우 장애가 발생할 수 있다.
이미 연결된 Pool을 이용해 쿼리를 실행하지만, 실제 Instance는 변경된 상태이기 때문에 쿼리 실행에 실패한다.

image

해결방법으로는 RDS가 업데이트되어 재부팅되었을 때 서버로 특정 이벤트를 전달해서 connection을 다시 맺어줄 수 있을것이다.
하지만 이를 직접 구현하기란 번거롭다.

해결방법

TypeORM의 연결 config 설정 중에 이를 해결할 수 있는 옵션이 있다.

    /**
    * If true, PoolCluster will attempt to reconnect when connection fails. (Default: true)
    */
    canRetry: true,

    /**
     * If connection fails, node's errorCount increases.
     * When errorCount is greater than removeNodeErrorCount, remove a node in the PoolCluster. (Default: 5)
     */
    removeNodeErrorCount: 5,

    /**
     * If connection fails, specifies the number of milliseconds before another connection attempt will be made.
     * If set to 0, then node will be removed instead and never re-used. (Default: 0)
     */
     restoreNodeTimeout: 0,

    /**
     * Determines how slaves are selected:
     * RR: Select one alternately (Round-Robin).
     * RANDOM: Select the node by random function.
     * ORDER: Select the first node available unconditionally.
     */
    selector: "RR"

https://typeorm.io/multiple-data-sources#replication

restoreNodeTimeout 설정값이 default 0인데, 이는 연결이 실패했을 때 재연결하는 주기를 설정한다.
0으로 설정할 경우 연결 실패에 대해 다시 연결하지 않도록 한다.

간단하게 이를 1000 을 주어 해결할 수 있다. (ms 단위이다.) 그럼 Pool 을 사용하다가 쿼리에 실패했을 경우 (연결 오류로 인해) 1000ms 주기로 db 에 재연결을 시도한다.