scala – 为什么下面的代码泄漏了Slick数据库集合?
发布时间:2020-12-16 18:04:19 所属栏目:安全 来源:网络整理
导读:我在play的Action下编写了以下包装器,它将使用一个同时接受会话和请求的函数.这是第一个版本: def ActionWithSession[A](bp: BodyParser[A])(f: Session = Request[A] = Result): Action[A] = Action(bp) { db.withSession { session: DbSession = request
我在play的Action下编写了以下包装器,它将使用一个同时接受会话和请求的函数.这是第一个版本:
def ActionWithSession[A](bp: BodyParser[A])(f: Session => Request[A] => Result): Action[A] = Action(bp) { db.withSession { session: DbSession => request => f(session)(request) } } 此版本运行良好(正确的结果返回到浏览器),但每次调用都会泄漏数据库连接.几次调用后,我开始遇到以下异常: java.sql.SQLException: Timed out waiting for a free available connection. 当我将其更改为以下版本时(通过在Action之后移动请求=>,连接泄漏消失,并且它可以正常工作. def ActionWithSession[A](bp: BodyParser[A])(f: Session => Request[A] => Result): Action[A] = Action(bp) { request => db.withSession { session: DbSession => f(session)(request) } } 为什么导致连接泄漏的第一个版本,以及第二个版本如何修复它? 解决方法
代码的第一个版本不应该工作.您不应该从withSession范围返回任何包含Session对象引用的内容.在这里你返回一个包含这样一个引用的闭包.稍后通过Play调用闭包时,withSession作用域已经关闭且Session对象无效.不可否认,在闭包中泄漏Session对象非常容易(并且将来会被Slick捕获).
这就是为什么它似乎首先工作,但泄漏Connection:Session对象懒惰地获取连接. withSession块返回(或关闭)块结尾处的连接(如果已获取).当您从块中泄漏未使用的Session对象并在块结束后第一次使用它时,它仍然懒惰地打开连接,但没有自动关闭它.我们不久前认识到这是一种不受欢迎的行为,但尚未解决.我们想到的修复方法是,一旦调用了.close方法,就不允许Session对象获取连接.在您的情况下,这将导致异常而不是泄漏连接. 见https://github.com/slick/slick/pull/107 正确的代码确实是你发布的第二个版本,返回的闭包的主体包含整个withSession块,而不仅仅是它的结果. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |