RabbitMQ详解(二)-----RabbitMQ简介和简单使用

一.RabbitMQ简介

  1.rabbitmq的工作模式:

(1)Broker

   RabbitMQ服务器,帮助我们存储、转发消息的代理/中介。

(2)Connection

  生产者发送消息/消费者接收消息,都需要跟Broker之间建立一个TCP的长连接

(3)channel

   所有的生产者发送消息和消费者接收消息,都直接创建和释放TCP长连接的话,对于Broker来说会造成很大的性能损耗。因此引入了Channel(通道)的概念,它是一个虚拟的连接,这样我们就可以在保持的TCP长连接里去创建和释放Channel,大大减少了资源消耗。

(4)Queue

     queue(队列)真正用来存储消息的,是一个独立运行的进程,有自己的数据库(Mnesia)。
     消费者获取消息有两种模式,一种是Push,只要生产者发到服务器,就马上推送给消费者。另一种是Pull,消息存放在服务端,只有消费者主动获取才能拿到消息。消费者不需要循环不断地从队列获取消息,可以基于事件机制,实现消费者对队列的监听。由于队列有FIFO的特性,只有确定前一条消息被消费者接收之后,才会把这条消息从数据库删除,继续投递下一条消息。

(5)Exchange
         在 RabbitMQ 里消息不会直接发送到队列的。而是通过交换机(Exchange)用来实现消息的灵活路由。交换机是一个绑定列表,用来查找匹配的绑定关系。队列使用绑定键(Binding Key)跟交换机建立绑定关系。生产者发送的消息需要携带路由键,交换机收到消息时会根据它保存的绑定列表,决定将消息路由到哪些与它绑定的队列上。
 ps:交换机与队列、队列与消费者都是多对多的关系。

(6)Vhost
          虚拟主机VHOST。VHOST 可以提高硬件资源的利用率之外,实现资源的隔离和权限的控制。不同的 VHOST中可以有同名的Exchange和Queue,它们是完全透明的。可以使自己的业务系统不跟别人混用一个系统。

2.路由方式

(1)直连 Direct
         队列与直连类型的交换机绑定,需指定一个精确的绑定键。生产者发送消息时会携带一个路由键。只有当路由键与其中的某个绑定键完全匹配时,这条消息才会从交换机路由到满足路由关系的此队列上。

                

                channel.basicPublish(“MY_DIRECT_EXCHANGE”,”spring”,”msg1”); 只有第一个队列能收到消息。

(2)主题 Topic
          队列与主题类型的交换机绑定时,可以在绑定键中使用通配符。两个通配符:# 0个或者多个单词,* 不多不少一个单词单词,单词用英文的点“.”隔开的字符。例如abc.def是两个单词。

           

           第一个队列支持路由键以junior 开头的消息路由,后面可以有单词,也可以没有。
           第二个队列支持路由键以netty开头,并且后面是一个单词的消息路由。
           第三个队列支持路由键以jvm结尾,并且前面是一个单词的消息路由

          channel.basicPublish("MY_TOPIC_EXCHANGE","junior.fjd.klj","msg 2"); 只有第一个队列能收到消息。
         channel.basicPublish("MY_TOPIC_EXCHANGE","junior.jvm", "msg 3"); 第一个队列和第三个队列能收到消息

(3)广播 Fanout

            主题类型的交换机与队列绑定时,不需要指定绑定键。因此生产者发送消息到广播类型的交换机上,也不需要携带路由键。消息达到交换机时,所有与之绑定了的队列,都会收到相同的消息的副本。

           

                 channel.basicPublish("MY_FANOUT_EXCHANGE","","msg 4"); 三个队列都会收到 msg 4。

一.简单使用

1.创建Maven工程,pom.xml引入依赖

<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>

2.生产者

public class MyProducer {
    private final static String EXCHANGE_NAME = "SIMPLE_EXCHANGE";
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
          // 连接 IP
        factory.setHost("127.0.0.1");
          // 连接端口
        factory.setPort(5672);
        // 虚拟机
        factory.setVirtualHost("/");
          // 用户
        factory.setUsername("guest");
        factory.setPassword("guest");
        // 建立连接
        Connection conn = factory.newConnection();
        // 创建消息通道
        Channel channel = conn.createChannel();
        // 发送消息
        String msg = "HelloWorld";
        channel.basicPublish(EXCHANGE_NAME, "test.best", null, msg.getBytes());
        channel.close();
        conn.close();
    }
}

3.消费者

public class MyConsumer {
    private final static String EXCHANGE_NAME = "SIMPLE_EXCHANGE";
    private final static String QUEUE_NAME = "SIMPLE_QUEUE";
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");
        factory.setUsername("guest");
        factory.setPassword("guest");
        Connection conn = factory.newConnection();
        Channel channel = conn.createChannel();
        // 声明交换机(参数1.交换机名
        //         2.交换机类型:direct,topic,fanout.
        //         3.是否持久化,代表交换机在服务器重启后是否还存在
        //         4.是否自动删除,设置为TRUE则表是自动删除,自删除的前提是至少有一个队列或者交
        //           换器与这交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑.
        //         5.其它一些结构化参数比如:alternate-exchange)
        channel.exchangeDeclare(EXCHANGE_NAME,"direct",false, false, null);
        // 声明队列(参数1 队列名
        //    2是否持久化,代表队列在服务器重启后是否还存在
        //    3是否排他性队列。排他性队列只能在声明它的 Connection中使用(可以在同一个
        //              Connection 的不同的 channel 中使用),连接断开时自动删除。
        //    4.是否自动删除。如果为 true,至少有一个消费者连接到这个队列,之后所有与这个队列
        //               连接的消费者都断开时,队列会自动删除。
        //    5.队列的其他属性
        //     )
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" Waiting for message....");
         // 绑定队列和交换机
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"test.best");
            // 创建消费者
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body, "UTF-8");
                System.out.println("Received message : '" + msg + "'");
                System.out.println("consumerTag : " + consumerTag );
                System.out.println("deliveryTag : " + envelope.getDeliveryTag());
            }
        };
         // 开始获取消息
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}

5.打开控制台localhost:15672.可观察队列内消息的动态变化

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值