考虑最简单的scotty应用程序:
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Data.Monoid (mconcat)
main = scotty 3000 $ do
get "/:word" $ do
beam <- param "word"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
我将此代码放入app.hs
并使用GHC进行编译。我用./app
运行它。简单。
当人们访问该网站时会发生什么?它只有一个./app
正在运行。每当每个用户触发get "/:word" $ do
行时,是否会在同一个应用中创建新主题?有多少这样的线程可以存在?千?一万?
运行./app
后,会显示消息Setting phasers to stun... (port 3000) (ctrl-c to quit)
。但它没有显示更多。它不会输出传入的Web请求。我该怎么做呢?这对于日志记录非常有用。
答案 0 :(得分:11)
假设您正在使用GHC,对scotty服务器的每个请求实际上都会创建一个由GHC运行时调度的“绿色线程”。您可以轻松地同时运行数千个。
Scotty本身不会执行任何请求记录,但由于它是在WAI之上构建的,因此您可以使用为其存在的任何中间件组件,例如RequestLogger
。
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Network.Wai.Middleware.RequestLogger
import Data.Monoid (mconcat)
main = scotty 3000 $ do
middleware logStdoutDev
get "/:word" $ do
beam <- param "word"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
答案 1 :(得分:9)
1。当人们访问该网站时会发生什么?它只有一个./app正在运行。每当每个用户触发get&#34; /:word&#34;时,是否会在同一个应用中创建新线程。 $ do line?有多少这样的线程可以存在?千?一万?
Scotty是围绕warp构建的,但可以使用任何其他实现web application interface (WAI)的库。使用forkIOUnmasked
创建一个新的轻量级线程(隐藏在模块Network.Wai.Handler.Warp.Run
中的fork
中)。您可以许多:
并发是&#34;轻量级&#34;,这意味着线程创建和上下文切换开销都非常低。 Haskell线程的调度是在Haskell运行时系统内部完成的,并没有使用任何操作系统提供的线程包。 (source)
这里是performance comparison between nginx and warp,其中还包含有关扭曲背后的一般概念的信息。
2。运行./app后,它显示消息设置阶段到stun ...(端口3000)(ctrl-c退出)。但它没有显示更多。它不会输出传入的Web请求。我该怎么做呢?这对于日志记录非常有用。
您do
区块的类型是什么?它应该是ScottyM
,因为scotty :: Port -> ScottyM () -> IO ()
。如果ScottyM
是MonadIO
的实例,则可以将liftIO
与putStrLn
(或任何其他IO
操作一起使用)。
现在,ScottyM
实际上是ScottyT
的类型同义词,实际上是MonadIO
的实例。此外,内部monad ActionM
也是ActionT
的类型同义词,也是MonadIO
。因此,记录就像
main = scotty 3000 $ do
liftIO $ putStrLn "incoming request"
get "/:word" $ do
beam <- param "word"
liftIO $ print $ mconcat ["get, word = ", beam]
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
但是,请记住,当您真的希望每秒有一万个请求时,记录到终端可能不是一个好主意。