亚马逊ec2中pika-rabbitmq的心跳间隔良好

时间:2013-02-22 02:10:39

标签: python rabbitmq heartbeat pika

我正在使用最新的pika库(0.9.9+)用于rabbitmq。我对rabbitmq和pika的用法如下:

  1. 我作为工人长期执行任务(约5分钟)。这些任务接受了来自rabbitmq的请求。请求很少发生,即请求之间有很长的空闲时间。
  2. 我之前遇到的问题与空闲连接有关(由于空闲连接导致连接关闭)。所以,我已经在pika中启用了心跳。
  3. 现在选择心跳是一个问题。 Pika似乎是一个单线程库,其中心跳接收和确认恰好在请求时间帧之间完成。
  4. 因此,如果心跳间隔设置为小于回调函数用于执行长时间运行计算的时间,则服务器不会收到任何心跳确认并关闭连接。
  5. 因此,我假设最小心跳间隔应该是阻塞连接中回调函数的最大计算时间。
  6. 对于亚马逊ec2来说,防止它关闭空闲连接有什么好的心跳值?

    另外,有些人建议使用rabbitmq keepalive(或libkeepalive)来维护tcp连接。我认为在tcp层管理心跳要好得多,因为应用程序不需要管理它们。这是真的吗?与RMQ心跳相比,keepalive是一种好方法吗?

    我看到有人建议使用多个线程并为长时间运行的任务排队。但这是长期运行任务的唯一选择吗?非常令人失望的是,必须在此场景中使用另一个队列。

    提前谢谢你。我想我已经详细说明了这个问题。如果我能提供更多细节,请告诉我。

1 个答案:

答案 0 :(得分:3)

如果你不喜欢使用鼠兔,这thread帮助我实现了你想用kombu做的事情:

#!/usr/bin/env python
import time, logging, weakref, eventlet
from kombu import Connection, Exchange, Queue
from kombu.utils.debug import setup_logging
from kombu.common import eventloop
from eventlet import spawn_after

eventlet.monkey_patch()

log_format = ('%(levelname) -10s %(asctime)s %(name) -30s %(funcName) '
              '-35s %(lineno) -5d: %(message)s')
logging.basicConfig(level=logging.INFO, format=log_format)
logger = logging.getLogger('job_worker')
logger.setLevel(logging.INFO)


def long_running_function(body):
    time.sleep(300)

def job_worker(body, message):
    long_running_function(body)
    message.ack()

def monitor_heartbeats(connection, rate=2):
    """Function to send heartbeat checks to RabbitMQ. This keeps the
       connection alive over long-running processes."""
    if not connection.heartbeat:
        logger.info("No heartbeat set for connection: %s" % connection.heartbeat)
        return
    interval = connection.heartbeat
    cref = weakref.ref(connection)
    logger.info("Starting heartbeat monitor.")

    def heartbeat_check():
        conn = cref()
        if conn is not None and conn.connected:
            conn.heartbeat_check(rate=rate)
            logger.info("Ran heartbeat check.")
            spawn_after(interval, heartbeat_check)
    return spawn_after(interval, heartbeat_check)

def main():
    setup_logging(loglevel='INFO')

    # process for heartbeat monitor
    p = None

    try:
        with Connection('amqp://guest:guest@localhost:5672//', heartbeat=300) as conn:
            conn.ensure_connection()
            monitor_heartbeats(conn)
            queue = Queue('job_queue',
                          Exchange('job_queue', type='direct'),
                          routing_key='job_queue')
            logger.info("Starting worker.")
            with conn.Consumer(queue, callbacks=[job_worker]) as consumer:
                consumer.qos(prefetch_count=1)
                for _ in eventloop(conn, timeout=1, ignore_timeouts=True):
                    pass
    except KeyboardInterrupt:
        logger.info("Worker was shut down.")

if __name__ == "__main__":
    main()

我删除了我的域特定代码,但基本上这是我使用的框架。