У меня есть следующее приложение Скотти, которое пытается использовать STM для подсчета обслуживаемых вызовов API:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Web.Scotty
import Data.Monoid (mconcat)
import Control.Concurrent.STM
import Control.Monad.IO.Class
main :: IO ()
main = do
counter <- newTVarIO 0
scotty 3000 $
get "/:word" $ do
liftIO $ atomically $ do
counter' <- readTVar counter
writeTVar counter (counter' + 1)
liftIO $ do
counter' <- atomically (readTVar counter)
print counter'
beam <- param "word"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
Я «нагрузочно тестирую» API следующим образом:
ab -c 100 -n 100000 http://127.0.0.1:3000/z
Однако API обслуживает примерно около 16 тысяч запросов, после чего «зависает» — ab
останавливается с ошибкой apr_socket_recv: Operation timed out (60)
.
Я думаю, что неправильно использую STM, но не уверен, что делаю неправильно. Какие-либо предложения?
Быстрая догадка здесь. 16 000 — это количество доступных TCP-портов. Возможно ли, что вы не закрыли ни одного соединения и поэтому у вас закончились открытые порты для ab
?
ага, вот оно! Спасибо! все эти соединения находятся в состоянии TIME_WAIT
. означает ли это, что Скотти неправильно закрывает соединения?
Итак, каково решение?
похоже, что wrk
(вместо ab
) не вызывает этой проблемы.
@firefrorefiddle, я не совсем уверен. Я кликнул, потому что потратил много времени на изучение STM, а не на Скотти. Я знаю, что TCP-порты должны быть закрыты, прежде чем можно будет открыть больше, но как это сделать, вероятно, следует задать в новом вопросе со Скотти в заголовке.
Сколько ЦП использует ваш сервер, когда он «зависает»?