【发布时间】:2016-07-06 11:53:43
【问题描述】:
不确定是否适合这个问题的 stackexchange
我有一个 akka-http 应用程序,它充当一些繁重计算的前端。它处理的请求在处理它们所需的时间上有所不同。有些在一秒钟内完成,有些则需要更多时间。计算是纯异步的,在任何时候都没有Await,我用 Future 完成请求,即:
val spotsJsonF: Future[String] = spotsF.map(spots => DebugFormatter.produceJson(text, spots._1, spots._2, env))
complete(spotsJsonF.map { t => HttpEntity(ContentTypes.`application/json`, t) })
我的要求/假设:
- 我需要最大限度地提高并行性,即不应在重负载下拒绝连接
- 如果服务繁忙,我可以忍受一些(甚至很小的)请求需要更长时间
- 我可以忍受一些超长请求在重负载下超时,只要它们在 HTTP 请求超时完成后不会过多影响并行性。
为此,我为繁重的计算提供了一个单独的执行上下文(即 Scala 的默认 ExecutionContext.global),即它在与 Akka http 调度程序使用的线程池不同的线程池上生成和修改 Futures。我认为这将停止计算“坐在” Akka 的线程上,因此它可以接受更多连接。目前它是 Akka 的默认调度程序(我的 reference.conf 为空):
"default-dispatcher": {
"attempt-teamwork": "on",
"default-executor": {
"fallback": "fork-join-executor"
},
"executor": "default-executor",
"fork-join-executor": {
"parallelism-factor": 3,
"parallelism-max": 64,
"parallelism-min": 8,
"task-peeking-mode": "FIFO"
},
"mailbox-requirement": "",
"shutdown-timeout": "1s",
"thread-pool-executor": {
"allow-core-timeout": "on",
"core-pool-size-factor": 3,
"core-pool-size-max": 64,
"core-pool-size-min": 8,
"fixed-pool-size": "off",
"keep-alive-time": "60s",
"max-pool-size-factor": 3,
"max-pool-size-max": 64,
"max-pool-size-min": 8,
"task-queue-size": -1,
"task-queue-type": "linked"
},
"throughput": 5,
"throughput-deadline-time": "0ms",
"type": "Dispatcher"
},
但是发生的情况是,在 Akka 由于超时而取消请求后,长时间运行的计算会继续执行很长时间。由于内核数量有限,这意味着即使不再需要启动此过载的计算,被拒绝的请求的数量也会开始增加。
显然,我不知道如何正确管理此应用程序中的线程。
满足我的要求的最佳方式是什么?几个线程池 - 好/坏主意?我需要明确取消吗?可能目前使用 Scala 的原版 Future 不是最佳选择?
【问题讨论】:
-
您是否考虑过创建单独的演员,每个资源一个?扩展它应该很容易,将繁重的计算代理到其他节点,并且主节点在这种情况下仅用作路由器。
-
我们不将其用作分布式应用程序,因为它必须在内存中保持非常重 (13G) 的结构,因此我们仅将其部署在大型 EC2 实例上
标签: multithreading scala akka akka-http