GouHuang

导航

 

1. 下载Homebrew

Homebrew是一款Mac OS平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能
Homebrew官网的下载指令由于国内网络原因下载相当慢,甚至会报 443,建议使用国内源

打开终端执行:/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
该地址提供多个国内源地址,根据提示选择国内源,安装非常简便,亲测有效

检查是否安装成功,终端执行:brew -v
打印版本信息安装成功

2. 安装rabbitmq
终端执行:brew install rabbitmq

在安装完成后,安装目录会在末尾进行提示
我的安装目录是:/opt/homebrew/opt/rabbitmq/sbin/rabbitmq-server

2.运行rabbitmq

终端进入rabbitmq安装目录的sbin目录下,执行:./rabbitmq-server --->开启rabbitmq
sbin目录下的,rabbitmqctl 用于关闭rabbitmq: ./rabbitmqctl stop --->关闭rabbitmq

3.rabbitmq的模式

  • 简单模式
  • 交换机模式
    • 交换机之发布订阅模式
    • 交换机之关键字模式
    • 交换机之通配符模式

3.1 简单模式
原理:
生产者连接rabbitmq,创建一个队列,并向队列发送消息;
消费者连接rabbitmq,监听一个队列,队列内有消息后将消息取出

  • 生产者

    点击查看代码
    import pika # 导包 没有就终端执行 pip install pika
    
    # 连接rabbitmq,指定rabitmq服务器的ip 和 端口,5672是rabbitmq的默认端口
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='127.0.0.1',port=5672))  
    
    # 创建管道
    channel = connection.channel()  
    
    # 创建名字为hello的消息队列,尽量使名字唯一
    channel.queue_declare("hello")  
    
    channel.basic_publish(exchange='',
                          routing_key='hello', # 指定队列,给哪个队列发送消息
                          body='我是你大爷实打实的') # 向队列发送的内容
    
    print(" [x] Sent '我是你大爷实打实的'")
    
  • 消费者

    点击查看代码
    import pika
    
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='127.0.0.1', port=5672))
    channel = connection.channel()
    
    # 这一步不能省略,生产者、消费者谁先启动,就谁先创建队列。
    # 否者消费者后启动,监听 hello 队列时,hello队列并未创建会报错。
    channel.queue_declare(queue='hello')
    
    
    # 定义回调函数,用于处理从队列中获取的数据
    def callback(ch, method, properties, body):
        body = body.decode('utf-8')
        print(" [x] Received %r" % body)
    
    # 确定监听的队列
    channel.basic_consume(queue='hello',  # 监听的队列名
                          auto_ack=True,  # True表示默认应答
                          on_message_callback=callback)  # 指定数据的处理方式
    
    print(' [*] Waiting for messages. To exit press CTRL+C')
    
    # 开始监听
    channel.start_consuming()
    
  • 参数设置

    1. 应答参数
      在消费者,中默认应答方式为:只要消费者将队列中的数据取出,rabbitmq就将该条消息删除。
      这种应答方式,效率很高,但是如果消费者将数据取出后,在执行 callback 回调函数发生错误宕机。
      重启后该条数据将会消失(数据未处理完,rabbitmq队列也已经删除)。这种默认应答对重要数据显然不够安全。

      默认应答 ---> 手动应答
      手动应答:在消费者获取队列数据后,rabbitmq不会立即将被获取的数据删除,当 callback 函数处理完成后,发送消息给rabbitmq 确认后,rabbitmq才会将该条数据删除

      手动应答效率不如默认应答,但是更安全

      点击查看代码
       ######## 在消费者中 ########
      
      # 定义回调函数,用于处理从队列中获取的数据
      def callback(ch, method, properties, body):
          body = body.decode('utf-8')
          print(" [x] Received %r" % body)
          ch.basic_ack(delivery_tag=method.delivery_tag) # 数据安全处理完成,告诉rabbitmq可以删除了
      
      # 确定监听
      channel.basic_consume(queue='hello',  
                            auto_ack=False,  # 手动应答
                            on_message_callback=callback)  
      
    2. 持久化参数
      rabbitmq,运行时队列内的数据是跑在内存上,当rabbitmq所在服务器宕机时,队列内还未被消费者取出的数据将会消失。
      持久化参数,用于将数据保存在硬盘上,即使rabbitmq意外宕机,重启后数据依然存在。

      点击查看代码
      ######## 在生产者中 ########
      
      # 申明一个可以持久化存储的队列,注意:消费者此处要保持一致
      channel.queue_declare("hello2", durable=True)   # 已经申明过的队列不能改变其性质
      
      channel.basic_publish(exchange='',
                            routing_key='hello2',
                            body='我是你大爷实打实的',
                            properties=pika.BasicProperties( # 生产者发送消息时,添加这个参数可以使消息持久化
                                delivery_mode=2,)   
                            )
      
    3. 分发参数
      rabbitmq默认采用轮询分发,即每个消费者获取队列内的数据个数是一致的。当轮到某个消费者从队列中获取数据,而该消费者(服务器)上个队列数据还未处理完,rabbitmq将会等待该消费者处理完成;即使该消费者的下一个消费者已经处理完上个队列数据,正在等待rabbitmq队列数据,rabbitmq也不会将队列数据发给它的下一个消费者。
      这种分法方式显然是不合常理的,每台服务器配置不一样,各个队列数据处理形式也不一样,采用轮询分发,将会造成资源的浪费。
      公平分发:只要各消费者数据处理完成了,就可以去取rabbitmq队列中的新数据。

      点击查看代码
      ######## 在消费者中 ########
      
      #在消费者中新增加,实现公平分发
      channel.basic_qos(prefetch_count=1)
      
      # 注意:公平分发必须在 手动应答模式下进行
      

