使用akka-http

时间:2016-07-06 11:53:44

标签: multithreading scala akka akka-http

不确定这个问题是否适合此问题

我有一个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),即它在不同的线程池上生成并修改Future s到一个由Akka http调度员使用的。我以为这会停止计算和坐下来#34;在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的vanilla目前还不是最好的选择吗?

1 个答案:

答案 0 :(得分:2)

对我而言,这听起来并不是关于管理线程,将繁重的工作分离给您已经完成的单独调度员,而是关于管理实际处理。

为了能够在工作中停止长时间运行的过程,您可能需要将其拆分为较小的块,以便在不再需要时可以在中途中止它。

与actor有一个共同的模式是让一个处理参与者将结果“存储到目前为止”或者将其作为消息发送给自己,这样它就可以对两者之间的“停止工作”消息作出反应,或者可能检查它是否存在已经处理了这么长的时间,它应该中止。触发工作负载的消息可以包含例如允许“客户端”指定它的超时值。

(这与在手动线程和阻止应用程序中正确处理InterruptedExceptionThread.isInterrupted基本相同)