云原生-Quarkus反應(yīng)性入門

Quarkus的多個(gè)反應(yīng)面

Quarkus是反應(yīng)性的。如果您在引擎蓋下看,會(huì)發(fā)現(xiàn)為Quarkus應(yīng)用程序提供動(dòng)力的反應(yīng)式引擎。該引擎是Eclipse Vert.x(https://vertx.io)。所有網(wǎng)絡(luò)I/O都通過無阻塞和響應(yīng)式Vert.x引擎?zhèn)鬟f。

想象一個(gè)傳入的HTTP請求。嵌入在Quarkus中的(Vert.x)HTTP服務(wù)器接收請求,然后將其路由到應(yīng)用程序。如果請求的目標(biāo)是命令式方法(傳統(tǒng)的JAX-RS,用@Blocking......注釋的代碼),則路由層將在工作線程中調(diào)用資源方法并在數(shù)據(jù)可用時(shí)寫入響應(yīng)。到目前為止,沒有什么新的或杰出的。下圖描述了這種行為。在這種情況下,在工作線程上調(diào)用應(yīng)用程序代碼,而業(yè)務(wù)邏輯可以阻止該線程。

但是,如果HTTP請求的目標(biāo)是響應(yīng)式方法(使用RESTEasy Reactive,響應(yīng)式路由的JAX-RS,@Incoming未使用@Blocking...注釋的方法),則路由層將在I/O線程上調(diào)用路由,從而帶來許多好處,例如更高的并發(fā)性和表現(xiàn):

因?yàn)镼uarkus使用I/O線程來調(diào)用的代碼,所以節(jié)省了上下文切換,避免了大線程池管理,從而提高了資源利用率。但是,代碼必須阻止線程。為什么?因?yàn)?,I/O線程用于處理多個(gè)并發(fā)請求。一旦因?yàn)樾枰獔?zhí)行一些I/O而無法處理請求,它就會(huì)調(diào)度這些I/O并傳遞一個(gè)繼續(xù)。它釋放可以處理另一個(gè)請求的線程。計(jì)劃的I/O完成后,繼續(xù)執(zhí)行該操作,返回I/O線程。

因此,許多Quarkus組件在設(shè)計(jì)時(shí)都考慮到了響應(yīng)性,例如數(shù)據(jù)庫訪問(PostgreSQL,MySQL,Mongo等),應(yīng)用程序服務(wù)(郵件,模板引擎等),消息傳遞(Kafka,AMQP等)。等等。但是,要充分利用此模型,應(yīng)以非阻塞方式編寫應(yīng)用程序代碼。那是擁有反應(yīng)式API的終極武器。

Mutiny-一個(gè)反應(yīng)式編程庫

Mutiny是一個(gè)反應(yīng)式編程庫,允許表達(dá)和編寫異步動(dòng)作。它提供兩種類型:

  • io.smallrye.mutiny.Uni -用于提供0或1個(gè)結(jié)果的異步操作
  • io.smallrye.mutiny.Multi -用于多物料(帶背壓)流

兩種類型都是惰性的,并且遵循訂閱模式。僅在實(shí)際需要時(shí)(即,訂戶加入),才開始計(jì)算。

uni.subscribe().with(
    result -> System.out.println("result is " + result),
    failure -> failure.printStackTrace()
);

multi.subscribe().with(
    item -> System.out.println("Got " + item),
    failure -> failure.printStackTrace()
);

雙方UniMulti揭露事件驅(qū)動(dòng)的API:表達(dá)想要在一個(gè)給定的事件(成功,失敗等)做什么。這些API分為幾組(操作類型),以使其更具表現(xiàn)力,并且避免將100個(gè)方法附加到一個(gè)類中。操作的主要類型是對失敗,完成,處理項(xiàng)目,提取或收集它們做出反應(yīng)。它具有可導(dǎo)航的API,可提供流暢的編碼體驗(yàn),并且結(jié)果不需要太多有關(guān)反應(yīng)式的知識。

httpCall
    .onFailure().recoverWithItem("my fallback");

反應(yīng)式流參考(https://www.reactive-streams.org/)。 Multi實(shí)現(xiàn)Reactive Streams Publisher從而實(shí)現(xiàn)Reactive Streams背壓機(jī)制。

擁抱Quarkus的反應(yīng)性和命令性支柱的統(tǒng)一,UniMulti為命令性構(gòu)造提供橋梁??梢詫⑥D(zhuǎn)換MultiIterable等待產(chǎn)生的項(xiàng)目Uni

// Block until the result is available
String result = uni.await().indefinitely();

// Transform an asynchronous stream into a blocking iterable
stream.subscribe().asIterable().forEach(s -> System.out.println("Item is " + s));

如果是RxJava或電抗器的用戶,可能不知道你如何使用自己熟悉的Flowable,SingleFlux,Mono...兵變允許轉(zhuǎn)換UnisMultis從和RX Java和反應(yīng)堆類型:

Maybe<String> maybe = uni.convert().with(UniRxConverters.toMaybe());
Flux<String> flux = multi.convert().with(MultiReactorConverters.toFlux());

但是,Vert.x呢?還可以使用Mutiny類型使用Vert.x API。以下代碼片段顯示了Vert.x Web客戶端的用法:

// Use io.vertx.mutiny.ext.web.client.WebClient
client = WebClient.create(vertx,
                new WebClientOptions().setDefaultHost("fruityvice.com").setDefaultPort(443).setSsl(true)
                        .setTrustAll(true));
// ...
Uni<JsonObject> uni =
    client.get("/api/fruit/" + name)
        .send()
        .onItem().transform(resp -> {
            if (resp.statusCode() == 200) {
                return resp.bodyAsJsonObject();
            } else {
                return new JsonObject()
                        .put("code", resp.statusCode())
                        .put("message", resp.bodyAsString());
            }
        });

最后但并非最不重要的一點(diǎn)是,Mutiny與SmallRye Context Propagation內(nèi)置了集成,因此可以在反應(yīng)式管道中傳播事務(wù),可追溯性數(shù)據(jù)等。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容