Yesod 脚手架站点释放数据库池连接缓慢
Yesod scaffolded site slow to release database pool connection
更新
我已使用从脚手架创建的实际项目简化了演示 - 您可以在此处查看:https://github.com/tetigi/yesod-bug-test
按照自述文件设置回购并复制问题!谢谢:)
原版POST
我最近一直在尝试使用 yesod 创建一个简单的网站 - 在一个特定的处理程序中,它进行了几次 runDB 调用(选择一些值并将其插入到约 200 个项目的数据库中)。但是,在中等负载下,例如在浏览器中快速重新加载页面,页面开始挂起。
调试了一下,发现yesod app好像没有及时释放到数据库池的连接,一直在等待释放。为了证实这一点,我发现了以下其他内容:
- 将数据库池减少到 2 后,我只点击了几下就死机了
- 点击约 5 秒后默认 (10) 冻结
- 将 DB 池增加到 100 使我的点击时间更长,快速点击大约需要 10-15 秒
- 无论我使用的是 postgres 还是 sqlite,问题都是一样的
- 在 postgres 中,可以看到 'COMMIT' 事务随时间堆积起来
- 这些交易最终会随着时间的推移消失,网站会再次响应
我在这里遗漏了什么吗?该网页不会做任何复杂的事情,如下面的代码片段所示。有任何想法吗?目前,在我找到解决此问题的方法之前,该网站将无法供多个用户使用!
我正在按照文档中的建议通过堆栈使用标准脚手架 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")
问题出在 Data.Random - 将 choice
调用替换为:
import System.Random (randomRIO)
...
-- Pick an entity at random
randomInt1 <- liftIO $ randomRIO (0, length entities -1)
let Entity _ thisThingEntity = entities !! randomInt1
修复了所有问题,我们不再变慢了。不太确定为什么 Data.Random 这样做,但至少它现在有效!
另一个需要注意的有趣的事情 - Mac OS X 上不存在该问题,仅 Linux 口味(CentOS、Arch、Ubuntu 是我们尝试过的)
更新
我已使用从脚手架创建的实际项目简化了演示 - 您可以在此处查看:https://github.com/tetigi/yesod-bug-test
按照自述文件设置回购并复制问题!谢谢:)
原版POST
我最近一直在尝试使用 yesod 创建一个简单的网站 - 在一个特定的处理程序中,它进行了几次 runDB 调用(选择一些值并将其插入到约 200 个项目的数据库中)。但是,在中等负载下,例如在浏览器中快速重新加载页面,页面开始挂起。
调试了一下,发现yesod app好像没有及时释放到数据库池的连接,一直在等待释放。为了证实这一点,我发现了以下其他内容:
- 将数据库池减少到 2 后,我只点击了几下就死机了
- 点击约 5 秒后默认 (10) 冻结
- 将 DB 池增加到 100 使我的点击时间更长,快速点击大约需要 10-15 秒
- 无论我使用的是 postgres 还是 sqlite,问题都是一样的
- 在 postgres 中,可以看到 'COMMIT' 事务随时间堆积起来
- 这些交易最终会随着时间的推移消失,网站会再次响应
我在这里遗漏了什么吗?该网页不会做任何复杂的事情,如下面的代码片段所示。有任何想法吗?目前,在我找到解决此问题的方法之前,该网站将无法供多个用户使用!
我正在按照文档中的建议通过堆栈使用标准脚手架 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")
问题出在 Data.Random - 将 choice
调用替换为:
import System.Random (randomRIO)
...
-- Pick an entity at random
randomInt1 <- liftIO $ randomRIO (0, length entities -1)
let Entity _ thisThingEntity = entities !! randomInt1
修复了所有问题,我们不再变慢了。不太确定为什么 Data.Random 这样做,但至少它现在有效!
另一个需要注意的有趣的事情 - Mac OS X 上不存在该问题,仅 Linux 口味(CentOS、Arch、Ubuntu 是我们尝试过的)