如何为Akka HTTP配置特定的调度程序?

时间:2019-02-11 20:30:24

标签: multithreading scala akka threadpool akka-http

我有一个简单的Akka HTTP应用程序,用于websocket。我的请求处理程序具有阻塞调用(例如JDBC)。因此,我需要使用一些固定大小的线程池来处理此类代码。

因此,据我了解,我应该使用 application.conf (像这样- https://github.com/mkuthan/example-akka-http/blob/master/src/main/resources/application.conf)。但是我不知道如何使用固定的固定线程配置自定义线程池。

运行应用程序并进行线程转储时,我看到两个线程名称:

  • akka-system-akka.actor.default-dispatcher-62
  • Routes-akka.actor.default-dispatcher-79

我不明白,这些线程池是什么。

我尝试设置默认线程池,如下所示:

akka {
  actor {
    default-dispatcher {
      type = Dispatcher
      executor = "thread-pool-executor"
      thread-pool-executor {
        fixed-pool-size = 40
      }
    }
  }
}

它非常奇怪:

1 个答案:

答案 0 :(得分:1)

您可能启动了两个名称分别为akka-system-akkaRoutes-akka的两个单独的ActorSystem,因为在日志中看到了两种类型的线程名称。

thread-pool-executor是由Java运行时定义的ThreadPoolExecutor,它不是FixedThreadPool。

  

ThreadPoolExecutor将自动调整池大小(请参阅   根据corePoolSize设置的界限(请参见getPoolSize())(请参见   getCorePoolSize()和maximumPoolSize(请参见getMaximumPoolSize())。   在方法execute(Runnable)中提交新任务时,更少   当corePoolSize线程正在运行时,将创建一个新线程来   处理请求,即使其他工作线程处于空闲状态也是如此。如果有   大于corePoolSize但小于maximumPoolSize线程   运行时,仅当队列已满时才创建新线程。通过   设置corePoolSize和maximumPoolSize相同,则创建一个   固定大小的线程池。通过将maximumPoolSize设置为本质上   无限值(例如Integer.MAX_VALUE),则允许池   容纳任意数量的并发任务。最典型的是   核心池大小和最大池大小仅在构造时设置,但是它们   也可以使用setCorePoolSize(int)和   setMaximumPoolSize(int)。

因此,您可以看到它以小于定义的大小开始,并根据传入的任务增加了线程数。

阅读Keep-alive times的部分,其中说明了如何终止线程。

出现问题:

请勿覆盖default-dispatcher,因为akka将其用于其他目的,例如,将要执行的消息传递给所有参与者,这很容易配置错误。而且,最重要的是,不要在默认调度程序上运行阻止任务(有关更多详细信息,请阅读akka docs)。而是引入一个单独的调度程序并在那里执行阻塞代码。

这里是一个示例,如何使用普通的http请求(抱歉,我之前没有使用过Web套接字)

  val asyncHandler: HttpRequest => Future[HttpResponse] = { req =>
    val blockingExecutionContext = system.dispatchers.lookup("blocking-dispatcher")
    Future {
      // blocking call 
      HttpRespone(???)
    }(blockingExecutionContext) // this can be passed implicitly too
  }
  Http().bindAndHandleAsync(asyncHandler, "localhost")

blocking-dispatcher必须在application.conf中进行配置,类似于对default-dispatcher进行的配置,但是它是在配置文件的根目录中定义的。

blocking-dispatcher {
  type = Dispatcher
  executor = "thread-pool-executor"
  thread-pool-executor {
    core-pool-size-min = 2
    core-pool-size-factor = 2.0
    core-pool-size-max = 10
  }
}

通常,将阻止执行隔离到单独的执行上下文中,您可以专门为这种类型的阻止操作进行配置。由于执行任务的类型受您的限制和控制,因此更容易微调此类方法。