我想通过Akka HTTP 与Akka Actor进行互动。这个想法是要有一个系统,其中HTTP客户端调用Akka HTTP服务器方法,该方法处理对Akka Actor的请求。 actor处理该消息并响应给调用方(Akka HTTP),该调用方对HTTP客户端进行应答。 如上所述,我设法做到了,但是由于我的实现似乎受阻,因此我认为我做得不正确。
我会更好地解释:如果我发出许多并发的HTTP请求,我会看到Akka HTTP“产生了一个队列”,因此等待参与者处理请求之后再发送以下内容。
我想获得的是, Akka HTTP服务器将来自HTTP客户端的请求立即转发到目标akka参与者,而无需等待参与者结束阐述。 我想使用actor邮箱容量参数来确定邮件队列的大小,如果邮件过多,则拒绝邮件。
因此,我需要一种让Akka HTTP异常等待actor响应的方法。
我知道邮箱容量工作正常,因为如果我改为使用简单的 actor2.tell(“ Prova1”,system.deadLetters())(仅用于测试),超过邮箱大小的请求将被正确拒绝。
为了测试我的系统,我按照akka文档提供的最少示例创建了一个简单的配置。 这对于akka http: https://doc.akka.io/docs/akka-http/current/routing-dsl/index.html#minimal-example
以及以下用于创建演员的内容: https://doc.akka.io/docs/akka/current/actors.html#creating-actors
我要做的第一件事是用一个actor(actor1)创建一个系统,按如下所示配置akka HTTP:
public class TestActor {
private static ActorSystem system;
public static void main(String[] args) throws InterruptedException
{
String httpBindAddress = "0.0.0.0";
int httpPort = 8086;
system = ActorSystem.create("deupnp");
ActorMaterializer materializer = ActorMaterializer.create(system);
Http http = Http.get(system);
AllDirectives app = new AllDirectives() {
};
Route routeActor = app.get(() ->
app.pathPrefix("mysuburl", () ->
app.pathPrefix(akka.http.javadsl.unmarshalling.StringUnmarshallers.STRING, actor ->
app.path(akka.http.javadsl.unmarshalling.StringUnmarshallers.STRING, message ->
app.onSuccess(() ->
CompletableFuture.supplyAsync(() -> actorFunctionCall(actor, message)), response ->
app.complete(StatusCodes.get(200), response))))));
Flow<HttpRequest, HttpResponse, NotUsed> routeFlow = app.route(routeActor).flow(system, materializer);
CompletionStage<ServerBinding> binding = http.bindAndHandle(routeFlow, ConnectHttp.toHost(httpBindAddress, httpPort), materializer);
// create system with one actor
ActorRef actor1 = system.actorOf(Props.create(ActorTest.class,"actor1").withMailbox("my-mailbox"),"actor1");
}
private static String actorFunctionCall(String actor, String message)
{
try {
Inbox inbox = Inbox.create(system);
system.actorSelection("user/"+actor).tell(message, inbox.getRef());
String response = (String) inbox.receive(Duration.create(20000, TimeUnit.SECONDS));
return response;
} catch (Exception e) {
//return new ResponseMessage(204,"Error");
e.printStackTrace();
return null;
}
}
}
我的ActorTest如下:
public class ActorTest extends AbstractActor {
private String myName = "";
public ActorTest(String nome){
this.myName = nome;
}
@Override
public void preStart()
{
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class,
message -> {
Thread.sleep(5000l);
System.out.println(this.getClass().getName() + " >> " + myName + " >> " + message);
})
.matchAny(mex->{
System.out.println("Error");
})
.build();
}
}
我的application.conf非常简单:
akka
{
stdout-loglevel = "DEBUG"
loglevel = "DEBUG"
actor {
default-dispatcher {
throughput = 10
}
}
}
my-mailbox {
mailbox-type = "akka.dispatch.NonBlockingBoundedMailbox"
mailbox-capacity = 1
}
如您所见,在 mailbox-capacity = 1 的情况下, 如果我发出的并发请求超过1个,则仅处理一个,其余的将被丢弃。
我认为上面的代码与我想获取的代码不正确,因为我使用Akka HTTP路由来接收http://127.0.0.1/mysuburl/actor1/my_msg上的HTTP请求,然后使用收件箱发送给演员的消息,然后等待响应。
所以我的问题是:哪种异步方式将Akka HTTP请求链接到Akka Actor actor 1是正确的方法?
如果您需要更多详细信息,请告诉我。
我什至阅读了以下文章: https://doc.akka.io/docs/akka-http/current/handling-blocking-operations-in-akka-http-routes.html
解释了如何创建有限数量的线程以处理多个阻塞请求,但是我认为这只能“缓解”我正在阻塞的代码的效果,但必须以一种不封锁。