RESTEasy Reactive とは
RESTEasy Reactive は Quarkus 1.11 で追加された拡張です。RESTEasyReactive では、 JAX-RS API を利用したまま、リクエストをイベントループ(Quarkus ではこれを I/Oスレッドと呼びます)で処理することでスループットを大幅に向上できます。
RESTEasy Reactive の拡張には以下のものが提供されています。
- quarkus-resteasy-reactive
- quarkus-resteasy-reactive-jackson
- quarkus-resteasy-reactive-jsonb
- quarkus-resteasy-reactive-links
- quarkus-resteasy-reactive-qute
Quarkus 2.2.0 で変更されたスレッドの割当ルール
I/Oスレッドはノンブロッキングであり、1つのスレッドで複数のリクエストを処理することができます。これに対して、1つのリクエストに1つのスレッドを割り当てる場合には、(旧来からの)ワーカースレッドが使われます。
Quarkus 2.2.0 以前の RESTEasy Reactive では、デフォルトで全てのリクエストが I/Oスレッドで実行されました。ワーカースレッドを使う場合には、エンドポイントメソッドに @Blocking
を指定する必要があり、特に Hibernate ORM などのブロッキングな操作を行う場合は、このアノテーションを明示的に追加する必要がありました。
Quarkus 2.2.0 からは、メソッドシグネチャに基づいて、I/Oスレッドまたはワーカースレッドが自動的に選択されるように変更されました。
戻り値の型がリアクティブな場合は、I/Oスレッドが利用され、それ以外の場合にはワーカースレットへディスパッチされます。つまり以下のような割当となります。
T method(…)
ワーカースレッドUni<T> method(…)
I/OスレッドCompletionStage<T> method(…)
I/OスレッドMulti<T> method(…)
I/OスレッドPublisher<T> method(…)
I/Oスレッド
ただし、@Transactional CompletionStage<T> method(…)
のように @Transactional
でアノテートされていた場合は ワーカースレッド が利用されます。
これらの割当ポリシーは @Blocking
と@NonBlocking
アノテーションを明示することで上書き変更することができます。
以下の例では、以前は I/Oスレッドで処理されていましたが、Quarkus 2.2.0 からはワーカースレッドで処理されるように変わりました。
package org.acme; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/hello") public class GreetingResource { @GET public String hello() { return "Hello"; } }
I/O スレッドで処理するには @NonBlocking
を付けるか、以下のような戻り値に変更します。
import io.smallrye.mutiny.Uni; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/hello") public class GreetingResource { @GET public Uni<String> hello() { return Uni.createFrom().item("Hello"); } }
旧来からの Hibernate ORM を利用する場合は以下のようになり、これはワーカースレッドで処理されます。
import org.jboss.resteasy.reactive.RestQuery; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/fruit") public class FruitResource { @GET public Fruit getFruit(@RestQuery String name) { return Fruit.find("name", name).firstResult(); } }
Hibernate Reactive を使った場合は、以下のようにすることで I/Oスレッドが使われます。
import io.smallrye.mutiny.Uni; import org.jboss.resteasy.reactive.RestQuery; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/fruit") public class FruitResource { @GET public Uni<Fruit> getFruit(@RestQuery String name) { return Fruit.find("name", name).firstResult(); } }
まとめ
Quarkus 2.2.0 から RESTEasy Reactive のスレッド割当ポリシーが変更されました。
I/Oスレッドが利用されるか、ワーカースレッドが利用されるかは、メソッドシグネチャにより自動的に判断されるようになりました。
旧来からの RESTEasy Reactive ユーザは注意してください。