Python 3 日志记录:QueueListener + SocketHandler,第一次清空队列非常缓慢

3
在我的Python 3代码中,我设置了一个类似这样的日志记录器:
class TmpQListener(logging.handlers.QueueListener):
    def dequeue(self, block):
        print('QSIZE : ' + str(self.queue.qsize())) # only change to the QueueListener
        return self.queue.get(block)

log_q = queue.Queue(-1) # unlimited size
logger = logging.getLogger('TestLogger')
socket_handler = logging.handlers.SocketHandler('localhost', 1337)
q_handler = logging.handlers.QueueHandler(log_q)
q_listener = TmpQListener(log_q, socket_handler)
logger.addHandler(q_handler)
q_listener.start()

当我运行我的程序(接收日志消息的服务器已经启动运行),队列会很快填满。每添加20-30条消息,只有2-3条消息从队列中移除(即发送)。 我的内存逐渐填满,使程序变得越来越慢,直到我的RAM基本上被填满为止,此时程序变得非常缓慢,并尝试一次性清空整个队列(即发送所有内容)。如果由于任何原因它无法快速清空所有内容,则会继续变慢,直到程序完成。如果它成功清空队列并发送大约几GB的LogRecords,那么它将再次加速并按照我期望的方式工作,这意味着从此时起,它将在将消息添加到队列时立即发送所有消息而不影响性能。
由于这可能不是预期的行为,我认为我做错了什么。
值得一提的是,我正在使用LogRecord的'extra' argument发送列表以及我的某些LogRecords。这些日志记录调用看起来像这样:
logger.info("PROX_MARKER", extra={'vector': [some_list]})

其中some_list是一个包含数千个双精度值的列表,使得LogRecord非常大。我知道这并不是logging调用的本意,但是我认为如果程序成功清除了初始的消息积压,那么这并不是问题。

我查看了SocketHandler/QueueHandler/QueueListener的代码,但没有找到任何可以解释这种行为的内容。在我的原始代码中,我使用自定义的SocketHandler序列化日志记录。我已将其替换为默认的SocketHandler,但结果仍然相同。现在我想不出其他的办法了。

非常感谢任何有关如何解决此问题的提示。

1个回答

0

我的帖子可能有点晚了。从你的问题来看,队列容量被设置为无限制,并且内存消耗不断增加,那么可能是队列监听不能像日志生产者那样快速清除。这可能是由于网络连接缓慢,远程套接字端无法快速清除日志消息。

可能的解决方案包括:

  1. 设置合理的队列限制并监视未处理的队列大小。对于您的情况,请尝试获取一个合理的值并将您的队列设置为此数字,而不是无限制。

  2. 检查日志消息生成器,注释掉不必要的日志消息。监视未处理的队列大小并根据此调整大小。

  3. 可以考虑使用MemoryHandler。它可用于缓冲相关的日志消息,并在末尾出现错误时一次性发送。

  4. 将调试级别设置为较高的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接