HackToTech

Hack To Technology

auroraでフェイルオーバーした際にコネクションの接続がぜんぜん切り替わらなくて色々見てたのでメモ

環境

  • Aurora postgresql
  • Spring Boot
    • driver は org.postgresql.driver
  • Doma

メモ

AWSのベストプラクティスにも書かれているやつで、targetServerTypeprimary に指定しておけばFOした際に自動的にコネクションが再接続される

jdbc:postgresql://myauroracluster.cluster-c9bfei4hjlrd.us-east-1-beta.rds.amazonaws.com:5432,myauroracluster.cluster-ro-c9bfei4hjlrd.us-east-1-beta.rds.amazonaws.com:5432/postgres?user=<primaryuser>&password=<primarypw>&loginTimeout=2&connectTimeout=2&cancelSignalTimeout=2&socketTimeout=60&tcpKeepAlive=true&targetServerType=primary

docs.aws.amazon.com

targetServerType = String

Allows opening connections to only servers with required state, the allowed values are any, primary, master, slave, secondary, preferSlave and preferSecondary. The primary/secondary distinction is currently done by observing if the server allows writes. The value preferSecondary tries to connect to secondary if any are available, otherwise allows falls back to connecting also to primary. jdbc.postgresql.org

ただAWS公式だと参照系クエリをreplicaに逃がす部分の話はなかったので、一応pgjdbcの実装を確認した github.com

HostStatus hostStatus = HostStatus.ConnectOK;
if (candidateHost.targetServerType != HostRequirement.any) {
  hostStatus = isPrimary(queryExecutor) ? HostStatus.Primary : HostStatus.Secondary;
}
GlobalHostStatusTracker.reportHostStatus(hostSpec, hostStatus);
knownStates.put(hostSpec, hostStatus);
if (!candidateHost.targetServerType.allowConnectingTo(hostStatus)) {
  queryExecutor.close();
  continue;
}

pgjdbc/ConnectionFactoryImpl.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub

Tuple results = SetupQueryRunner.run(queryExecutor, "show transaction_read_only", true);

で接続先がreadonlyかどうかチェックしているらしい

pgjdbc/ConnectionFactoryImpl.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub

  primary {
    public boolean allowConnectingTo(@Nullable HostStatus status) {
      return status == HostStatus.Primary || status == HostStatus.ConnectOK;
    }
  },
  secondary {
    public boolean allowConnectingTo(@Nullable HostStatus status) {
      return status == HostStatus.Secondary || status == HostStatus.ConnectOK;
    }
  },

allowConnectingTo でコネクションが接続先の条件(targetServerType で指定した HostStatus )にマッチしているかを確かめて、マッチしていなければクローズするみたいな実装にしているらしい

pgjdbc/HostRequirement.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub

最終的に 書き込み用のコネクションプールの接続をjdbc:postgresql://<cluster_endpoiont>?targetServerType=primary
参照用のコネクションプールの接続をjdbc:postgresql://<cluster_readonly_endpoint>?targetServerType=secondary
にしていい感じになった
他にもベストプラクティスのパラメータ足したり、SpringBoot使ってるのでHikariCP周りの設定した