您好,登錄后才能下訂單哦!
本篇內容介紹了“Apache Dubbo全鏈路異步怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
Dubbo從2.7.0版本開始,升級了對java8的支持,以JUC包下的CompletableFuture為基礎,支持所有異步編程接口,解決了2.7.0版本之前異步調用功能使用上的不方便。
Dubbo異步調用也是基于NIO的非阻塞能力實現的,服務消費端不需要啟動多個線程即可完成并行調用多個遠程服務,其調用流程如下:
Dubbo2.7.0之前的弊端
在2.7.0之前,Dubbo的服務消費者異步調用服務提供者的的方式如下:
public interface UserService {
String findUser(String name);
}
// 此調用會立即返回null
userService.findUser(fooId);
// 拿到調用的Future引用,當結果返回后,會被通知和設置到此Future
Future<User> userFuture = RpcContext.getContext().getFuture();
userFuture.get();
或者
// 此調用會立即返回nulluserService.findUser(userId);// 拿到Dubbo內置的ResponseFuture并設置回調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(); }});
我們可以看到,無論從使用方面,還是從代碼的整潔度方面,都極不友好,需要進行很多額外的操作才能拿到異步調用后的結果。
Dubbo2.7.0基于CompletableFuture的增強
2.7.0發布后,Dubbo升級到對java8的支持,同時基于CompletableFuture增強了異步調用。2.7.0允許接口返回CompletableFuture,通過這種類型的返回值,我們更容易的實現Consumer、Provider端的異步編程。
Dubbo2.7.0基于CompletableFuture編程的幾種方式
方法1、接口直接返回CompletableFuture
基于Dubbo的應用,服務消費者和服務提供者都依賴一個二方SDK,我們可以直接把二方SDK的接口的返回值定義為CompletableFuture類型即可,服務消費端根據這個返回值類型,很方便的進行異步調用。
// 接口定義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); // 為了保證方法級服務治理規則依然有效,建議保持方法名不變: findUser // 使用default實現,避免給服務端提供者帶來額外實現成本 // boolean placeHoler只是為了實現重載而增加,只要Java語法規則允許,你可以使用任何方法重載手段 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());
這樣一來,服務消費端可以直接調用重載后的findUser方法即可。
方法3、基于AsyncContext實現異步調用
// 接口定義public interface UserService { User findUser(String name);}// Provider端public class UserServiceImpl implements UsercService { public User findUser(String name) { final AsyncContext asyncContext = RpcContext.startAsync(); // 耗時方法在線程中執行 new Thread(() -> { User user = new User(); // 返回結果 asyncContext.write(user); }).start(); return null; }}// Consumer端UserService userService = (UserService) context.getBean("userService");System.out.println(userService.findUser("liuli"));
在方法體中通過RpcContext.startAsync()開啟異步,然后耗時業務在新線程中異步執行,然后執行的結果通過asynvContext.write方法寫回,方法直接返回null。
“Apache Dubbo全鏈路異步怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。