Slick 2.1 / 3 执行上下文使用的最佳实践
Best practice for Slick 2.1 / 3 execution context usage
我们使用 Slick (2.1.0) 和 Spray-io (1.3.3)。目前我们面临一个问题,因为我们对访问同一数据库的 Spray HTTP API 部分和后台 运行 作业使用相同的执行上下文。所有数据库/阻塞调用都使用相同的 scala.concurrent.ExecutionContext.global 执行上下文包装在 futures 中。
当后台作业开始执行繁重的工作时,它们将消耗所有可用线程,这将导致 API 端超时,因为它们没有任何可用线程来处理 API 工作。
显而易见的解决方案是对两个部分使用不同的执行上下文,总线程数不高于配置的数据库连接池 (HikariCP)。 (正如这里的部分建议 https://www.playframework.com/documentation/2.1.0/ThreadPools#Many-specific-thread-pools)但是这样的设置如何与执行上下文绑定到数据库配置本身的 Slick 3 一起工作?
Slick3 带有自己的执行上下文和线程数 configurable.You 可以调整所有连接池设置,例如 (MySQL):
dev-dbconf={
dataSourceClass = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
numThreads = 10 //for execution context
maxConnections = 10
minConnections = 5
connectionTimeout = 10000
initializationFailFast = false
properties {
user = "root"
password = "root"
databaseName = "db_name"
serverName = "localhost"
}
}
在此配置中,您可以根据需要更改线程数。
我想建议您从未将 "scala.concurrent.ExecutionContext.global" 用于 IO。因为默认的ExecutionContext自带fork-join线程池,不利于IO.You 可以为IO创建自己的线程池:
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executors
object MyExecutionContext {
private val concorrency = Runtime.getRuntime.availableProcessors()
private val factor = 3 // get from configuration file
private val noOfThread = concorrency * factor
implicit val ioThreadPool: ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(noOfThread))
}
// Use this execution context for IO instead of scala execution context.
import MyExecutionContext.ioThreadPool
Future{
// your blocking IO code
}
您可以根据需要更改noOfThread。如果您根据机器中的处理器数量设置线程数,那就太好了。
更多信息,您可以查看Best Practices for Using Slick on Production
和 Slick Doc.
我们使用 Slick (2.1.0) 和 Spray-io (1.3.3)。目前我们面临一个问题,因为我们对访问同一数据库的 Spray HTTP API 部分和后台 运行 作业使用相同的执行上下文。所有数据库/阻塞调用都使用相同的 scala.concurrent.ExecutionContext.global 执行上下文包装在 futures 中。
当后台作业开始执行繁重的工作时,它们将消耗所有可用线程,这将导致 API 端超时,因为它们没有任何可用线程来处理 API 工作。 显而易见的解决方案是对两个部分使用不同的执行上下文,总线程数不高于配置的数据库连接池 (HikariCP)。 (正如这里的部分建议 https://www.playframework.com/documentation/2.1.0/ThreadPools#Many-specific-thread-pools)但是这样的设置如何与执行上下文绑定到数据库配置本身的 Slick 3 一起工作?
Slick3 带有自己的执行上下文和线程数 configurable.You 可以调整所有连接池设置,例如 (MySQL):
dev-dbconf={
dataSourceClass = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
numThreads = 10 //for execution context
maxConnections = 10
minConnections = 5
connectionTimeout = 10000
initializationFailFast = false
properties {
user = "root"
password = "root"
databaseName = "db_name"
serverName = "localhost"
}
}
在此配置中,您可以根据需要更改线程数。 我想建议您从未将 "scala.concurrent.ExecutionContext.global" 用于 IO。因为默认的ExecutionContext自带fork-join线程池,不利于IO.You 可以为IO创建自己的线程池:
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executors
object MyExecutionContext {
private val concorrency = Runtime.getRuntime.availableProcessors()
private val factor = 3 // get from configuration file
private val noOfThread = concorrency * factor
implicit val ioThreadPool: ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(noOfThread))
}
// Use this execution context for IO instead of scala execution context.
import MyExecutionContext.ioThreadPool
Future{
// your blocking IO code
}
您可以根据需要更改noOfThread。如果您根据机器中的处理器数量设置线程数,那就太好了。
更多信息,您可以查看Best Practices for Using Slick on Production 和 Slick Doc.