溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Apache Dubbo全鏈路異步怎么實現(xiàn)

發(fā)布時間:2021-12-15 15:02:42 來源:億速云 閱讀:247 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“Apache Dubbo全鏈路異步怎么實現(xiàn)”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Dubbo從2.7.0版本開始,升級了對java8的支持,以JUC包下的CompletableFuture為基礎(chǔ),支持所有異步編程接口,解決了2.7.0版本之前異步調(diào)用功能使用上的不方便。

Dubbo異步調(diào)用也是基于NIO的非阻塞能力實現(xiàn)的,服務(wù)消費端不需要啟動多個線程即可完成并行調(diào)用多個遠(yuǎn)程服務(wù),其調(diào)用流程如下:

Apache Dubbo全鏈路異步怎么實現(xiàn)

Dubbo2.7.0之前的弊端

在2.7.0之前,Dubbo的服務(wù)消費者異步調(diào)用服務(wù)提供者的的方式如下:

public interface UserService {    String findUser(String name);}
// 此調(diào)用會立即返回nulluserService.findUser(fooId);// 拿到調(diào)用的Future引用,當(dāng)結(jié)果返回后,會被通知和設(shè)置到此FutureFuture<User> userFuture = RpcContext.getContext().getFuture();userFuture.get();

或者

// 此調(diào)用會立即返回nulluserService.findUser(userId);// 拿到Dubbo內(nèi)置的ResponseFuture并設(shè)置回調(diào)ResponseFuture future = ((FutureAdapter)RpcContext.getContext().getFuture()).getFuture();future.setCallback(new ResponseCallback() {    @Override    public void done(Object response) {        System.out.print(response);    }    @Override    public void caught(Throwable exception) {        exception.printStackTrace();    }});

我們可以看到,無論從使用方面,還是從代碼的整潔度方面,都極不友好,需要進(jìn)行很多額外的操作才能拿到異步調(diào)用后的結(jié)果。

Dubbo2.7.0基于CompletableFuture的增強

2.7.0發(fā)布后,Dubbo升級到對java8的支持,同時基于CompletableFuture增強了異步調(diào)用。2.7.0允許接口返回CompletableFuture,通過這種類型的返回值,我們更容易的實現(xiàn)Consumer、Provider端的異步編程。

Dubbo2.7.0基于CompletableFuture編程的幾種方式

方法1、接口直接返回CompletableFuture

基于Dubbo的應(yīng)用,服務(wù)消費者和服務(wù)提供者都依賴一個二方SDK,我們可以直接把二方SDK的接口的返回值定義為CompletableFuture類型即可,服務(wù)消費端根據(jù)這個返回值類型,很方便的進(jìn)行異步調(diào)用。

// 接口定義public interface UsercService {    CompletableFuture<User> findUser(String name);}// Provider端public class UserServiceImpl implements UserService {    public CompletableFuture<User> findUser(String name) {        return CompletableFuture.supplyAsync(() -> {            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            return new User();        });    }}// Consumer端final UserService userService = (AsyncService) context.getBean("userService");CompletableFuture<User> future = userService.findUser("liuli");future.whenComplete((v, t) -> {    if (t != null) {        t.printStackTrace();    } else {       System.out.println("Response: " + v);    }});

方法2、重載原始方法

如果我們不想修改原始方法,我們可以重載原始方法,并將重載后的方法定義為CompletableFuture類型的返回值。

// 定義接口public interface UserService {    // 原始方法    User findUser(String name);    // 為了保證方法級服務(wù)治理規(guī)則依然有效,建議保持方法名不變: findUser    // 使用default實現(xiàn),避免給服務(wù)端提供者帶來額外實現(xiàn)成本    // boolean placeHoler只是為了實現(xiàn)重載而增加,只要Java語法規(guī)則允許,你可以使用任何方法重載手段    default CompletableFuture<User> findUser(String name, boolean placeHolder) {      return CompletableFuture.completedFuture(findUser(name));    }}// Provider端public class UserServiceImpl implements UserService {    @Override    public User findUser(String name) {        return new User();    }}// Consumer端UserService userService = (UserService) context.getBean("userService");CompletableFuture<User> future = userService.findUser("liuli");System.out.println("async call ret :" + future.get());

這樣一來,服務(wù)消費端可以直接調(diào)用重載后的findUser方法即可。

方法3、基于AsyncContext實現(xiàn)異步調(diào)用

// 接口定義public interface UserService {    User findUser(String name);}// Provider端public class UserServiceImpl implements UsercService {    public User findUser(String name) {        final AsyncContext asyncContext = RpcContext.startAsync();        // 耗時方法在線程中執(zhí)行        new Thread(() -> {            User user = new User();            // 返回結(jié)果            asyncContext.write(user);        }).start();        return null;    }}// Consumer端UserService userService = (UserService) context.getBean("userService");System.out.println(userService.findUser("liuli"));

在方法體中通過RpcContext.startAsync()開啟異步,然后耗時業(yè)務(wù)在新線程中異步執(zhí)行,然后執(zhí)行的結(jié)果通過asynvContext.write方法寫回,方法直接返回null。

“Apache Dubbo全鏈路異步怎么實現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI