考虑最简单的scotty应用程序:
{-# LANGUAGE OverloadedStrings #-} import Web.Scotty import Data.Monoid (mconcat) main = scotty 3000 $ do get "/:word" $ do beam <- param "word" html $ mconcat ["Scotty, ", beam, " me up!
"]
我将此代码放入app.hs
并使用GHC进行编译.我用它来运行它./app
.简单.
当人们访问该网站时会发生什么?它只是一个./app
正在运行的.每当每个用户触发get "/:word" $ do
一行时,是否在同一个应用程序中创建了新的线程?有多少这样的线程可以存在?千?万?
运行./app
后显示消息Setting phasers to stun... (port 3000) (ctrl-c to quit)
.但它没有显示更多.它不会输出传入的Web请求.我该怎么做呢?这对于记录目的很有用.
shang.. 12
假设您正在使用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 ["Scotty, ", beam, " me up!
"]
Zeta.. 9
1.当人们访问该网站时会发生什么?它只有一个./app正在运行.每当每个用户触发get"/:word"$ do行时,是否在同一个应用程序中创建了新的线程?有多少这样的线程可以存在?千?万?
Scotty是围绕warp构建的,但可以使用任何其他实现Web应用程序接口(WAI)的库.创建一个新的轻量级线程forkIOUnmasked
(隐藏在fork
模块中Network.Wai.Handler.Warp.Run
).你可以有很多这样的:
并发是"轻量级",这意味着线程创建和上下文切换开销都非常低.Haskell线程的调度在Haskell运行时系统内部完成,并且不使用任何操作系统提供的线程包.(资源)
这是nginx和warp之间的性能比较,其中还包括有关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 ["Scotty, ", beam, " me up!
"]
但是,请记住,当您真正期望每秒一万个请求时,记录到终端可能不是一个好主意.