MQ - rabbitMq


前言

消息队列Message Queue,是一种跨进程的通信机制,用于在系统之间进行传递消息.是一种跨进程的通信机制,用于在系统之间进行传递消息,


提示:以下是本篇文章正文内容,下面案例可供参考

一、消息队列的使用场景

应用解耦

多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败
系统间消息传递通过MQ进行解耦,“消息队列”是在消息的传输过程中保存消息 的容器
在这里插入图片描述

异步处理

应用间并发处理消息,相比串行处理,减少处理时间
比如用户为了使用某个应用,进行注册,系统需要发送注册邮件,验证短信
在这里插入图片描述

限流削峰

广泛应用于秒杀或抢购活动中,避免流量过大导致处理请求阻塞的情况
在这里插入图片描述

二、RabbitMQ

RabbitMQ是支持多种消息协议,易于部署和使用的开源消息代理服务器,用于在分布式系统中存储转发消息
1.由以高性能、健壮以及可伸缩性出名的Erlang语言编写;提供了成熟的高并发,高可用的解决方案
A.可以根据实际业务情况动态地扩展集群节点
B.在集群中的机器上设置镜像,使得在部分节点出现问题的情况下仍然可用
2.支持多种客户端语言,如:Python、Ruby、.NET、Java等,支持AJAX
RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的 节点等。

安装与使用

在这里插入图片描述
Linux安装使用
在这里插入图片描述

常用命令

启停服务

在这里插入图片描述

用户管理

命令行指令
在这里插入图片描述

相关概念

在这里插入图片描述

Queue

消息队列,提供了FIFO(先入先出)的处理机制,具有缓存消息的能力。rabbitmq中,队列消息可以设置为持久化,临时或者自动删除。
1.设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止系统crash.
2.数据丢失设置为临时队列,queue中的数据在系统重启之后就会丢失
3.设置为自动删除的队列,当不存在用户连接到server,队列中的数据会被自动删除

队列状态
在这里插入图片描述

Vhost虚拟主机

虚拟主机vhost是AMQP概念的基础,RabbitMQ包含了开箱即用的 默认虚拟主机"/“
1.vhost之间是绝对隔离,保障了队列和交换机的安全性。
2.rabbitmqctl add_vhost[vhost_name]
3.rabbitmqctl delete _vhost[vhost_name]

Exchange

Exchange类似于数据通信网络中的交换机,提供消息路由策略。rabbitmq中,producer不是通过信道直接将消息发送给queue,而是先发送给Exchange。一个Exchange可以和多个Queue进行绑定,producer在传递消息的时候,会传递一个ROUTING_KEY,Exchange会根据这个ROUTING_KEY按照特定的路由算法,将消息路由给指定的queue。和Queue一样,Exchange也可设置为持久化,临时或者自动删除。
Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别:

1.Direct

直接交换器,工作方式类似于单播,Exchange会将消息发送完全匹配ROUTING_KEY的Queue

2.Fanout

广播式交换器,不管消息的ROUTING_KEY设置为什么,Exchange都会将消息转发给所有绑定的Queue。

3.Topic

主题交换器,工作方式类似于组播,Exchange会将消息转发和ROUTING_KEY匹配模式相同的所有队列,比如,ROUTING_KEY为user.stock的Message会转发给绑定匹配模式为 * .stock,user.stock, * . * 和#.user.stock.#的队列。( * 表是匹配一个任意词组,#表示匹配0个或多个词组)

4.Headers

消息体的header匹配(ignore)

Java 客户端访问RabbitMQ

添加依赖

在这里插入图片描述

创建生产者
/**
     * 生产者
     * @throws IOException
     * @throws TimeoutException
     */
    @Test
    public void producer() throws IOException, TimeoutException {
        ConnectionFactory connectionFactory=new ConnectionFactory();
        connectionFactory.setVirtualHost("/user");
        connectionFactory.setHost("localhost");
        connectionFactory.setPassword("guest");
        connectionFactory.setUsername("guest");
        connectionFactory.setPort(5672);
        //创建连接
        Connection connection=connectionFactory.newConnection();
        //创建管道
        Channel channel=connection.createChannel();
        //参数一:队列的名称,有则直接用,没有则创建
        //参数二:是否持久化,false表示不作持久化处理
        //参数三:是否私有化,false表示任何消费者都可以访问该队列,true表示只有第一次访问该队列的消费者才可以访问
        //参数四:是否自动删除,表示mq停掉服务后是否删除该队列,false表示不自动删除
        //参数五:是其他的一些属性设置
        channel.queueDeclare("user_queue",false,false,false,null);
        //参数一:交换机的名称
        //参数二:队列的名称
        //参数三:其他额外的属性
        //参数四:发布的消息
        channel.basicPublish("","user_queue",null,"2019/8/13".getBytes());
        channel.close();
        connection.close();
    }
创建消费者
	@Test
    public void Consumer() throws IOException, TimeoutException {
        ConnectionFactory connectionFactory=new ConnectionFactory();
        connectionFactory.setVirtualHost("/user");
        connectionFactory.setHost("localhost");
        connectionFactory.setPassword("guest");
        connectionFactory.setUsername("guest");
        connectionFactory.setPort(5672);
        //创建连接
        Connection connection=connectionFactory.newConnection();
        //创建管道
        Channel channel=connection.createChannel();
        //参数一:队列的名称,有则直接用,没有则创建
        //参数二:是否持久化,false表示不作持久化处理
        //参数三:是否私有化,false表示任何消费者都可以访问该队列,true表示只有第一次访问该队列的消费者才可以访问
        //参数四:是否自动删除,表示mq停掉服务后是否删除该队列,false表示不自动删除
        //参数五:是其他的一些属性设置
        channel.queueDeclare("user_queue",false,false,false,null);
        //参数一:队列
        //参数二:是否代码手动签收,false代表手动签收(推荐)
        channel.basicConsume("user_queue", false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery
                    (String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                //参数一:消息的ID
                //参数二:true表示签收的所有消息,false表示只签收当前消息
                channel.basicAck(envelope.getDeliveryTag(),false);
                System.out.println(new String(body));//2019/8/13
            }
        });

    }

RabbitMQ的工作模式

Simp工作模式

一个生产者,一个消费者
在这里插入图片描述
生产者

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("work_queue", false, false, false, null);
        for (int i = 1; i < 100; i++) {
            Message message = new Message();
            message.setId(i);
            message.setContext("work_通知");
            String json = JSONObject.toJSONString(message);
            channel.basicPublish("", "work_queue", null, json.getBytes());
        }
        channel.close();
        connection.close();
    }

消费者

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory= RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.basicConsume("work_queue", false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                channel.basicAck(envelope.getDeliveryTag(),false);
                System.out.println("消费消息:"+new String(body));
            }
        });
    }
Work工作模式

1.一个生产者,多个消费者,每个消费者获取到的消息唯一
2.在多个消息的情况下,WorkQueue会将消息分派给不同的消费者,每个消费者会 接收到不同的消息,并且可以根据消息的处理速度来接受不同数量的消息,进而让 消费者程序发挥最大的性能
3.适合在集群的环境中做异步处理,最大发挥每一台服务器的性能
在这里插入图片描述

publish/subscribe发布订阅模式

1该模式下交换机的类型为扇形交换中心(Fanout exchange)
在这里插入图片描述

2.一个生产者发送的消息会被多个消费者获取
3.发布订阅模式中生产者不在直接与队列进行绑定,而是将数据发送给交换机 (Exchange)

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //生产者直接与exchange交互,将消息投递投递给exchange
        channel.basicPublish("msg_exchange","",null,"一些短信通知".getBytes());
        channel.close();
        connection.close();
        System.out.println("完成生产");
    }

