Yesod脚手架网站缓慢释放数据库池连接

Tet*_*igi 6 haskell yesod

UPDATE

我已经通过脚手架创建的实际项目简化了演示 - 您可以在这里查看:https://github.com/tetigi/yesod-bug-test

按照README设置repo并复制问题!谢谢 :)

原始邮政

我最近一直在尝试使用yesod创建一个简单的网站 - 在一个特定的处理程序中,它会进行一些runDB调用(选择并将一些值插入到~200项DB中).但是,在中等负载上,例如在浏览器中快速重新加载页面,页面开始挂起.

做一些调试,我发现似乎yes应用程序没有及时释放与数据库池的连接,最终等待它们发布.为了解决这个问题,我发现了以下其他事情:

  • 将数据库池减少到2只会在几次点击后冻结
  • 单击约5秒后,默认值(10)冻结
  • 将数据库池增加到100会给我一个更长的点击时间,最多可以快速点击大约10-15秒
  • 无论我使用的是postgres还是sqlite,问题都是一样的
  • 在postgres中,有可能看到'COMMIT'交易随着时间的推移而堆积起来
  • 随着时间的推移,这些交易最终会消失,网站将再次响应

这里有什么我想念的吗?网页没有做任何复杂的事情,因为下面的代码段会显示.有任何想法吗?目前,该网站将无法用于多个用户,直到我找到解决方法!

我正在使用标准的scaffolded yesod应用程序堆栈,如文档中所建议的那样.

干杯!

卢克

示例处理程序代码(删节)

getCompareR :: Handler Html
getCompareR = do

    -- Get all entities from the db. Throws error if < 2 elems in the DB.
    entities <- fmap (\xs -> assert (length xs >= 2) xs) $ runDB $ selectList [] []

    -- Pick an entity at random
    Entity _ thisThingEntity <- liftIO $ runRVar (choice entities) DevRandom

    -- Pull out everything NOT the thing we just picked
    otherEntities <- runDB $ selectList [ComparisonHash !=. (comparisonHash thisThingEntity)] []

    -- Pick one at random
    Entity _ thatThingEntity <- liftIO $ runRVar (choice otherEntities) DevRandom

    -- Some stuff including some inserts
    -- ...
    -- ...

    runDB $ sequence [update thisId [ComparisonElo =. thisElo], update thatId [ComparisonElo =. thatElo]]

    -- Start laying out the webpage
    defaultLayout $ do
        -- Fill in the rest with compare.hamlet
        $(widgetFile "compare")
Run Code Online (Sandbox Code Playgroud)

Tet*_*igi 3

问题出在 Data.Random 中 - 将调用替换choice为以下内容:

import System.Random (randomRIO)

...

 -- Pick an entity at random
randomInt1 <- liftIO $ randomRIO (0, length entities -1) 
let Entity _ thisThingEntity = entities !! randomInt1
Run Code Online (Sandbox Code Playgroud)

修复了所有问题,我们不再放慢速度。不太清楚为什么 Data.Random 会这样做,但至少现在它可以工作了!

另一个值得注意的有趣的事情 - 这个问题不存在于 Mac OS X 上,只存在于 Linux 版本上(我们尝试过 CentOS、Arch、Ubuntu)