2015-06-22 70 views
1

我有一場重要的角色需要撥打電話一個緩慢的一個場景(15 - 20 )遠程系統:爲阿卡演員艙壁策略

// Non-actor code equivalent 
public Result makeSlowNetworkCall(Request request) { 
    Result result = slowServiceClient.soooooSlow(request);  // Could be up to 15 - 20 SECONDS (mehhhh) 
    return result; 
} 

的阿卡相當於這是目前看起來像:

// Groovy 
class SlowServiceActor extends UntypedActor { 
    @Override 
    void onReceive(Object message) { 
     if(message instanceof CallSlowService) { 
      Request request = (message as CallSlowService).request 
      Result result = makeSlowNetworkCall(request) 
      // ...now do something with result, some 15 seconds later 
     } 
    } 

    Result makeSlowNetworkCall(Request request) { 
     slowServiceClient.soooooSlow(request) 
    } 
} 

顯然,這是阻止壞,壞,壞的。閱讀this excellent article on handling non-blocking DB calls後,我的主要外賣的是,有兩個基本「艙壁」戰略,我可以使用:

  • 將所有SlowServiceActor情況下,在自己的調度員,從其他演員隔離的延遲/阻塞岬/不直接與慢服務交互的線程;和
  • 通過Futures真正調用緩慢的服務「異步

所以我的最好的嘗試迄今爲止是:

// In application.conf: 
slowServiceDispatcher { 
    ...config here 
} 

class CallSlowService implements Callable<Result> { 
    @Override 
    Result call() throws Exception { 
     slowServiceClient.soooooSlow(request) 
    } 
} 

// Created using the "slowServiceDispatcher" 
class SlowServiceActor extends UntypedActor { 
    @Override 
    void onReceive(Object message) { 
     if(message instanceof CallSlowService) { 
      Request request = (message as CallSlowService).request 
      Future<Result> callSlowServiceFuture = Futures.future(new CallSlowService()) 

      Result result = ??? 

      // ...now do something with result, some 15 seconds later 
     } 
    } 
} 

但正如你所看到的,我有幾個問題:

  • 我想我誤解了Futures.future(...) API;我不認爲這意味着構建新的Futures
  • 我如何以非阻塞的方式實際獲得result
  • 最後:我錯過了什麼嗎?我沒有使用/利用我應該的任何策略?
+1

我不特別理解akka,但對於基於一般事件的系統,不應該有一個不同的處理程序來處理來自緩慢服務的結果? –

+0

Thanks @RajatGarg(+1) - * yes *,但該處理程序將需要一種方法,不僅可以調用回執行者系統,還可以執行該特定執行上下文中的特定執行者。在不知道Akka的情況下,您很難理解爲什麼這會使典型的回調/處理器解決方案不可行。 – smeeb

回答

1

如果我理解這個正確的,你有種此處有兩個選項:你聽Future被完成或你做的結果是什麼:

如果你想聽聽,你可以使用一些回調像

final ExecutionContext ec = system.dispatcher(); 

future.onSuccess(new OnSuccess<String>() { 
    public void onSuccess(String result) { 
    if ("bar" == result) { 
     //Do something if it resulted in "bar" 
    } else { 
     //Do something if it was some other String 
    } 
    } 
}, ec); 

另一種方式是map未來的結果。所以,你有這樣的:

callSlowServiceFuture.map(new Mapper<ReturnType1, ReturnType2>() { 
    public ReturnType2 apply(ReturnType1 s) { 
    // do something with 's' 
    } 
}, ec); 

這樣,你說:「......那一刻我從服務調用的結果,請操縱它作爲描述適用......」