对于背景: 我在将日志发送到AWS Cloudwatch时将django与django_rq工作者一起使用(为简洁起见,可能省略了详细信息...)。随机地,从工作人员发出的日志停止将其发送到CloudWatchLogger处理程序。这个CloudWatchLogger被包装在multiprocessing_logging包装器中,我们称之为MPLogger。
在MPLogger的emit()函数中,如果我调用print(self.queue.qsize()),我会看到当故障开始时,qsize永远永久地变大,而self.queue.empty()在_receive()函数中返回True,从而导致CloudWatchLogger的emit()方法再也不会被调用...
您知道什么可能导致此锁定吗? ...或者我该如何调试引起它的原因?谢谢!我将不胜感激任何反馈。下面的代码:
在MPLogger中:
# _receive() is running in a thread, self.sub_handler is CloudWatchLogger
def _receive(self):
while not (self._is_closed and self.queue.empty()):
try:
record = self.queue.get(timeout=0.2)
self.sub_handler.emit(record)
except (KeyboardInterrupt, SystemExit):
raise
except EOFError:
break
except queue.Empty:
pass # This periodically checks if the logger is closed.
except:
traceback.print_exc(file=sys.stderr)
self.queue.close()
self.queue.join_thread()
def emit(self, record):
try:
s = self._format_record(record)
self.queue.put_nowait(record)
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
在CloudWatchLogger中:
def emit(self, message):
cwl_message = dict(timestamp=int(message.created * 1000), message=self.format(message))
if self.stream_name not in self.queues:
# start _batch_sender() in a thread referencing this queue
self.make_queue_and_thread(stream_name)
self.queues[stream_name].put(cwl_message)
# batch_sender() in a thread
def batch_sender(self, my_queue, stream_name, send_interval, max_batch_size, max_batch_count):
msg = None
# See https://boto3.readthedocs.io/en/latest/reference/services/logs.html#CloudWatchLogs.Client.put_log_events
while msg != self.END:
cur_batch = [] if msg is None or msg == self.FLUSH else [msg]
cur_batch_size = sum(size(msg) for msg in cur_batch)
cur_batch_msg_count = len(cur_batch)
cur_batch_deadline = time.time() + send_interval
while True:
try:
msg = my_queue.get(block=True, timeout=max(0, cur_batch_deadline-time.time()))
if size(msg) > max_batch_size:
msg = truncate(msg)
except queue.Empty:
# If the queue is empty, we don't want to reprocess the previous message
msg = None
if msg is None \
or msg == self.END \
or msg == self.FLUSH \
or cur_batch_size + size(msg) > max_batch_size \
or cur_batch_msg_count >= max_batch_count \
or time.time() >= cur_batch_deadline:
self._submit_batch(cur_batch, stream_name)
if msg is not None:
# We don't want to call task_done if the queue was empty and we didn't receive anything new
my_queue.task_done()
break
elif msg:
cur_batch_size += size(msg)
cur_batch_msg_count += 1
cur_batch.append(msg)
my_queue.task_done()