Micronaut Reactive HTTP Request Processing
Since Micronaut is built on Netty, it is possible to perform non-blocking I / O.
Reactive HTTP Request Processing
If your controller method returns a non-blocking type such as an RxJava Observable or a CompletableFuture then Micronaut will use the Event loop thread to subscribe to the result.
When the Controller method returns the RxJava ʻObservable or CompletableFuture, it uses the Event loop thread to subscribe to the Controller` result.
If however you return any other type then Micronaut will execute your @Controller method in a preconfigured I/O thread pool.
If it returns any other type, it will use the I / O thread pool.
The return type of Controller is important, isn't it?
Well, it's easy, but let's use it.
Click here for this environment.
$ mn -V
| Micronaut Version: 1.0.4
| JVM Version: 1.8.0_191
For the time being, create a template project.
$ mn create-app hello-reactive --build maven
$ cd hello-reactive
Leave the class with the main method as it is for the time being
src/main/java/hello/reactive/Application.java
package hello.reactive;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class);
}
}
Let's make Controller.
src/main/java/hello/reactive/HelloReactiveController.java
package hello.reactive;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.reactivex.Flowable;
import org.reactivestreams.Publisher;
@Controller("/reactive")
public class HelloReactiveController {
}
Let's write the contents of the method.
First, let's check the documentation to see what type to return.
org.reactivestreams.PublisherSingle and ʻObservable`Mono and Fluxjava.util.concurrent.CompletableFutureIt seems like that.
In addition, it seems that you can use CompletableFuture or Reactive type for method arguments.
Let's create a text / event-stream method that returns a message every second.
@Get(value = "/hello", produces = MediaType.TEXT_EVENT_STREAM)
public Publisher<String> hello() {
return Flowable
.fromArray("Hello Reactive")
.repeat(10)
.delay(1, TimeUnit.SECONDS)
.map(m -> String.format("[%s] %s", LocalDateTime.now(), m));
}
When I checked the dependency of the created project, I found RxJava, so I used this.
$ ./mvnw dependency:tree
[INFO] +- io.micronaut:micronaut-runtime:jar:1.0.4:compile
[INFO] | +- io.micronaut:micronaut-aop:jar:1.0.4:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.8:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
[INFO] | +- io.reactivex.rxjava2:rxjava:jar:2.2.2:compile
Start and check.
$ curl -i localhost:8080/reactive/hello
HTTP/1.1 200 OK
transfer-encoding: chunked
Date: Wed, 20 Feb 2019 13:00:07 GMT
transfer-encoding: chunked
content-type: text/event-stream
data: [2019-02-20T13:00:08.861] Hello Reactive
data: [2019-02-20T13:00:09.940] Hello Reactive
data: [2019-02-20T13:00:10.943] Hello Reactive
data: [2019-02-20T13:00:11.946] Hello Reactive
data: [2019-02-20T13:00:12.948] Hello Reactive
data: [2019-02-20T13:00:13.950] Hello Reactive
data: [2019-02-20T13:00:14.953] Hello Reactive
data: [2019-02-20T13:00:15.954] Hello Reactive
data: [2019-02-20T13:00:16.956] Hello Reactive
data: [2019-02-20T13:00:17.959] Hello Reactive
Somehow, it works like that.
Let's write something that takes an argument.
@Post(value = "echo", consumes = MediaType.TEXT_PLAIN, produces = MediaType.TEXT_EVENT_STREAM)
public Publisher<String> echo(@Body Flowable<String> text) {
return text.map(t -> "★" + t + "★");
}
The input isn't streamed either ...
$ curl -i -XPOST -H 'Content-Type: text/plain' localhost:8080/reactive/echo -d 'hello'
HTTP/1.1 200 OK
transfer-encoding: chunked
Date: Wed, 20 Feb 2019 13:01:29 GMT
transfer-encoding: chunked
content-type: text/event-stream
data: ★hello★
Is it okay to put Reactor in the dependency?
For the time being, I was able to make a simple confirmation.
Recommended Posts