我有一个简单的Akka HTTP应用程序,用于websocket。我的请求处理程序具有阻塞调用(例如JDBC)。因此,我需要使用一些固定大小的线程池来处理此类代码。
因此,据我了解,我应该使用 application.conf (像这样- https://github.com/mkuthan/example-akka-http/blob/master/src/main/resources/application.conf)。但是我不知道如何使用固定的固定线程配置自定义线程池。
运行应用程序并进行线程转储时,我看到两个线程名称:
我不明白,这些线程池是什么。
我尝试设置默认线程池,如下所示:
akka {
actor {
default-dispatcher {
type = Dispatcher
executor = "thread-pool-executor"
thread-pool-executor {
fixed-pool-size = 40
}
}
}
}
它非常奇怪:
答案 0 :(得分:1)
您可能启动了两个名称分别为akka-system-akka
和Routes-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
}
}
通常,将阻止执行隔离到单独的执行上下文中,您可以专门为这种类型的阻止操作进行配置。由于执行任务的类型受您的限制和控制,因此更容易微调此类方法。