天天看點

Java 微服務異步并行調用優化

Java 微服務異步并行調用優化

我們先來設想一個場景。

有一個 http 的接口 A,該接口内部實際上是由另外三個接口 B、C、D 傳回結果的組合,這三個接口不存在互相依賴。我們一般的寫法就是 B、C、D 同步順序執行,依次拿到結果後組裝在一起。那麼假如這三個接口分别耗時 2 秒,那麼 A 接口就要耗時 6 秒。如果可以讓 B、C、D 同時執行的話,那麼 A 接口理論上隻要耗時 2 秒。

當然實際情況肯定複雜的多,如果一個接口内部存在不互相依賴的耗時調用的話,那麼我們可以做這樣的合并,響應時間上的減少還是非常明顯的。整個接口的響應時間取決于最長的那個内部接口。

那麼我們來看看在 Java 中有哪些方法可以達到這樣的目的。認真思考下你會發現,如果要并行處理的話,在 Java 中隻能用多線程來做。實際情況中每個線程處理完的時間肯定不一樣,那麼如何讓線程先處理完的停下來等最後那個處理完的呢。如果經常用多線程的小夥伴肯定能想到 CountDownLatch 工具類。當然也有直接簡單暴力的方法,在空循環裡輪詢每個線程是否執行完,但是這樣做肯定不優雅。

那下面就直接上代碼了: 假設有個學生服務提供查詢學生名字,年齡和家庭資訊,每個服務之間沒有互相依賴。 我們就簡單模拟下來擷取學生資訊的一個接口。

正常方法

@RequestMapping("/getStudentInfo")

public Object getStudentInfo() {

long start = System.currentTimeMillis();

Map resultMap = new HashMap<>(10);

try {

resultMap.put("studentName", studentService.getStudentName());

resultMap.put("studentAge", studentService.getSutdentAge());

resultMap.put("studentFamilyInfo", studentService.getSutdentFamilyInfo());

} catch (Exception e) {

resultMap.put("errMsg", e.getMessage());

}

resultMap.put("total cost", System.currentTimeMillis() - start);

return resultMap;

順序同步執行,耗時 6 秒。

1. Future

@RequestMapping("/getStudentInfoWithFuture")

public Object testWhitCallable() {

CountDownLatch countDownLatch = new CountDownLatch(3);

Future futureStudentName = es.submit(() -> {

Object studentName = studentService.getStudentName();

countDownLatch.countDown();

return studentName;

});

Future futureStudentAge = es.submit(() -> {

Object studentAge = studentService.getSutdentAge();

return studentAge;

Future futureStudentFamilyInfo = es.submit(() -> {

Object studentFamilyInfo = studentService.getSutdentFamilyInfo();

return studentFamilyInfo;

//同步等待所有線程執行完之後再繼續

countDownLatch.await();

resultMap.put("studentName", futureStudentName.get());

resultMap.put("studentAge", futureStudentAge.get());

resultMap.put("studentFamilyInfo", futureStudentFamilyInfo.get());

2.RxJava

@RequestMapping("/getStudentInfoWithRxJava")

public Object testWithRxJava() {

CountDownLatch countDownLatch = new CountDownLatch(1);

Observable studentNameObservable = Observable.create(observableEmitter -> {

observableEmitter.onComplete();

}).subscribeOn(Schedulers.io());

Observable studentAgeObservable = Observable.create(observableEmitter -> {

Observable familyInfoObservable = Observable.create(observableEmitter -> {

//建立一個下遊 Observer

Observer observer = new Observer() {

@Override

public void onSubscribe(Disposable d) {

public void onNext(Object o) {

public void onError(Throwable e) {

public void onComplete() {

//因為後面用了 merge 操作符,是以會合并後發射,那麼隻要 countdown 一次就行了。

};

//建立連接配接,

Observable.merge(studentNameObservable, studentAgeObservable, familyInfoObservable).subscribe(observer);

//等待異步線程完成

對于 RxJava 我不熟,我也是臨時學習的,不知道這種寫法是不是最佳的。

3.CompletableFutures

@RequestMapping("/getStudentInfoWithCompletableFuture")

public Object getStudentInfoWithCompletableFuture() {

CompletableFuture completableFutureStudentName = CompletableFuture.supplyAsync(() -> {

return studentService.getStudentName();

} catch (InterruptedException e) {

e.printStackTrace();

return null;

CompletableFuture completableFutureSutdentAge = CompletableFuture.supplyAsync(() -> {

return studentService.getSutdentAge();

CompletableFuture completableFutureFamilyInfo = CompletableFuture.supplyAsync(() -> {

return studentService.getSutdentFamilyInfo();

CompletableFuture.allOf(completableFutureStudentName, completableFutureSutdentAge, completableFutureFamilyInfo).join();

resultMap.put("studentName", completableFutureStudentName.get());

resultMap.put("studentAge", completableFutureSutdentAge.get());

resultMap.put("studentFamilyInfo", completableFutureFamilyInfo.get());

自帶最後的同步等待,不需要 CountDownLatch。CompletableFuture 還有很多其他好用的方法。

有興趣的可以自己來實驗下。 github 項目位址 reactive-programming-sample。

Java程式員如何學習才能快速入門并精通呢?

當真正開始學習的時候難免不知道從哪入手,導緻效率低下影響繼續學習的信心。

但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,是以有一套實用的視訊課程用來跟着學習是非常有必要的。

為了讓學習變得輕松、高效,今天給大家免費分享一套阿裡架構師傳授的一套教學資源。幫助大家在成為架構師的道路上披荊斬棘。這套視訊課程詳細講解了(Spring,MyBatis,Netty源碼分析,高并發、高性能、分布式、微服務架構的原理,JVM性能優化、分布式架構)等這些成為架構師必備的内容!而且還把架構需要用到的各種程式進行了打包,根據基礎視訊可以讓你輕松搭建分布式架構環境,像在企業生産環境一樣進行學習和實踐。

Java 微服務異步并行調用優化

如果想提升自己的,看看上圖大綱能知道你現在還處于什麼階段要向那些方面發展?

同時小編已将上圖知識大綱裡面的内容打包好了......

想要資料的朋友,可以直接加群960439918擷取免費架構資料(包括高可用,高并發,spring源碼,mybatis源碼,JVM,大資料,Netty等多個技術知識的架構視訊資料和各種電子書籍閱讀)

加入群聊【java進階架構交流群】

Java 微服務異步并行調用優化