3.2 交换机之订阅发布模式
真棒
简单模式下,rabbitmq消息队列的数据只能被一个消费者取走;而在订阅发布模式下,会为每一个订阅者创建一个队列,而发布者(生产者)发布消息时,会将消息放置在所有相关队列中。

  1. 生产者

    点击查看代码
    import pika
    
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='127.0.0.1', port=5672))
    channel = connection.channel()
    
    # 申明一个交换机
    channel.exchange_declare(exchange='logs',  # 交换机名称
                             exchange_type='fanout')  # 交换机类型:fanout 就是发布订阅模式
    
    message = "info: Hello World!".encode()
    channel.basic_publish(exchange='logs',
                          routing_key='',
                          body=message)
    print(" [x] Sent %r" % message)
    connection.close()
    
  2. 消费者

    点击查看代码
    import pika
    
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='127.0.0.1', port=5672))
    channel = connection.channel()
    
    # 申明一个交换机
    channel.exchange_declare(exchange='logs',  # 交换机名称
                             exchange_type='fanout') # 交换机类型:fanout 就是发布订阅模式
    
    # 由pika模块自动生成一个唯一的队列名
    result = channel.queue_declare("",exclusive=True)
    queue_name = result.method.queue
    
    # 将队列绑定在交换机上
    channel.queue_bind(exchange='logs',
                       queue=queue_name)
    
    print(' [*] Waiting for logs. To exit press CTRL+C')
    
    def callback(ch, method, properties, body):
        print(" [x] %r" % body)
    
    
    channel.basic_consume(queue=queue_name,
                          auto_ack=True,
                          on_message_callback=callback)
    
    channel.start_consuming()
    

3.3 交换机之关键字模式
真棒
与发布订阅模式类似,为每个订阅者创建一个队列;但是交换机在给队列发送数据时,会根据设定的关键字发送指定数据,并不是将所有数据都发送给每个队列。

1.生产者

点击查看代码
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# 创建一个交换机
channel.exchange_declare(exchange='logs2',
                         exchange_type='direct') # direct 表示关键字模式

message = "Hello World!".encode()
channel.basic_publish(exchange='logs2',
                      routing_key='warning', # 本次发布的关键字为 warning
                      body=message)

print(" [x] Sent %r" % message)
connection.close()

2.消费者

点击查看代码
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# 创建一个交换机
channel.exchange_declare(exchange='logs2',
                         exchange_type='direct') # direct 表示关键字模式


result = channel.queue_declare("",exclusive=True)
queue_name = result.method.queue
print(queue_name)

# 绑定交换机并指定关键字
channel.queue_bind(exchange='logs2',
                   queue=queue_name,
                   routing_key="error") # 获取关键字 error 的数据
# 可以绑定多个关键字,可用for循环写
channel.queue_bind(exchange='logs2',
                   queue=queue_name,
                   routing_key="warning")  #获取关键字 warning 的数据

print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
    print(" [x] %r" % body)


channel.basic_consume(queue=queue_name,
                      auto_ack=True,
                      on_message_callback=callback)

channel.start_consuming()

3.4 交换机之通配符

通配符模式与关键字模式类似,但是比关键字模式更加精细化。通配符可以进行模糊匹配,
以“key1.key2.keyN....”的模式来指定信息传输的key的大类型和大类型下面的小类型,让消费者可以更加精细的确认自己想要获取的信息类型。而在消费者一段,不用精确的指定具体到哪一个大类型下的小类型的key,而是可以使用类似正则表达式(但与正则表达式规则完全不同)的通配符在指定一定范围或符合某一个字符串匹配规则的key,来获取想要的信息。

“通配符交换机”(Topic Exchange)将路由键和某模式进行匹配。此时队列需要绑定在一个模式上。符号“#”匹配一个或多个词,符号“”仅匹配一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.”只会匹配到“audit.irs”。(这里与我们一般的正则表达式的“*”和“#”刚好相反,这里我们需要注意一下。)
下面是一个解释通配符模式交换机工作的一个样例
真棒

1.生产者

点击查看代码
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
    host='localhost'))
channel = connection.channel()

# 创建一个交换机
channel.exchange_declare(exchange='logs5',
                         exchange_type='topic') # topic 表示通配符模式

message = "usa.news: Hello World!".encode()
channel.basic_publish(exchange='logs5',
                      routing_key='usa.news', # 本次发布的key
                      body=message)

print(" [x] Sent %r" % message)
connection.close()

2.消费者

点击查看代码
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# 创建一个交换机
channel.exchange_declare(exchange='logs5',
                         exchange_type='topic')  #topic表示通配符模式


result = channel.queue_declare("",exclusive=True)
queue_name = result.method.queue

# 绑定交换机,并申明要获取的关键字
channel.queue_bind(exchange='logs5',
                   queue=queue_name,
                   routing_key="#.weather") #   #号表示多个词,只要末尾是 .weather 的信息都要
# 同样可以绑定多个
channel.queue_bind(exchange='logs5',
                   queue=queue_name,
                   routing_key="*.news") #    *号表示一个词,末尾是 .news 且前面只有一个词的信息,如 usa.news china.news 等

print(' [*] Waiting for logs. To exit press CTRL+C')

def callback(ch, method, properties, body):
    print(" [x] %r" % body)


channel.basic_consume(queue=queue_name,
                      auto_ack=True,
                      on_message_callback=callback)

channel.start_consuming()
posted on 2022-02-25 20:53  GouHuang  阅读(636)  评论(0编辑  收藏  举报