Haskell 守护进程无法从 Redis 中提取 `getAddrInfo`/`Too many open files` 错误

标签 haskell redis daemon

我有一个相对简单的 Haskell 守护进程,它从 Redis 中blpops 东西,并在一个线程中将它们写入 channel ,然后从 channel 中读取它们,并在另一个线程中将它们打印到标准输出。

运行它时,它开始时一切正常,一段时间后,我在 stderr 上得到以下信息:

hogstash: getAddrInfo: does not exist (nodename nor servname provided, or not known)

并在我的 system.log (OSX) 中查看以下内容:

hogstash[11281]: dnssd_clientstub deliver_request: socketpair failed 24 (Too many open files)

我从中推断出我正在以某种方式进行一些无界线程 DNS 查找,但我不明白如何进行,而且我对 Haskell 的熟悉程度不够,无法真正了解如何调试它。

主要程序如下:

import Hogstash.Inputs.Redis
import Hogstash.Event
import Hogstash.Outputs.Stdout

import Control.Concurrent
import Control.Concurrent.BoundedChan
import Control.Monad

main = forever $ do
           channel <- newBoundedChan 10
           forkIO $ do
               connection <- tmpHaxx
               forever $ getEvent connection "logstash:beaver" channel
           forkIO $ forever $ stdout channel

stdout 就是:

module Hogstash.Outputs.Stdout where

import Control.Concurrent.BoundedChan as BC
import Hogstash.Event

stdout :: BoundedChan Event -> IO ()
stdout channel = do 
                     event <- readChan channel
                     putStrLn $ show event

getEvent是:

module Hogstash.Inputs.Redis where

import Database.Redis

import Hogstash.Event

import Control.Concurrent
import Control.Concurrent.BoundedChan as BC
import qualified Data.ByteString.Char8 as BSC


eventFromByteString :: BSC.ByteString -> Event
eventFromByteString _ = Event

listListen key = blpop [key] 0

tmpHaxx = connect defaultConnectInfo -- FIXME Remove this

getEvent :: Connection -> String -> BoundedChan Event -> IO ()

getEvent a b = getEvent' a (BSC.pack b)

getEvent' ci key channel = do
                                fnar <- pullEvent ci key
                                case fnar of
                                    Just e -> BC.writeChan channel e
                                    Nothing -> return ()

pullEvent :: Connection -> BSC.ByteString -> IO (Maybe Event)
pullEvent connection key = do
                                    event_data <- runRedis connection $ listListen key
                                    return (case event_data of
                                        Left a -> Nothing
                                        Right a -> extractEvent a)

extractEvent :: Maybe (a, BSC.ByteString) -> Maybe Event
extractEvent = fmap (eventFromByteString . snd)

谢谢

最佳答案

非常感谢 #haskell 在 Freenode 上的 Kaini:

main 愚蠢地使用 forever 无限期阻塞主线程。这当然意味着永远产生 Redis 和 stdout 线程,从而达到文件打开限制。

重写 main

main = do
           channel <- newBoundedChan 10
           forkIO $ do
               connection <- tmpHaxx
               forever $ getEvent connection "logstash:beaver" channel
           forkIO $ forever $ stdout channel
           forever $ threadDelay 1000 -- Block forever

效果明显更好!

关于Haskell 守护进程无法从 Redis 中提取 `getAddrInfo`/`Too many open files` 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18765463/

相关文章:

haskell - 定义所需的 Fractional Int 实例

java - 使用 Jmeter Redis 数据集从 Redis 获取值(value)

django websockets 无法在 channel 上发送消息

c - 如何在ubuntu中将c程序设置为守护进程?

haskell - ghc-mod 不使用我的 cabal 沙箱。为什么?

Haskell 读取原始键盘输入

Python守护进程

python - 你能在 Python 2.4 中使用 python-daemon 吗?

list - Haskell 在列表和应用函数的列表上迭代每个 2x2 网格

spring - 如何在使用 Redis session 存储的 Spring Boot 应用程序中获取当前主体