Python 3 Logging:QueueListener + SocketHandler,第一次清除队列真的很慢

时间:2017-07-17 10:22:07

标签: python performance python-3.x logging

在我的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' arguement发送了一些列表和一些LogRecords。这些日志记录调用如下所示:

logger.info("PROX_MARKER", extra={'vector': [some_list]})

其中some_list是几千个双值的列表,使LogRecord的大小非常大。我意识到这并不完全是日志记录调用的内容,但我不知道这是一个问题,看看它是如何工作完全正常的如果程序设法清除初始值积累消息。

我查看过SocketHandler / QueueHandler / QueueListener的代码,找不到任何可以解释此行为的内容。 在我的原始代码中,我使用自定义SocketHandler来序列化日志记录。我用默认的SocketHandler替换了它,但结果是一样的。现在,我完全没有想法。

非常感谢任何关于如何解决这个问题的提示。

1 个答案:

答案 0 :(得分:0)

我的帖子可能为时已晚。根据您的问题,队列容量设置为无限制,并且内存消耗正在增加,这可能是因为队列侦听无法像日志生成器一样快地清除。可能是由于网络连接速度慢,远程套接字端无法快速清除日志消息。

可能的解决方案是

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

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

  3. 可以考虑使用MemoryHandler。您可以缓存相关的日志消息,如果最后有错误,则一次性发送。

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