我想为我的webapp实现'graceful shutdown'命令(而不是我的第一直觉,就是要求人们杀死进程)
我的前两次尝试包括
liftIO exitSuccess
E.yield (responseLBS statusOK [G.contentType "text/plain"] "") E.EOF
两者都只是愉快地将结果返回给客户并继续收听。应用程序可以做什么来杀死服务器?这甚至是一件合理的事情吗?
我承认我对iteratee没有很强的理解,只知道我可以消耗我的输入并且Iteratee是一个MonadIO实例。
答案 0 :(得分:11)
exitImmediately
。拆除过程的最快方法之一,也非常讨厌调试。我不相信终结者/括号/最后一个块会在下降的过程中被调用,具体取决于你的应用程序它可能会破坏状态。Warp.run
不会捕获异常,因此这可以通过允许主线程(以及仅主线程)上的默认异常处理程序来终止进程。正如其他人所说,使用MVar可能是最好的选择。为了完整起见,我把其他人包括在内,但他们确实有自己的位置。 throwTo
在基础库中有点使用,我使用了一些使用等效于exitImmediately
:exit()
的C的应用程序,虽然我没有遇到任何Haskell应用程序使用这种方法。
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Control.Concurrent (MVar, ThreadId, forkIO, myThreadId, newEmptyMVar, putMVar, takeMVar)
import Control.Exception (Exception, throwTo)
import Control.Monad.Trans (liftIO)
import Data.ByteString (ByteString)
import Data.Data (Data, Typeable)
import Data.Enumerator (Iteratee)
import Network.HTTP.Types
import Network.Wai as Wai
import Network.Wai.Handler.Warp as Warp
import System.Exit (ExitCode (ExitSuccess))
import System.Posix.Process (exitImmediately)
data Shutdown = Shutdown deriving (Data, Typeable, Show)
instance Exception Shutdown
app :: ThreadId -> MVar () -> Request -> Iteratee ByteString IO Response
app mainThread shutdownMVar Request{pathInfo = pathInfo} = do
liftIO $ case pathInfo of
["shutdownByThrowing"] -> throwTo mainThread Shutdown
["shutdownByMVar"] -> putMVar shutdownMVar ()
["shutdownByExit"] -> exitImmediately ExitSuccess
_ -> return ()
return $ responseLBS statusOK [headerContentType "text/plain"] "ok"
main :: IO ()
main = do
mainThread <- myThreadId
shutdownMVar <- newEmptyMVar
forkIO $ Warp.run 3000 (app mainThread shutdownMVar)
takeMVar shutdownMVar