• RabbitMQ 快速入门


    1.简介

    RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue protocol)的开源实现。AMQP高级消息队列,说白了就是一个开源的消息中间件。它能解决不同组件、模块、系统间消息通信。

    2.系统架构

    RabbitMQ Server: 也叫broker server,存储消息的地方

    Producer:数据的发送方

    Consumer:数据的接收方

    Connection: 就是一个TCP的连接。Producer和Consumer都是通过TCP连接到RabbitMQ Server的。以后我们可以看到,程序的起始处就是建立这个TCP连接。

    Channels: 虚拟连接。它建立在上述的TCP连接中。数据流动都是在Channel中进行的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。

     那么,为什么使用Channel,而不是直接使用TCP连接?

    对于OS来说,建立和关闭TCP连接是有代价的,频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。对于Producer或者Consumer来说,可以并发的使用多个Channel进行Publish或者Receive。

    Message:消息。服务器和应用程序之间传递的数据,本质上就是一段数据,由Properties和Body组成。

    Exchange:交换机。接收消息,根据路由键转发消息到绑定的队列。

    Binding:Exchange和Queue之间的虚拟连接,binding中可以包含routing key。

    Routing key:一个虚拟地址,虚拟机可用它来确定如何路由一个特定消息。

    Queue:也称为Message Queue,消息队列,保存消息并将它们转发给消费者。

    Virtual Host:其实是一个虚拟概念。类似于权限控制组,一个Virtual Host里面可以有若干个Exchange和Queue,可以用来隔离Exchange和Queue。,同一个Virtual Host里面不能有相同名称的Exchange和Queue。但是权限控制的最小粒度是Virtual Host。(下面会讲到)

    3、图解

        1. 信息生产者将消息(message)发送到exchange

      2. exchange接受消息之后,负责将其路由到具体的队列中

      3. Bindings负责连接exchange和队列(queue)

      4. 消息到达队列(queue),然后等待被消息接收端处理

      5. 消息接收端处理消息

    Exchanges有三种类型:direct, fanout,topic。 每个实现了不同的路由算法(routing algorithm)。

    Direct exchange: 如果 routing key 匹配, 那么Message就会被传递到相应的queue中。其实在queue创建时,它会自动的以queue的名字作为routing key来绑定那个exchange。

    Fanout exchange: 会向响应的queue广播。

    Topic exchange: 对key进行模式匹配,比如ab*可以传递到所有ab*的queue。

    Consumer和Procuder都可以通过 queue.declare 创建queue。如果queue已经存在,也不会报错。如果没有,要么发送不了消息,要么取不到消息,所以还是都创建吧。

    Bindings就是将通过Exchange将queue和routing keys绑定。

    总结:生产者将消息发送到Exchange交换机的,不是发送到Queue上的,生产者不知道消息是谁消费,有哪些消费者消费。Exchange根据一定的路由规则将消息转发到Queue。
    消费者是监听队列的,不知道是哪个生产者发送的

    4.具体代码

    添加maven 依赖

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

    消费者

    package com.flying.rabbitmq.quickstart;
    
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    import com.rabbitmq.client.QueueingConsumer;
    
    import java.io.IOException;
    import java.util.concurrent.TimeoutException;
    
    public class Consumer {
        public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
            //创建connectionFactory 并进行配置
            ConnectionFactory connectionFactory=new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setVirtualHost("/");
            //2.通过连接工厂创建连接
            Connection connection=connectionFactory.newConnection();
            //3.通过connection 创建一个channel 通道
            Channel channel=connection.createChannel();
            //4 声明(创建)一个队列
            String queueName = "test001";
            channel.queueDeclare(queueName,true,false,false,null);
            //5.声明一个消费者
            QueueingConsumer queueingConsumer=new QueueingConsumer(channel);
            //6.设置Channel
            channel.basicConsume(queueName,true,queueingConsumer);
            while (true){
                //7.获取消息
                QueueingConsumer.Delivery delivery=queueingConsumer.nextDelivery();
                String msg=new String(delivery.getBody());
                System.err.println("消费端"+msg);
            }
        }
    }

    生产端

    package com.flying.rabbitmq.quickstart;
    
    import com.rabbitmq.client.Channel;
    import com.rabbitmq.client.Connection;
    import com.rabbitmq.client.ConnectionFactory;
    
    import java.io.IOException;
    import java.util.concurrent.TimeoutException;
    
    public class Producer {
        public static void main(String[] args) throws IOException, TimeoutException {
            //创建connectionFactory 并进行配置
            ConnectionFactory connectionFactory=new ConnectionFactory();
            connectionFactory.setHost("127.0.0.1");
            connectionFactory.setPort(5672);
            connectionFactory.setVirtualHost("/");
            //2.通过连接工厂创建连接
            Connection connection=connectionFactory.newConnection();
            //3.通过connection 创建一个channel 通道
            Channel channel=connection.createChannel();
            //4.通过Channel 发送数据
            for(int i=0; i < 5;i++){
                String msg="Hello rabbitmq";
                channel.basicPublish("","test001",null,msg.getBytes());
            }
    
            //5 记得要关闭相关的连接
            channel.close();
            connectionFactory.clone();
    
        }
    }

    运行结果

  • 相关阅读:
    并发编程三要素:原子性,有序性,可见性
    【华为云技术分享】【Python成长之路】来聊聊多线程的几位“辅助”
    【华为云技术分享】根因分析
    【华为云技术分享】浅谈服务化和微服务化(下)
    【华为云技术分享】浅谈服务化和微服务化(上)
    【华为云技术分享】STM32 GPIO的原理、特性、选型和配置
    【华为云技术分享】快速理解spark-on-k8s中的external-shuffle-service
    【华为云技术分享】如何设计高质量软件-领域驱动设计DDD(Domain-Driven Design)学习心得
    【华为云技术分享】唐老师带你秒懂大数据,以及Spark和Flink在干啥咧
    【华为云技术分享】昇腾AI处理器软件栈--总览
  • 原文地址:https://www.cnblogs.com/lflying/p/11107150.html
Copyright © 2020-2023  润新知