RabbitMQ — docker安装RabbitMQ,Java + Python集成

RabbitMQ — docker安装RabbitMQ,Java + Python集成

一、简介

  • rabbitmq:

    数据一致性

  • 基于AMQP协议

二、安装

1. docker方式

  1. docker拉取和启动:
    推荐以下方式2和3,方式2和3安装配置完,在web管理界面可以直接通过 admin / admin进行登录

    • 方式1,官方命令:

      docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
      
    • 方式2,运行时配置用户和密码:

      docker run -d --hostname my-rabbit --name myrabbit -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 5672:5672 -p 15672:15672 rabbitmq:3-management
      	-h "mars": 指定容器的hostname;
      	15672是管理界面的端口,5672是服务的端口
      
    • 方式3,分开运行:

      下载镜像
      docker pull rabbitmq:3-management
      
      创建容器并运行(15672是管理界面的端口,5672是服务的端口。这里顺便将管理系统的用户名和密码设置为admin admin)
      docker run -dit --name Myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:3-management
      
  2. web访问:

    http://192.168.142.63:15672/
    
    如果配置好了用户名和密码,则采用配置好的用户名和密码进行登录,否准为guest/guest
    

2. rabbitmq常用命令

2.1 授权账号和密码
  • 参考:https://www.linuxhub.cn/2018/08/14/rabbitmq-user.html
  1. 创建用户

    rabbitmqctl add_user admin abc123456
    # 帐号:admin
    # 密码:abc123456
    
  2. 设置管理员

    rabbitmqctl set_user_tags admin administrator
    
    • 用户级别:

      • 超级管理员(administrator)

        可登陆管理控制台(启用management plugin的情况下),可查看所有的信息,并且可以对用户,策略(policy)进行操作。

      • 监控者(monitoring)

        可登陆管理控制台(启用management plugin的情况下),同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)

      • 策略制定者(policymaker)

        可登陆管理控制台(启用management plugin的情况下), 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。

      与administrator的对比,administrator能看到这些内容

      • 普通管理者(management)

        仅可登陆管理控制台(启用management plugin的情况下),无法看到节点信息,也无法对策略进行管理。

      • 其他

        无法登陆管理控制台,通常就是普通的生产者和消费者。

  3. 设置权限

    rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
    
  4. 列出用户

    rabbitmqctl list_users
    
  5. 修改密码:

    #修改guest用户密码为abc123456
    rabbitmqctl change_password guest abc123456
    
  6. 删除用户:

    rabbitmqctl delete_user username
    

三、rabbitmq基本知识

  • 参考资料:https://blog.csdn.net/qq_35387940/article/details/100514134

rabbitmq消息推送到接收的流程:

JCccc-RabbitMq

  1. 交换机:

    常用的交换机有以下三种,因为消费者是从队列获取信息的,队列是绑定交换机的(一般),所以对应的消息推送/接收模式也会有以下几种:

    • Direct Exchange:

      直连型交换机,根据消息携带的路由键将消息投递给对应队列。

      大致流程,有一个队列绑定到一个直连交换机上,同时赋予一个路由键 routing key 。
      然后当一个消息携带着路由值为X,这个消息通过生产者发送给交换机时,交换机就会根据这个路由值X去寻找绑定值也是X的队列。

    • Fanout Exchange:

      扇型交换机,这个交换机没有路由键概念,就算你绑了路由键也是无视的。 这个交换机在接收到消息后,会直接转发到绑定到它上面的所有队列

    • Topic Exchange:

      主题交换机,这个交换机其实跟直连交换机流程差不多,但是它的特点就是在它的路由键和绑定键之间是有规则的。
      简单地介绍下规则:

      • *(星号) 用来表示一个单词 (必须出现的)
      • #(井号) 用来表示任意数量(零个或多个)单词

      通配的绑定键是跟队列进行绑定的,举个小例子:

      • 队列Q1 绑定键为 *.TT.* 队列Q2绑定键为 TT.#
        如果一条消息携带的路由键为 A.TT.B,那么队列Q1将会收到;
        如果一条消息携带的路由键为TT.AA.BB,那么队列Q2将会收到;

      主题交换机是非常强大的,为啥这么膨胀?
      当一个队列的绑定键为 “#”(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。
      当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机就拥有的直连交换机的行为。
      所以主题交换机也就实现了扇形交换机的功能,和直连交换机的功能。

      管理界面中交换机如图:

      在这里插入图片描述

  2. virtual host:

    虚拟主机,类似于MySQL中的数据库,一个项目(一块业务)对应一个虚拟主机

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4m3av3fc-1619705906487)(C:\Users\penti\AppData\Roaming\Typora\typora-user-images\image-20210428143930025.png)]

    管理界面中虚拟主机界面:

    在这里插入图片描述