4.交换机Exchage负责将数据按照某种规则送入与之绑定的队列,进而供消费者使用

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("xc_queue",false,false,false,null);
        //将队列与交换机绑定
        //参数一:队列;参数二:交换机;参数三:路由key
        channel.queueBind("xc_queue","msg_exchange","");
        channel.basicConsume("xc_queue",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                channel.basicAck(envelope.getDeliveryTag(),false);
                System.out.println("msg:"+new String(body));
            }
        });
    }
Routing 路由模式

1.路由模式下交换机的类型是直接交换中心 (Direct exchange)
在这里插入图片描述

2.发布订阅模式是交换机无条件将所有消息分发给绑定的队列;而路由模式则是根据 routing key有条件的将数据筛选后分发给绑定的队列。
3.发送消息到交换机时要指定路由key ,消费者将队列绑定到交换机时也需要指定路由key
生产者

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        Map map=new HashMap();
        map.put("chain.ch.2000-10-1","2000-10-1川航票务");
        map.put("chain.xh.2000-10-1","2000-10-1夏航票务");
        map.put("chain.cd.2000-10-1","2000-10-1成都票务");
        map.put("chain.xz.2000-10-1","2000-10-1西藏票务");
        map.put("chain.bj.2000-10-2","2000-10-2北京票务");
        map.put("chain.xh.2000-10-2","2000-10-2夏航票务");
        map.put("chain.cd.2000-10-2","2000-10-2成都票务");
        map.put("chain.xz.2000-10-2","2000-10-2西藏票务");
        map.put("chain.bj.2000-10-2","2000-10-2北京票务");
        for(Iterator iterator=map.entrySet().iterator();iterator.hasNext();){
            Map.Entry<String,String> entry= (Map.Entry<String, String>) iterator.next();
            //参数二为路由key
            channel.basicPublish("route_exchange",entry.getKey(),null,entry.getValue().getBytes());
        }

    }

消费者

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("qn_queue",false,false,false,null);
        //将队列与交换机绑定
        //参数一:队列;参数二:交换机;参数三:路由key
        channel.queueBind("qn_queue","route_exchange","chain.xz.2000-10-2");
        channel.basicConsume("qn_queue",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                channel.basicAck(envelope.getDeliveryTag(),false);
                System.out.println("msg:"+new String(body));
            }
        });
    }
Topic主题模式

1.主题模式是在Routing模式匹配基础上,提供了对RouteKey模糊匹配的功能,可 以简化编程,主题模式下交换机的类型为主题交换中心(Topic exchange)
在这里插入图片描述
2.主题模式下,模糊匹配表达式规则为
*匹配单个关键字
#匹配所有关键字

生产者

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        Map map=new HashMap();
        map.put("chain.ch.2000-10-1","2000-10-1川航票务");
        map.put("chain.xh.2000-10-1","2000-10-1夏航票务");
        map.put("chain.cd.2000-10-1","2000-10-1成都票务");
        map.put("chain.xz.2000-10-1","2000-10-1西藏票务");
        map.put("chain.bj.2000-10-2","2000-10-2北京票务");
        map.put("chain.xh.2000-10-2","2000-10-2夏航票务");
        map.put("chain.cd.2000-10-2","2000-10-2成都票务");
        map.put("chain.xz.2000-10-2","2000-10-2西藏票务");
        map.put("chain.bj.2000-10-2","2000-10-2北京票务");
        for(Iterator iterator = map.entrySet().iterator(); iterator.hasNext();){
            Map.Entry<String,String> entry= (Map.Entry<String, String>) iterator.next();
            //参数二为路由key
            channel.basicPublish("topic_exchange",entry.getKey(),null,entry.getValue().getBytes());
        }
    }

消费者

public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUitl.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("qn_queue",false,false,false,null);
        //将队列与交换机绑定
        //参数一:队列;参数二:交换机;参数三:路由key
        channel.queueBind("qn_queue","topic_exchange","*.*.2000-10-2");
        channel.basicConsume("qn_queue",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                channel.basicAck(envelope.getDeliveryTag(),false);
                System.out.println("msg:"+new String(body));
            }
        });
    }

RabbitMQ消息确认机制(待补充)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值