每个请求的 Slick 连接池

Slick Connection Pool on per requests

如何使用 slick 连接池?
例如:
使用此配置:

database {
  dataSourceClass = org.postgresql.ds.PGSimpleDataSource
  driver = org.postgresql.Driver
  properties = {
    url = "jdbc:postgresql://172.17.0.2/sampleDB"
    user = "user"
    password = "userpass"
  }
  minConnections = 10
  maxConnections = 20
  numThreads = 10
}

我只有一个客户端,这个客户端使用 Web 浏览器请求从 API 获取所有人。
现在 slick 生成 10 个数据库连接。
第二步客户端刷新浏览器并在不使用以前的连接的情况下 slick 生成新的 10 个数据库连接。
然后在浏览器中重新刷新并 slick 生成另外 10 个数据库连接。 (现在我只有一个客户端在数据库上有大约 30 个连接!)

为什么?这正常吗?
为什么 maxConnections 不起作用?
我必须在请求后关闭连接吗?
或者忘记一些配置?

更新
这是我的样本 API :

trait PersonsApi extends DatabaseConfig with JsonMapper {

  val getAllPersons = (path("persons") & get) {
    complete(db.run(PersonDao.findAll))
  }

  val getPersonById = (path("persons" / IntNumber) & get) {
    num => complete(db.run(PersonDao.findById(num)))
  }


  val personsApi =
    getAllPersons ~ 
    getPersonById
}     

这是我的示例实体 class(DAO 模式):

class PersonTable(tag: Tag) extends Table[Person](tag, "persons") {
  def id = column[Long]("id", O.AutoInc, O.PrimaryKey)

  def name = column[String]("name")

  def family = column[String]("family")

  override def * : ProvenShape[Person] = (id.?, name, family) <> (Person.tupled, Person.unapply)
}


object PersonDao extends BaseDao {
  def findAll = personTable.result

  def findById(id: Long) = personTable.filter(_.id === id).result

}

此 DatabaseConfig 接口:

trait DatabaseConfig extends Config {
  val driver = slick.driver.PostgresDriver

  import driver.api._

  def db = Database.forConfig("database")

}

注意 : 我不使用 play framework .

您的配置似乎没问题。如果没有来自您的应用程序的更多代码示例,这是不可能的,但我敢打赌,您正在为您的应用程序的每个请求创建您的数据库。

只需确保此代码:

Database.forConfig("database")

可能被执行一次:

  • 将其作为 Singleton 注入的依赖项或

  • 通过使用 play-slick 并且它是处理 Slick 配置的方式(如果您使用的是 Play ,这又不可能从您的问题,虽然我假设它是你提到的网络请求)。

编辑(问题更新后): 我们有答案。每次你调用 db 方法新的 Database 对象(与连接池一起创建)。只需按照我上面的建议移动它(每个应用程序生命周期创建一次)。最简单的方法(不一定是最好的方法)是更改此行:

def db = Database.forConfig("database")

对此:

lazy val db = Database.forConfig("database")

以上将立即解决您的问题(假设您的应用程序中只创建了一个 PersonsApi 实例。

其他解决方案(也许更好)是创建这样的东西:

object DatabaseConfig extends Config {
  val driver = slick.driver.PostgresDriver

  import driver.api._

  lazy val db = Database.forConfig("database")
}

然后将您的 API 更改为:

trait PersonsApi extends JsonMapper {

  val getAllPersons = (path("persons") & get) {
    complete(DatabaseConfig.db.run(PersonDao.findAll))
  }

  val getPersonById = (path("persons" / IntNumber) & get) {
    num => complete(DatabaseConfig.db.run(PersonDao.findById(num)))
  }


  val personsApi =
    getAllPersons ~ 
    getPersonById
}