参考以下提及的实施方案:
http://doc.akka.io/docs/akka-http/10.0.5/scala/http/client-side/host-level.html
val poolClientFlow = Http().cachedHostConnectionPool[Promise[HttpResponse]]("akka.io")
val queue =
Source.queue[(HttpRequest, Promise[HttpResponse])](QueueSize, OverflowStrategy.dropNew)
.via(poolClientFlow)
.toMat(Sink.foreach({
case ((Success(resp), p)) => p.success(resp)
case ((Failure(e), p)) => p.failure(e)
}))(Keep.left)
.run()
从多个线程提供队列http请求是否可以安全? 如果不是,那么实施此类要求的最佳方式是什么?或许使用专门的演员?
答案 0 :(得分:2)
不,根据api doc:SourceQueue that current source is materialized to is for single thread usage only.
专门的演员可以正常工作,但是,如果可以的话,使用Source.actorRef
(doc link)代替Source.queue
会更容易。
一般来说,Source.actorRef
的缺点是背压不足,但是当你使用OverflowStrategy.dropNew
时,很明显你没有预料到背压。因此,您可以使用Source.actorRef
获得相同的行为。
答案 1 :(得分:2)
正如@ frederic-a所说,SourceQueue
不是线程安全的解决方案。
也许合适的解决方案是使用MergeHub
(有关详细信息,请参阅docs)。这有效地允许您分两个阶段运行图表。
Sink
实际上是为了分发而设计的,所以这是非常安全的。 根据MergeHub
行为
如果消费者无法跟上,那么所有的生产者都是 backpressured。
下面的代码示例:
val reqSink: Sink[(HttpRequest, Promise[HttpResponse]), NotUsed] =
MergeHub.source[(HttpRequest, Promise[HttpResponse])](perProducerBufferSize = 16)
.via(poolClientFlow)
.toMat(Sink.foreach({
case ((Success(resp), p)) => p.success(resp)
case ((Failure(e), p)) => p.failure(e)
}))(Keep.left)
.run()
// on the user threads
val source: Source[(HttpRequest, Promise[HttpResponse]), NotUsed] = ???
source.runWith(reqSink)