四、代码集成

1. Java

参考资料:https://www.cnblogs.com/jikeyi/p/13339124.html

  1. 依赖:

    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>4.10.0</version>
    </dependency>
    
  2. 代码编程:

    • 工具类:

      import com.rabbitmq.client.Channel;
      import com.rabbitmq.client.Connection;
      import com.rabbitmq.client.ConnectionFactory;
      
      /**
       * @projName: JavaSkillStack
       * @packgeName: indi.pentiumcm.rabbitmq
       * @className: ConnectionUtil
       * @author: pentiumCM
       * @email: 842679178@qq.com
       * @date: 2021/4/28 17:37
       * @describe: RabbitMq帮助类
       */
      public class RabbitMqUtil {
      
          private static ConnectionFactory factory;
      
      
          static {
              // static:静态代码块类加载执行,执行一次
      
              // 重量级资源
              // 1.创建连接工厂
              factory = new ConnectionFactory();
      
              // 2.在工厂对象中设置MQ的连接信息(ip,port,virtualhost,username,password)
              factory.setHost("192.168.142.63");
              // 设置端口号
              factory.setPort(5672);
              // 设置连接哪个虚拟主机
              factory.setVirtualHost("/test");
              // 设置访问虚拟主机的用户名和密码
              factory.setUsername("admin");
              factory.setPassword("admin");
          }
      
          /**
           * 定义提供连接对象
           *
           * @return
           */
          public static Connection getConnection() {
              try {
                  // 3.通过工厂对象获取与MQ的链接
                  Connection connection = factory.newConnection();
                  return connection;
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return null;
          }
      
      
          /**
           * 关闭通道和连接的工具方法
           *
           * @param channel
           * @param connection
           */
          public static void closeConnectionAndChanel(Channel channel, Connection connection) {
      
              try {
                  if (channel != null) {
                      channel.close();
                  }
                  if (connection != null) {
                      connection.close();
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
      
    • 生产者:

      import com.rabbitmq.client.*;
      
      /**
       * @projName: JavaSkillStack
       * @packgeName: indi.pentiumcm.rabbitmq
       * @className: SendMsg
       * @author: pentiumCM
       * @email: 842679178@qq.com
       * @date: 2021/4/28 19:49
       * @describe: 消息队列——生产者
       */
      public class Productor {
      
          public static void main(String[] args) throws Exception {
      
              String QUEUE_NAME = "hello";
      
              // 1. 创建连接
              Connection connection = RabbitMqUtil.getConnection();
      
              // 2. 获取连接中的通道
              Channel channel = connection.createChannel();
      
              // 3. 声明队列,声明队列,如果该队列已经创建过,则不会重复创建
              // 参数1:定义的队列名称
              // 参数2:队列中的数据是否持久化(如果选择了持久化)
              // 参数3: 是否独占(当前队列是否为当前连接私有)
              // 参数4:自动删除(当此队列的连接数为0时,此队列会销毁(无论队列中是否还有数据))
              // 参数5:设置当前队列的参数
              channel.queueDeclare(QUEUE_NAME, true, false, false, null);
      
              String msg = "I am Java!";
      
              // 4. 发布消息
              // 参数1:交换机名称,如果直接发送信息到队列,则交换机名称为""
              // 参数2:目标队列名称
              // 参数3:设置当前这条消息的属性(设置过期时间 10)
              // 参数4:消息的内容
              channel.basicPublish("", QUEUE_NAME, false, null, msg.getBytes());
              System.out.println("生产者发送:" + msg);
      
      /*        channel.close();
              connection.close();*/
              RabbitMqUtil.closeConnectionAndChanel(channel, connection);
      
          }
      
      }
      
    • 消费者:

      import com.rabbitmq.client.*;
      
      import java.io.IOException;
      import java.util.concurrent.TimeoutException;
      
      
      /**
       * @projName: JavaSkillStack
       * @packgeName: indi.pentiumcm.rabbitmq
       * @className: ReceiveMsg
       * @author: pentiumCM
       * @email: 842679178@qq.com
       * @date: 2021/4/28 20:12
       * @describe: 消息队列——消费者
       */
      public class Consumer {
      
          public static void main(String[] args) throws IOException, TimeoutException {
      
              String QUEUE_NAME = "hello";
      
              // 创建连接对象
              Connection connection = RabbitMqUtil.getConnection();
      
              // 创建通道
              Channel channel = connection.createChannel();
      
              // 通道绑定对应消息队列,声明队列,如果该队列已经创建过,则不会重复创建
              channel.queueDeclare(QUEUE_NAME, true, false, false, null);
      
              DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
                  @Override
                  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                      super.handleDelivery(consumerTag, envelope, properties, body);
      
                      //body就是从队列中获取的数据
                      String message = new String(body, "UTF-8");
                      System.out.println("消费者接收:" + message);
                  }
              };
      
              // 消费信息
              channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
      
      //        RabbitMqUtil.closeConnectionAndChanel(channel, connection);
          }
      }
      
      

2. Python

  1. 依赖:

    python -m pip install pika --upgrade
    
  2. 代码编程:

    • 生产者:

      #!/usr/bin/env python
      # encoding: utf-8
      '''
      @Author  : pentiumCM
      @Email   : 842679178@qq.com
      @Software: PyCharm
      @File    : productor.py
      @Time    : 2021/4/29 20:34
      @desc	 : 消息队列——生产者
      '''
      
      import pika
      import json
      
      host_ip = '192.168.142.63'
      port = 5672
      
      virtual_host = '/test'
      QUEUE_NAME = "hello"
      
      # mq用户名和密码
      credentials = pika.PlainCredentials('admin', 'admin')
      
      # 1. 建立连接
      connection = pika.BlockingConnection(
          pika.ConnectionParameters(host=host_ip, port=port, virtual_host=virtual_host, credentials=credentials))
      
      # 2. 建立通道
      channel = connection.channel()
      
      # 3. 指定队列
      channel.queue_declare(queue=QUEUE_NAME, durable=True)
      
      # 4. 发布消息
      message = json.dumps({'name': 'pentiumcm'})
      # 向队列插入数值 routing_key是队列名
      channel.basic_publish(exchange='', routing_key=QUEUE_NAME, body=message)
      
      print("生产者发送完成:" + message)
      
      connection.close()
      
    • 消费者:

      #!/usr/bin/env python
      # encoding: utf-8
      '''
      @Author  : pentiumCM
      @Email   : 842679178@qq.com
      @Software: PyCharm
      @File    : consumer.py
      @Time    : 2021/4/29 20:34
      @desc	 : 消息队列——消费者
      '''
      
      import pika
      import json
      
      host_ip = '192.168.142.63'
      port = 5672
      
      virtual_host = '/test'
      QUEUE_NAME = "hello"
      
      # mq用户名和密码
      credentials = pika.PlainCredentials('admin', 'admin')
      
      # 1. 建立连接
      connection = pika.BlockingConnection(pika.ConnectionParameters(host=host_ip, port=port,
                                                                     virtual_host=virtual_host,
                                                                     credentials=credentials))
      # 2. 建立通道
      channel = connection.channel()
      
      # 3. 指定队列
      channel.queue_declare(queue=QUEUE_NAME, durable=True)
      
      
      # 定义一个回调函数来处理消息队列中的消息
      def callback(ch, method, properties, body):
          # 接收到生产者消息
          msg = json.loads(body)
          print("消费者接收:" % msg['name'])
      
      
      # 4. 消费消息
      channel.basic_consume(queue=QUEUE_NAME, auto_ack=True, on_message_callback=callback)
      
      channel.start_consuming()
      

五、业务设计

  1. 方式一:
    业务中可设计两个队列:未处理,已处理
    生产者先往未处理队列中发送消息,消费者从未处理的队列中去消息进行处理,当处理完毕之后将处理结果放到已处理的队列中

参考资料

  • docker镜像:https://registry.hub.docker.com/_/rabbitmq/

  • https://www.cnblogs.com/sgh1023/p/11217017.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值