Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Akka HTTP从多个参与者/web处理程序正确调用单个服务器?_Java_Akka_Akka Http - Fatal编程技术网

Java 如何使用Akka HTTP从多个参与者/web处理程序正确调用单个服务器?

Java 如何使用Akka HTTP从多个参与者/web处理程序正确调用单个服务器?,java,akka,akka-http,Java,Akka,Akka Http,我有一个服务(我们称之为服务a),它使用Akka服务器HTTP来处理传入的请求。 我还有第三方应用程序(服务B),它提供了几个web服务。 服务A的目的是转换客户端请求,调用服务B的一个或多个web服务,合并/转换结果并将其服务回客户端 我用演员演某些角色,而用未来演其他角色。 为了调用服务B,我使用Akka HTTP客户端 Http.get(actorSystem).singleRequest(HttpRequest.create() .withUri("http://127.

我有一个服务(我们称之为服务a),它使用Akka服务器HTTP来处理传入的请求。 我还有第三方应用程序(服务B),它提供了几个web服务。 服务A的目的是转换客户端请求,调用服务B的一个或多个web服务,合并/转换结果并将其服务回客户端

我用演员演某些角色,而用未来演其他角色。 为了调用服务B,我使用Akka HTTP客户端

Http.get(actorSystem).singleRequest(HttpRequest.create()
        .withUri("http://127.0.0.1:8082/test"), materializer)
        .onComplete(...)
问题是,每个服务a请求都会创建一个新的流,如果存在多个并发连接,则会导致
akka.stream.OverflowStrategy$Fail$bufferoverflowsexception:超出配置的最大打开请求值[32]错误

我已经问了这个问题,并得到了使用单个流的建议

虽然它适用于来自单个位置的一批请求,但我不知道如何使用来自所有并发请求处理程序的单个流


正确的“Akka方法”是什么?

您只需在服务a代码中设置a到服务B即可。这将为您提供一个
,该流可以添加到您的服务a streams中,以使用连接池(而不是每个流的新连接)将请求从a发送到B。从文件中:

与连接级客户端API不同,主机级API 使您不必手动管理单个HTTP连接。信息技术 自动管理一个可配置的连接池 特定目标端点(即主机/端口组合)

此流在不同流中的每个具体化都将从这个底层连接池中提取:

获取到给定目标的连接池的最佳方法 端点是Http.get(system.cachedHostConnectionPool(…)方法, 它返回可“烘焙”到应用程序级别的
流
流设置。此流也称为“池客户端流”


下面是Java版本的

最终流程<
一对
一对
未使用>流量=
get(actorSystem).superpol(materializer);
最终SourceQueue=源。
队列(缓冲区大小,OverflowStrategy.dropNew())
.通过(流量)
.toMat(Sink.foreach(p->p.second().complete(p.first())),Keep.left())
.run(物化器);
...
公共CompletionStage请求(HttpRequest请求){
调试(“发出请求{}”,请求);
允诺,许诺,许诺;
返回队列.offer(Pair.create(请求,承诺))
.然后组合(缓冲->{
if(QueueOfferResult.Enqueued$的缓冲实例){
返回futurecoverters.toJava(promise.future())
。然后应用(响应->{
if(log.isDebugEnabled()){
debug(“获取响应{}{}”、resp.status()、resp.getHeaders());
}
返回响应;
});
}否则{
错误(“无法缓冲请求{}”,请求);
返回CompletableFuture.completedFuture(HttpResponse.create().withStatus(StatusCodes.SERVICE_UNAVAILABLE));
}
});
}

我认为您可以使用
Source.queue
来缓冲您的请求。下面的代码假设您需要从第三方服务获得答案,因此非常欢迎您将来使用[HttpResponse]
。通过这种方式,您还可以提供一种溢出策略来防止资源不足

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.stream.scaladsl.{Keep, Sink, Source}
import akka.stream.{ActorMaterializer, OverflowStrategy}

import scala.concurrent.duration._
import scala.concurrent.{Await, Future, Promise}
import scala.util.{Failure, Success}

import scala.concurrent.ExecutionContext.Implicits.global

implicit val system = ActorSystem("main")
implicit val materializer = ActorMaterializer()
val pool = Http().cachedHostConnectionPool[Promise[HttpResponse]](host = "google.com", port = 80)
val queue = Source.queue[(HttpRequest, Promise[HttpResponse])](10, OverflowStrategy.dropNew)
  .via(pool)
  .toMat(Sink.foreach({
    case ((Success(resp), p)) => p.success(resp)
    case ((Failure(e), p)) => p.failure(e)
  }))(Keep.left)
  .run
val promise = Promise[HttpResponse]
val request = HttpRequest(uri = "/") -> promise

val response = queue.offer(request).flatMap(buffered => {
  if (buffered) promise.future
  else Future.failed(new RuntimeException())
})

Await.ready(response, 3 seconds)

(从my复制的代码)

不,它不起作用,我得到akka.stream.OverflowStrategy$Fail$bufferOverflowsException:超过配置的最大打开请求值[4]。这是我的代码@relgames,我想你需要重构一下你的代码。for循环中不应存在Source.single。相反,for循环应该是流的一部分。以scala为例:
Source(1到100).map(i=>(HttpRequest.create(“/test”),i).via(flow)
…这防止了100个流的具体化,而是使用单个流。服务a使用HTTP DSL处理HTTP请求。然后处理程序使用HTTP客户端API调用服务B,并将结果转发回请求者。因此,在实际程序中没有for循环,而是来自外部客户端的多个请求。I w我最初的问题就是:如何使用单流(和单物化器?)来自多个线程/服务的时间分布。@relgames这个问题解决了吗?我现在也有这个问题。提前谢谢。@tiago是的,检查这个答案很好,谢谢!我实际上在gitter上联系了开发人员,还得到了使用Source.queue和promises的建议。但是我还没有时间尝试。用你的代码,它会的更简单一点!@khiramatsu您有Java示例吗?此解决方案已添加到。我只想添加一点,即当您使用
cachedHostConnectionPool
时,不要忘记配置
akka.http.host connection pool
的设置,例如
max open requests
max connections
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.stream.scaladsl.{Keep, Sink, Source}
import akka.stream.{ActorMaterializer, OverflowStrategy}

import scala.concurrent.duration._
import scala.concurrent.{Await, Future, Promise}
import scala.util.{Failure, Success}

import scala.concurrent.ExecutionContext.Implicits.global

implicit val system = ActorSystem("main")
implicit val materializer = ActorMaterializer()
val pool = Http().cachedHostConnectionPool[Promise[HttpResponse]](host = "google.com", port = 80)
val queue = Source.queue[(HttpRequest, Promise[HttpResponse])](10, OverflowStrategy.dropNew)
  .via(pool)
  .toMat(Sink.foreach({
    case ((Success(resp), p)) => p.success(resp)
    case ((Failure(e), p)) => p.failure(e)
  }))(Keep.left)
  .run
val promise = Promise[HttpResponse]
val request = HttpRequest(uri = "/") -> promise

val response = queue.offer(request).flatMap(buffered => {
  if (buffered) promise.future
  else Future.failed(new RuntimeException())
})

Await.ready(response, 3 seconds)