2015-06-22 95 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); 

这样,你说:“......那一刻我从服务调用的结果,请操纵它作为描述适用......”