SOA異步特性設計稿

個人博客原文地址:http://www.ltang.me/2016/05/27/async-design/

思路

使用Java1.8的CompletableFuture特性,給soa框架的前後端添加異步特性。
+ 對於後端服務開發者(Porvider),要做的是構造一個包裝了預期返回結構體的Future,並返回,在其他線程中完成數據的準備,並調用CompletableFuture.complete方法。
+ 對於前端的方法調用者(Consumer),發起了一個請求,並返回了一個CompletableFuture的結果,在需要使用該結果時調用Future.get()方法。
+ 對於框架的層面,針對後端的異步,需要做的是維持數據通道,在Provider確定數據準備好之後,將數據取出,並返回給客戶端(Consumer);對於前端的異步,要做的是,接收到對應請求的返回結果後,將結果封裝到該請求對應的Future中。

代碼生成
Service
public interface HelloService {
    Future<String> sayHello(String name) throws com.isuwang.soa.core.SoaException;
}
Client
 public Future<String> sayHello(String name) throws SoaException {
        initContext("sayHello", true); //Is Async call
        try {
            sayHello_args sayHello_args = new sayHello_args();
            sayHello_args.setName(name);
            Future<String> response = new CompletableFuture<>();
            sendBase(sayHello_args, new sayHello_result(), new SayHello_argsSerializer(), new SayHello_resultSerializer(), response);
            return response;
            ...
Codec

打解包生成與同步的代碼生成結果一致,在發送和接收到數據前後進行Future的封裝和獲取。

使用
服務端
 @Override
public Future<String> sayHello(String name) throws SoaException {

    CompletableFuture<String> result = new CompletableFuture<>();

    new Thread(() -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        result.complete("result");
    }).start();

    return result;
}

簡單來說,即構造一個封裝了返回結果結構體的Future,並返回這個Future,此時工作線程已經返回,而組裝數據、通知完成的過程,則交給另一個線程處理,工作線程不需要在此阻塞,得到結果才返回。

客戶端

客戶端如常請求服務,並立即得到一個Future封裝的結果,該結果可能還沒有被寫入值,但此時線程可以執行其他後續任務,直到需要使用結果時調用Future.get()方法,此時如果結果已經從服務器返回,則立即獲得,否則阻塞至結果返回或超時。

HelloServiceClient client = new HelloServiceClient();
Future<String> result = client.sayHello("LiLei");

//do other job
System.out.println(result.get());

或者給Future添加一個回調方法,complete該Future的線程(或線程池)會執行該回調方法,客戶端不需要在此阻塞。

CompletableFuture<String> normalRequest = (CompletableFuture<String>) client.sayHello("Tomy", 15000l);
normalRequest.whenComplete((str, ex) -> {
     if (str != null) {
         System.out.println(str);
     } else {
         ex.printStackTrace();
     }
});

優化以及關注點

  • 客戶端可以自定義異步請求超時時間,時間到了如果服務端還沒返回會自動拋超時異常(已完成)
  • 服務端異常可以傳遞到客戶端(已完成)
  • 服務端completeExceptionally可以正確傳遞給客戶端(已完成)
  • 各種資源的正確釋放以及其他問題

相關鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章