Akka 演员的隔板策略

Bulkheading strategies for Akka actors

我有一个场景,一个重要的参与者需要调用一个慢速(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;
}

与此对应的 Akka 目前 看起来像:

// 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 后,我的主要收获是基本上有两种“bulkheading”策略我可以采用:

到目前为止我最好的尝试是:

// 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
        }
    }
}

但是如您所见,我遇到了一些问题:

如果我没理解错的话,你在这里有两种选择:你听 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);

这样你说“...当我从服务调用中得到结果时,请按照应用中的描述操作它...”