diff --git a/docs/src/main/asciidoc/vertx-reference.adoc b/docs/src/main/asciidoc/vertx-reference.adoc index f0a0364a8c71a..f87565ce76105 100644 --- a/docs/src/main/asciidoc/vertx-reference.adoc +++ b/docs/src/main/asciidoc/vertx-reference.adoc @@ -14,12 +14,11 @@ As described in the xref:quarkus-reactive-architecture.adoc[Quarkus Reactive Arc This guide is the companion to the xref:vertx.adoc[Using Eclipse Vert.x API from a Quarkus Application] guide. It provides more advanced details about the usage and the configuration of the Vert.x instance used by Quarkus. - [#vertx-access] -== Accessing the Vert.x instance +== Access the Vert.x instance To access the managed Vert.x instance, add the `quarkus-vertx` extension to your project. -Note that this dependency may already be installed (as a transitive dependency). +This dependency might already be available in your project (as a transitive dependency). With this extension, you can retrieve the managed instance of Vert.x using either field or constructor injection: @@ -54,25 +53,26 @@ If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an i Documentation about the Vert.x Mutiny variant is available on https://smallrye.io/smallrye-mutiny-vertx-bindings. [[vertx-config]] -== Configuring the Vert.x instance +== Configure the Vert.x instance You can configure the Vert.x instance from the `application.properties` file. The following table lists the supported properties: include::{generated-dir}/config/quarkus-vertx-core.adoc[opts=optional, leveloffset=+1] +See <> to configure the Vert.x instance using a programmatic approach. [[using-vertx-clients]] -== Using Vert.x clients +== Use Vert.x clients In addition to Vert.x core, you can use most Vert.x ecosystem libraries. Some Quarkus extension already wraps Vert.x libraries. === Available APIs -The following table lists the most used libraries from the Vert.x ecosystem. +The following table lists the **most** used libraries from the Vert.x ecosystem. To access these APIs, add the indicated extension or dependency to your project. -Refer to the associated documentation to learn how to use them. +Check the associated documentation to learn how to use them. [cols="1,1,1",stripes=even,options=headers] |=== @@ -140,7 +140,7 @@ Refer to the associated documentation to learn how to use them. To learn more about the usage of the Vert.x Mutiny API, refer to https://smallrye.io/smallrye-mutiny-vertx-bindings. -=== Example of usage +=== Use the Vert.x Web Client This section gives an example using the Vert.x `WebClient` in the context of a RESTEasy Reactive application. As indicated in the table above, add the following dependency to your project: @@ -230,7 +230,7 @@ Then, create the native executable with: include::{includes}/devtools/build-native.adoc[] [#using-vert-x-json] -== Using Vert.x JSON +== Use Vert.x JSON Vert.x APIs often rely on JSON. Vert.x provides two convenient classes to manipulate JSON document: `io.vertx.core.json.JsonObject` and `io.vertx.core.json.JsonArray`. @@ -302,7 +302,7 @@ http://localhost:8080/hello/Quarkus/array returns: This works equally well when the JSON content is a request body or is wrapped in a `Uni`, `Multi`, `CompletionStage` or `Publisher`. -== Using verticles +== Use Verticles link:https://vertx.io/docs/vertx-core/java/#_verticles[Verticles] is "a simple, scalable, actor-like deployment and concurrency model" provided by _Vert.x_. This model does not claim to be a strict actor-model implementation, but it shares similarities, especially concerning concurrency, scaling, and deployment. @@ -314,7 +314,7 @@ It supports: * _bare_ verticle - Java classes extending `io.vertx.core.AbstractVerticle` * _Mutiny_ verticle - Java classes extending `io.smallrye.mutiny.vertx.core.AbstractVerticle` -=== Deploying verticles +=== Deploy Verticles To deploy verticles, use the `deployVerticle` method: @@ -331,7 +331,7 @@ If you use the Mutiny-variant of Vert.x, be aware that the `deployVerticle` meth NOTE: An example explaining how to deploy verticles during the initialization of the application will follow. -=== Using @ApplicationScoped Beans as Verticle +=== Use @ApplicationScoped beans as Verticle In general, Vert.x verticles are not CDI beans. And so cannot use injection. @@ -398,7 +398,7 @@ public void init(@Observes StartupEvent e, Vertx vertx, Instance If not set, the address is the fully qualified name of the bean; for instance, in this snippet, it's `org.acme.vertx.GreetingService`. <2> The method parameter is the message body. If the method returns _something_, it's the message response. -=== Configuring the address +=== Configure the address The `@ConsumeEvent` annotation can be configured to set the address: @@ -515,7 +515,7 @@ public String consume(String name) { ---- <1> Receive the messages sent to the `greeting` address -=== Asynchronous processing +=== Process events asynchronously The previous examples use synchronous processing. Asynchronous processing is also possible by returning either an `io.smallrye.mutiny.Uni` or a `java.util.concurrent.CompletionStage`: @@ -534,12 +534,6 @@ import io.smallrye.mutiny.Uni; @ApplicationScoped public class GreetingService { - @ConsumeEvent - public CompletionStage consume(String name) { - // return a CompletionStage completed when the processing is finished. - // You can also fail the CompletionStage explicitly - } - @ConsumeEvent public Uni process(String name) { // return an Uni completed when the processing is finished. @@ -555,7 +549,7 @@ The previous example uses Mutiny reactive types. If you are not familiar with Mutiny, check xref:mutiny-primer.adoc[Mutiny - an intuitive reactive programming library]. ==== -=== Blocking processing +=== Blocking processing of events By default, the code consuming the event must be _non-blocking_, as it's called on an I/O thread. If your processing is blocking, use the `@io.smallrye.common.annotation.Blocking` annotation: @@ -581,7 +575,7 @@ void consumeBlocking(String message) { When using `@Blocking`, it ignores the value of the `blocking` attribute of `@ConsumeEvent`. -=== Replying to messages +=== Reply to events The _return_ value of a method annotated with `@ConsumeEvent` is used to respond to the incoming message. For instance, in the following snippet, the returned `String` is the response. @@ -613,7 +607,7 @@ You can inject an `executor` if you use the Context Propagation extension: ---- ==== -=== Implementing fire and forget interactions +=== Implement fire-and-forget interactions You don't have to reply to received messages. Typically, for a _fire and forget_ interaction, the messages are consumed, and the sender does not need to know about it. @@ -627,7 +621,7 @@ public void consume(String event) { } ---- -=== Dealing with messages +=== Consume messages (instead of events) Unlike the previous example using the _payloads_ directly, you can also use `Message` directly: @@ -640,14 +634,14 @@ public void consume(Message msg) { } ---- -=== Handling Failures +=== Handle failures If a method annotated with `@ConsumeEvent` throws an exception, then: * if a reply handler is set, then the failure is propagated back to the sender via an `io.vertx.core.eventbus.ReplyException` with code `ConsumeEvent#FAILURE_CODE` and the exception message, -* if no reply handler is set, then the exception is rethrown (and wrapped in a `RuntimeException` if necessary) and can be handled by the default exception handler, i.e. `io.vertx.core.Vertx#exceptionHandler()`. +* if no reply handler is set, then the exception is rethrown (and wrapped in a `RuntimeException` if necessary) and can be handled by the default exception handler, _i.e._ `io.vertx.core.Vertx#exceptionHandler()`. -=== Sending messages +=== Send messages Sending and publishing messages use the Vert.x event bus: @@ -700,7 +694,7 @@ Uni response = bus.request("address", "hello, how are you?") .onItem().transform(Message::body); ---- -=== Using codecs +=== Use codecs The https://vertx.io/docs/vertx-core/java/#event_bus[Vert.x Event Bus] uses codecs to _serialize_ and _deserialize_ objects. Quarkus provides a default codec for local delivery. @@ -743,7 +737,7 @@ Uni greeting(MyName name) { <1> Set the name of the codec to use to send the message <2> Set the codec to use to receive the message -=== Combining HTTP and the event bus +=== Combine HTTP and the Event Bus Let's revisit a greeting HTTP endpoint and use asynchronous message passing to delegate the call to a separated bean. It uses the request/reply dispatching mechanism. @@ -828,7 +822,7 @@ To better understand, let's detail how the HTTP request/response has been handle 5. Once the reply is received by the sender, the content is written to the HTTP response -=== Bidirectional communication with browsers using SockJS +=== Bidirectional communication with browsers by using SockJS The SockJS bridge provided by Vert.x allows browser applications and Quarkus applications to communicate using the event bus. It connects both sides. @@ -910,14 +904,16 @@ The browser must use the `vertx-eventbus` JavaScript library to consume the mess ---- [#native-transport] -== Native Transport +== Use native transports + +IMPORTANT: Native transports are not supported in native executables. -IMPORTANT: Native transports are not supported in GraalVM produced binaries. +NOTE: To use `io_uring`, refer to the <> section. -Vert.x is capable of using https://netty.io/wiki/native-transports.html[Netty's native transports], which offers -performance improvements on specific platforms.To enable them, you must include the appropriate dependency for your -platform. It's usually a good idea to have both to keep your application platform-agnostic. Netty is smart enough -to use the correct one, that includes none at all on unsupported platforms: +Vert.x is capable of using https://netty.io/wiki/native-transports.html[Netty's native transports], which offers performance improvements on specific platforms. +To enable them, you must include the appropriate dependency for your platform. +It's usually a good idea to have both to keep your application platform-agnostic. +Netty is smart enough to use the correct one, that includes none at all on unsupported platforms: [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] .pom.xml @@ -966,7 +962,7 @@ If all is well quarkus will log: [io.qua.ver.cor.run.VertxCoreRecorder] (main) Vertx has Native Transport Enabled: true ---- -=== Native Linux Transport +=== Native Linux transport On Linux you can enable the following socket options: @@ -987,7 +983,7 @@ quarkus.http.tcp-cork=true quarkus.http.tcp-fast-open=true ---- -=== Native macOS Transport +=== Native macOS transport On macOS Sierra and above you can enable the following socket options: @@ -996,8 +992,7 @@ On macOS Sierra and above you can enable the following socket options: quarkus.http.so-reuse-port=true ---- - -== Listening to a Unix Domain Socket +== Use a Unix domain socket Listening on a Unix domain socket allows us to dispense with the overhead of TCP if the connection to the quarkus service is established from the same host. @@ -1030,7 +1025,101 @@ See <> for details. IMPORTANT: Make sure your application has the right permissions to write to the socket. -== Read only deployment environments +[#use-io_uring] +== Use io_uring + +IMPORTANT: `io_uring` is not supported in native executables. + +NOTE: `io_uring` support is experimental + +`io_uring` is a Linux kernel interface that allows you to send and receive data asynchronously. +It provides unified semantics for both file and network I/O. +It was originally designed to target block devices and files but has since gained the ability to work with things like network sockets. +It has the potential to provide modest performance benefits to network I/O on its own and greater benefits for mixed file and network I/O application workloads. + +To learn more about `io_uring`, we recommend the following links: + +* https://developers.redhat.com/articles/2023/04/12/why-you-should-use-iouring-network-io[Why you should use io_uring for network I/O]: The main benefit of io_uring for network I/O is a modern asynchronous API that is straightforward to use and provides unified semantics for file and network I/O. +A potential performance benefit of io_uring for network I/O is reducing the number of syscalls. +This could provide the biggest benefit for high volumes of small operations where the overhead of system calls can be significant. +* https://dzone.com/articles/the-backend-revolution-or-why-io-uring-is-so-impor[The Backend Revolution and Why io_uring Is So Important]: The io_uring API uses two ring buffers for communication between application and kernel (hence the API name) and designed in a way that enables natural batching of requests and responses. +Besides, it provides a way to submit multiple requests in one system call, which can reduce overhead. +* https://stackoverflow.com/questions/61767702/what-exactly-is-io-uring[What exactly is io_uring?]: io_uring is a Linux kernel interface to efficiently allow you to send and receive data asynchronously. +It was originally designed to target block devices and files but has since gained the ability to work with things like network sockets. + + +To use `io_uring`, you need to add two dependencies to your project and enable native transport. +First add the following dependencies to your project: + +[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] +.pom.xml +---- + + io.netty.incubator + netty-incubator-transport-native-io_uring + 0.0.21.Final + linux-x86_64 + + + io.vertx + vertx-io_uring-incubator + +---- + +[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"] +.build.gradle +---- +// Update the io_uring version by picking the latest from https://github.com/netty/netty-incubator-transport-io_uring/tags +implementation("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.21.Final") +implementation("io.vertx:vertx-io_uring-incubator") +---- + +Then, in the `application.properties`, add: + +[source, properties] +---- +quarkus.vertx.prefer-native-transport=true +---- + +[NOTE] +.Can I use io_uring on my Linux machine? +==== +To check if you can use `io_uring` on your Linux machine, execute the following command: +[source, shell] +---- +> grep io_uring_setup /proc/kallsyms +0000000000000000 t __pfx_io_uring_setup +0000000000000000 t io_uring_setup +0000000000000000 T __pfx___x64_sys_io_uring_setup +0000000000000000 T __x64_sys_io_uring_setup +0000000000000000 T __pfx___ia32_sys_io_uring_setup +0000000000000000 T __ia32_sys_io_uring_setup +0000000000000000 d event_exit__io_uring_setup +0000000000000000 d event_enter__io_uring_setup +0000000000000000 d __syscall_meta__io_uring_setup +0000000000000000 d args__io_uring_setup +0000000000000000 d types__io_uring_setup +0000000000000000 d __event_exit__io_uring_setup +0000000000000000 d __event_enter__io_uring_setup +0000000000000000 d __p_syscall_meta__io_uring_setup +---- +If it prints something like above, you can use `io_uring`. +==== + +[NOTE] +.Troubleshooting +==== +`io_uring` support is still experimental. +Check the https://github.com/netty/netty-incubator-transport-io_uring#faq[Netty io_uring FAQ] if you see some odd behavior. +Also, the https://github.com/netty/netty-incubator-transport-io_uring/issues/152[netty io_uring was slower than epoll] issue describes a few configuration mistakes. +==== + +IMPORTANT: Domain sockets are not yet supported with io_uring. + +IMPORTANT: The Vert.x asynchronous file system API does not use io_uring yet. + + +== Deploy on read-only environments In environments with read only file systems you may receive errors of the form: @@ -1041,13 +1130,14 @@ java.lang.IllegalStateException: Failed to create cache dir Assuming `/tmp/` is writable this can be fixed by setting the `vertx.cacheDirBase` property to point to a directory in `/tmp/` for instance in OpenShift by creating an environment variable `JAVA_OPTS` with the value `-Dvertx.cacheDirBase=/tmp/vertx`. -== Customizing the Vert.x configuration +[#customizing-the-vert-x-configuration] +== Customize the Vert.x configuration The configuration of the managed Vert.x instance can be provided using the `application.properties` file, but also using _special beans_. CDI beans exposing the `io.quarkus.vertx.VertxOptionsCustomizer` interface can be used to customize the Vert.x configuration. For example, the following customizer change the `tmp` base directory: -[source, java] +[source,java] ---- @ApplicationScoped public class MyCustomizer implements VertxOptionsCustomizer {