見習いプログラミング日記

Javaを中心に色々なことを考えてみます。目指せ本物のプログラマ。

Quarkusのスレッドプール設定

Quarkusで実行されるブロッキングタスク(JAX-RS/Servletなど)は、従来のAPサーバと同様にランタイム内部で管理されるスレッドプールにより実行されます。

WildFly/JBoss EAPでtask-max-threadsに相当するパラメータは、ソースコード中のapplication.propertiesにおいてquarkus.thread-pool.max-threadsとして設定します。

src/main/resources/application.properties

# スレッドプールのアイドルスレッド数。未設定時のデフォルトは1。
quarkus.thread-pool.core-threads=32

# スレッドプールの最大数。未設定時のデフォルトは論理プロセッサ数x8。
quarkus.thread-pool.max-threads=64

このスレッドの実態はスレッドダンプを取得すると executor-thread-nとして確認できます。

kill -3 <pid>
"executor-thread-1" #24 daemon prio=5 os_prio=31 tid=0x00007f966b09b000 nid=0x5c03 waiting on condition [0x00007000112da000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at sample.quarkus.jpajaxrscdijta.Sleeper.sleep(Sleeper.java:7)

スレッドプールのチューニングはQuarkus0.16.1の時点では公式ドキュメントに言及がないですが、ブロッキングタスクを動かすならばチューニングした方が良いです。

  • デフォルト値が小さい。WildFlyではtask-max-threadsは論理プロセッサ数 x 16ですが、Quarkus0.16.1では論理プロセッサ数 x 8です。JDBCによるブロッキングI/O待ちですぐに枯渇します。
  • dockerの--cpuset-cpus=0など、コンテナレイヤで論理プロセッサ数を絞っている場合は、絞られたCPU数 x 8になる。
    • Quarkusの実装ではLinux環境の場合はコア数算出にRuntime.availableProcessor()依存せず、/proc/self/statusのCpus_allowedの値からコア数算出するorg.wildfly.common.cpu.ProcessorInfoクラスを使っているため、Java8のマイナーバージョンに関わらずcgroupsが反映されます。