话题
我想通过Akka HTTP与Akka Actor进行交互 。 这个想法是要有一个系统,其中HTTP客户端调用Akka HTTP服务器方法,该方法处理对Akka Actor的请求。 actor处理该消息并响应给调用方(Akka HTTP),该调用方对HTTP客户端进行应答。 如上所述,我设法做到了,但是由于我的实现似乎受阻,因此我认为我做得不正确。
我会更好地解释:如果我发出许多并发的HTTP请求,我会看到Akka HTTP“产生了一个队列”,因此等待参与者处理请求,然后再发送以下请求。
我想获得的是, Akka HTTP服务器将来自HTTP客户端的请求立即转发到目标akka actor,而无需等待actor结束阐述。 我想使用actor邮箱容量参数来确定邮件队列的大小,如果邮件过多,则拒绝邮件。
因此,我需要一种让Akka HTTP异常等待actor响应的方法。
我知道邮箱容量正常工作,因为如果我改用一个简单的actor2.tell(“ Prova1”,system.deadLetters())向我的actor发出许多请求(仅用于测试),则超出邮箱大小的请求是正确的被拒绝。
参考
为了测试我的系统,我按照akka文档提供的最少示例创建了一个简单的配置。 这对于akka http: https ://doc.akka.io/docs/akka-http/current/routing-dsl/index.html#minimal-example
我的密码
我做的第一件事是使用一个参与者(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 routeFlow = app.route(routeActor).flow(system, materializer);
CompletionStage 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
}
预期成绩
如您所见,在邮箱容量= 1的情况下,我希望,如果我发出多个并发请求,则仅处理一个,其余的将被丢弃。
我认为上面的代码对于我想要获取的代码是不正确的,因为我使用Akka HTTP路由来接收http://127.0.0.1/mysuburl/actor1/my_msg上的HTTP请求,然后使用Inbox将消息发送到演员,等待回应。
所以我的问题是:哪种异步方式将Akka HTTP请求链接到Akka Actor actor 1是正确的方法?
如果您需要更多详细信息,请告诉我。
注意
它解释了如何创建有限数量的线程以处理多个阻塞请求,但是我认为这只是“减轻”了我的代码(阻塞)的影响,但必须以不阻塞的方式编写。