WebFlux 服務(wù)編排使用優(yōu)勢(shì)詳解
WebFlux服務(wù)編排
WebFlux 服務(wù)編排是指使用 WebFlux 框架來編排多個(gè)異步服務(wù)的執(zhí)行順序和數(shù)據(jù)流動(dòng),從而構(gòu)建出一個(gè)完整的、基于事件驅(qū)動(dòng)的響應(yīng)式應(yīng)用程序。
WebFlux服務(wù)編排的優(yōu)勢(shì)如下:
高性能:WebFlux基于響應(yīng)式編程模型,可以使用少量的線程處理大量的請(qǐng)求,從而提高系統(tǒng)的并發(fā)能力和吞吐量。
異步處理:WebFlux可以異步處理請(qǐng)求和響應(yīng),避免線程的阻塞和等待,提高系統(tǒng)的并發(fā)能力和性能。
高可靠性:WebFlux基于事件驅(qū)動(dòng)的編程模型,可以更好地處理錯(cuò)誤和異常,從而提高系統(tǒng)的可靠性和穩(wěn)定性。
簡(jiǎn)潔清晰:WebFlux的代碼簡(jiǎn)潔清晰,可以使用函數(shù)式編程風(fēng)格來編寫業(yè)務(wù)邏輯,提高代碼的可讀性和可維護(hù)性。
可擴(kuò)展性:WebFlux可以輕松地集成其他的響應(yīng)式組件和服務(wù),例如Reactive Streams、Spring Cloud、RSocket等,從而提高系統(tǒng)的可擴(kuò)展性和靈活性。
綜上所述,WebFlux服務(wù)編排可以幫助我們構(gòu)建高性能、高可靠性、可擴(kuò)展性強(qiáng)的響應(yīng)式應(yīng)用程序,提高系統(tǒng)的并發(fā)能力和性能,從而更好地滿足現(xiàn)代應(yīng)用程序的需求。
一個(gè)示例
public Mono> getOrderDetails(String orderId) {
return Mono.fromCallable(() -> {
// 查詢訂單基本信息
return "order info";
})
.flatMap(orderInfo -> {
// 查詢訂單商品信息
return Mono.fromCallable(() -> {
return "order item info";
});
})
.flatMap(orderItemInfo -> {
// 查詢訂單配送信息
return Mono.fromCallable(() -> {
return "order delivery info";
});
})
.flatMap(orderDeliveryInfo -> {
// 查詢訂單支付信息
return Mono.fromCallable(() -> {
return "order payment info";
});
});
}為什么使用 fromCallable,就是上面說的,WebFlux 編排的是異步服務(wù),而不是同步服務(wù)。
但是實(shí)際線上不要使用 fromCallable,會(huì)導(dǎo)致創(chuàng)建很多個(gè)線程,高并發(fā)場(chǎng)景下會(huì)導(dǎo)致資源競(jìng)爭(zhēng)激烈,從而服務(wù)性能急劇下降。
1 串行
1.1 不需要 invoker1 的結(jié)果
long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> result = invoke1.flatMap(p -> Invoker2.invoke2())
.map(s -> {
return s.toString();
});
// result: invoker2, 耗時(shí):3592(串行)
System.out.println("result: " + result.block() + ", 耗時(shí):" + (System.currentTimeMillis() - start));1.2 需要返回 invoker1 的結(jié)果
long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> result = invoke1.flatMap(p -> {
return Invoker2.invoke2().map(s -> {
return p + s;
});
});
// result: invoker1invoker2, 耗時(shí):3554(串行)
System.out.println("result: " + result.block() + ", 耗時(shí):" + (System.currentTimeMillis() - start));2 并行
2.1 zip 方法
zip() 方法可以一次組裝任意個(gè)Mono,適用于有多個(gè)Mono的情況
long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> invoker2 = Invoker2.invoke2();
Mono<String> result = Mono.zip(invoke1, invoker2)
.map(s-> {
String t1 = s.getT1();
String t2 = s.getT2();
return String.format("invoke1:%s, invoke2: %s", t1, t2);
});
// invoker1invoker2耗時(shí):2650 (并行)
System.out.println("result: " + result.block() + ",耗時(shí):" + (System.currentTimeMillis() - start));2.2 zipWith 方法
zipWith() 每次組裝一個(gè)Mono對(duì)象,使用于組裝Mono個(gè)數(shù)比較少的情況。
long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> invoker2 = Invoker2.invoke2();
Mono<String> result = invoke1.zipWith(invoker2)
.map(s -> {
return String.format("invoke1:%s, invoke2: %s", s.getT1(), s.getT2());
});
// invoker1invoker2耗時(shí):2469 (并行)
System.out.println(result.block() + ",耗時(shí):" + (System.currentTimeMillis() - start));3 前提
這里的 invoker 就是第三方系統(tǒng)調(diào)用。
保證 invoker 是在獨(dú)立的線程中執(zhí)行,這樣 invoker 不會(huì)影響業(yè)務(wù)處理。
public class Invoker1 {
public static Mono<String> invoke1() {
return Mono.
fromSupplier(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "invoker1";
})
.subscribeOn(Schedulers.parallel())
.doOnError(e -> {
System.out.println("error invoker1");
});
}
}public class Invoker2 {
public static Mono<String> invoke2() {
return Mono.fromSupplier(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "invoker2";
})
.subscribeOn(Schedulers.parallel())
.doOnError(e -> {
System.out.println("error invoker2");
});
}
}以上就是WebFlux 服務(wù)編排使用優(yōu)勢(shì)詳解的詳細(xì)內(nèi)容,更多關(guān)于WebFlux 服務(wù)編排優(yōu)勢(shì)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring boot教程之產(chǎn)生的背景及其優(yōu)勢(shì)
這篇文章主要介紹了spring boot教程之產(chǎn)生的背景及其優(yōu)勢(shì)的相關(guān)資料,需要的朋友可以參考下2022-08-08
基于Java驗(yàn)證jwt token代碼實(shí)例
這篇文章主要介紹了基于Java驗(yàn)證jwt token代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
MyBatis批量插入數(shù)據(jù)的三種方法實(shí)例
由于項(xiàng)目需要生成多條數(shù)據(jù),并保存到數(shù)據(jù)庫(kù)當(dāng)中,項(xiàng)目使用了Spring+MyBatis,所以打算使用MyBatis批量插入,應(yīng)該要比循環(huán)插入的效果更好,下面這篇文章主要給大家介紹了關(guān)于MyBatis批量插入數(shù)據(jù)的三種方法,需要的朋友可以參考下2021-10-10
JavaEE SpringMyBatis是什么? 它和Hibernate的區(qū)別及如何配置MyBatis
這篇文章主要介紹了JavaEE Spring MyBatis是什么? 它和Hibernate的區(qū)別有哪些?如何配置MyBatis?本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
Java中用Socket實(shí)現(xiàn)HTTP文件上傳實(shí)例
本篇文章主要介紹了Java中用Socket實(shí)現(xiàn)HTTP文件上傳實(shí)例,詳細(xì)的介紹了通過讀取Socket的輸入流來實(shí)現(xiàn)一個(gè)文件上傳的功能,有興趣的同學(xué)可以一起了解一下2017-04-04
SpringBoot+JUnit5+MockMvc+Mockito單元測(cè)試的實(shí)現(xiàn)
今天聊聊如何在 SpringBoot 中集成 Junit5、MockMvc、Mocktio。Junit5 是在 Java 棧中應(yīng)用最廣的測(cè)試框架,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Spring運(yùn)行環(huán)境Environment的解析
本文主要介紹了Spring運(yùn)行環(huán)境Environment的解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
Centos下SpringBoot項(xiàng)目啟動(dòng)與停止腳本的方法
這篇文章主要介紹了Centos下SpringBoot項(xiàng)目啟動(dòng)與停止腳本的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11

