【发布时间】:2013-11-13 17:14:17
【问题描述】:
我编写了一个小型服务器,它接受作为 POST 请求的注册并通过将它们附加到文件来持久化它们。一旦我将此服务器置于负载状态(我使用具有 50 个并发线程和 10 个重复计数的 Apache JMeter,并且帖子包含一个包含约 7k 文本数据的字段),我就会得到很多“资源繁忙,文件是锁定”错误:
02/Nov/2013:18:07:11 +0100 [Error#yesod-core] registrations.txt: openFile: resource busy (file is locked) @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
这是代码的精简版:
{-# LANGUAGE QuasiQuotes, TemplateHaskell, MultiParamTypeClasses, OverloadedStrings, TypeFamilies #-}
import Yesod
import Text.Hamlet
import Control.Applicative ((<$>), (<*>))
import Control.Monad.IO.Class (liftIO)
import Data.Text (Text, pack, unpack)
import Data.String
import System.IO (withFile, IOMode(..), hPutStrLn)
data Server = Server
data Registration = Registration
{ text :: Text
}
deriving (Show, Read)
mkYesod "Server" [parseRoutes|
/reg RegR POST
|]
instance Yesod Server
instance RenderMessage Server FormMessage where
renderMessage _ _ = defaultFormMessage
postRegR :: Handler Html
postRegR = do
result <- runInputPost $ Registration
<$> ireq textField "text"
liftIO $ saveRegistration result
defaultLayout [whamlet|<p>#{show result}|]
saveRegistration :: Registration -> IO ()
saveRegistration r = withFile "registrations.txt" AppendMode (\h -> hPutStrLn h $ "+" ++ show r)
main :: IO ()
main = warp 8080 Server
我故意在没有-threaded 的情况下编译了代码,操作系统显示只有一个线程在运行。尽管如此,在我看来,请求并未完全序列化,并且在旧请求写入磁盘之前已经处理了新请求。
您能告诉我如何避免错误消息并确保所有请求都得到成功处理吗?性能还不是问题。
【问题讨论】:
标签: haskell file-io concurrency yesod haskell-warp