RabbitMq

  1. 安装
    下载完解压,加入环境变量即可。

     export RABBIT_HOME=/data/rabbitmq
     export PATH=$PATH:RABBIT_HOME/sbin
    
  2. 基本命令

     rabbitmq-server  # 启动rabbitmq,-detached参数可后台运行
     rabbitmqctrl stop
     rabbitmq-plugin enable rabbitmq_management  # 启动图形化管理界面,默认端口号15672
    
  3. AMQP(高级消息队列协议)
    参考:RabbitMQ中文
    AMQP 0-9-1的工作过程如下图:消息(message)被发布者(publisher)发送给交换机(exchange),交换机常常被比喻成邮局或者邮箱。然后交换机将收到的消息根据路由规则分发给绑定的队列(queue)。最后AMQP代理(broker)会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。

    RabbitMq_第1张图片
    image.png

    发布者(publisher)发布消息时可以给消息指定各种消息属性(message meta-data)。有些属性有可能会被消息代理(brokers)使用,然而其他的属性则是完全不透明的,它们只能被接收消息的应用所使用。

    从安全角度考虑,网络是不可靠的,接收消息的应用也有可能在处理消息的时候失败。基于此原因,AMQP模块包含了一个消息确认(message acknowledgements)的概念:当一个消息从队列中投递给消费者后(consumer),消费者会通知一下消息代理(broker),这个可以是自动的也可以由处理消息的应用的开发者执行。当“消息确认”被启用的时候,消息代理不会完全将消息从队列中删除,直到它收到来自消费者的确认回执(acknowledgement)。

  4. 交换机
    交换机拿到一个消息之后将它路由给一个或零个队列。它使用哪种路由算法是由交换机类型和被称作绑定(bindings)的规则所决定的。

    • Name(交换机类型) Default pre-declared names(预声明的默认名称)
    • Direct exchange(直连交换机) (Empty string) and amq.direct
    • Fanout exchange(扇型交换机) amq.fanout
    • Topic exchange(主题交换机) amq.topic
    • Headers exchange(头交换机) amq.match (and amq.headers in RabbitMQ)

    除交换机类型外,在声明交换机时还可以附带许多其他的属性,其中最重要的几个分别是:

    • Name
    • Durability (消息代理重启后,交换机是否还存在)
    • Auto-delete (当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它)
    • Arguments(依赖代理本身)
  5. 绑定
    绑定(Binding)是交换机(exchange)将消息(message)路由给队列(queue)所需遵循的规则。
    打个比方:

    队列(queue)是我们想要去的位于纽约的目的地
    交换机(exchange)是JFK机场
    绑定(binding)就是JFK机场到目的地的路线。能够到达目的地的路线可以是一条或者多条

  6. 消费者
    消息如果只是存储在队列里是没有任何用处的。被应用消费掉,消息的价值才能够体现。在AMQP 0-9-1 模型中,有两种途径可以达到此目的:

    • 将消息投递给应用 ("push API")
    • 应用根据需要主动获取消息 ("pull API")
  7. 消息确认
    消费者应用(Consumer applications) - 用来接受和处理消息的应用 - 在处理消息的时候偶尔会失败或者有时会直接崩溃掉。而且网络原因也有可能引起各种问题。这就给我们出了个难题,AMQP代理在什么时候删除消息才是正确的?AMQP 0-9-1 规范给我们两种建议:

    • 当消息代理(broker)将消息发送给应用后立即删除。(使用AMQP方法:basic.deliver或basic.get-ok)
    • 待应用(application)发送一个确认回执(acknowledgement)后再删除消息。(使用AMQP方法:basic.ack)

    如果一个消费者在尚未发送确认回执的情况下挂掉了,那AMQP代理会将消息重新投递给另一个消费者。如果当时没有可用的消费者了,消息代理会死等下一个注册到此队列的消费者,然后再次尝试投递。

  8. 通道(channel)
    有些应用需要与AMQP代理建立多个连接。无论怎样,同时开启多个TCP连接都是不合适的,因为这样做会消耗掉过多的系统资源并且使得防火墙的配置更加困难。AMQP 0-9-1提供了通道(channels)来处理多连接,可以把通道理解成共享一个TCP连接的多个轻量化连接。

    在涉及多线程/进程的应用中,为每个线程/进程开启一个通道(channel)是很常见的,并且这些通道不能被线程/进程共享。

    一个特定通道上的通讯与其他通道上的通讯是完全隔离的,因此每个AMQP方法都需要携带一个通道号,这样客户端就可以指定此方法是为哪个通道准备的。

  9. python实现

    python使用pika连接rabbitmq,pip install pika,安装pika依赖。

     import pika
     # 创建连接
     connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
    
     # 创建channel
     channel = connection.channel()
     
     # 创建队列,或者确认队列存在,使用的是默认交换机,将队列持久化
     channel.queue_declare(name='task_queue', durable=True)
     
     # 生产者发布消息
     channel.basic_publish(routing_key='task_queue', 
                                         exchange='', 
                                         body="Hello World")
     # 关闭连接
     connection.close()
     
     # 创建消费者,消费消息
     def callback(ch, method, properties, body):
         print "[Receive] %s " % body
         print "Handling task..."
         time.sleep(len(body) / 10)  # 模拟耗时操作
         print "Task handled"
    
     # 设置,同一时刻不发送给同一消费者超过1条消息
     channel.basic_qos(prefetch_count=1)
     channel.basic_consume(callback, queue="task_queue")
     channel.start_consuming() 
    

你可能感兴趣的:(RabbitMq)