RabbitMq学习总结

目录

RabbitMq定义:

AMQP组件:

交换器类型:

RabbitMq运行流程

RabbitMQ结构

交换器:

队列:

 

交换器和队列绑定:

发送消息:

消费消息:

RabbitMq定义:

基于AMQP协议的,消息中间件;

优点:解耦、异步、削峰。

缺点:降低了系统的稳定性,增加系统的复杂性

AMQP组件:

生成者(produce):消息创建者,将消息发送到消息中间件

消费者(consumer):连接到消息中间件,订阅队列,消息消费

消息(message):包括有效载荷(传输的数据)与标签(描述有效载荷的属性);通过标签决定谁获得信息,消费者只能获取有效载荷

信道(channel):虚拟连接,建立再tcp/ip之上,所有amqp消息都是通过信道传输

交换器、队列、绑定、路由键(exchange、queue、bindings、routing key):队列通过路由键绑定到交换器,生成者把消息发送到交换器,交换器根据绑定的路由键推到特定的队列中,再由订阅队列的消费者进行消息的消费

交换器类型:

fanout(分列):把所有发送到该交换器的消息,路由到所有与该交换器绑定的队列中

direct(直接):把消息路由 绑定键+路由键 完全匹配的队列中

topic(主题):类似于direct,但是可以使用 通配符匹配规则(广播);

 两种模糊匹配符号 *、#

.:将路由键分为了几个标识符

#:匹配一个或多个

*: * 匹配1个

header:消息不根据路由键的匹配规则路由,而是根据发生消息内容的headers属性进行匹配(少)

RabbitMq运行流程

生成者发送消息

1. 生产者于Broker建立连接(connection),开启信道(channel)

2. 生产者声明交换器(交换器类型、是否持久化、是否自动删除等)

3. 生产者声明队列(是否持久化、是否排他、是否自动删除)

4. 生产者通过路由键将交换器和队列绑定

5. 生产者发送消息到broker

6. 交换器接收到路由键,以及交换器类型查询匹配的队列

7. 队列将消息存入相应队列中

8. 找不到,根据生产者配置,选择丢弃还是返回给生产者

9. 关闭信道

10. 关闭连接

消费者接收消息

1. 消费者与Broker建立连接(connection),开启信道(channel)

2. 消费者向Broker请求消费对应对应的信息,可能设置回调函数

3. 等待Broker回应并投递相应队列中的消息,接收消息

4. 消费者确定(ack)接收到的信息

5. RabbitMQ从队列中删除相应已经被确认的消息

6. 关闭信道

7. 关闭连接

RabbitMQ结构

交换器:

Exchange.DeclareOk channel.exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) throws IOException;

队列:

声明队列:

Queue.DeclareOk queueDeclare() throws IOException;

Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean authDelete, Map<String, Object> arguments) throws IOException;

备注:排他队列,如果一个队列被申明为排他队列,改队列仅对首次声明它的连接可见,并在连接断开时自动删除。这种队列适用于一个客户端同时发送和读取消息的应用场景

1. 排他队列基于连接(Connection)可见,同一个连接的不同Channel是可以同时访问同一个连接创建的排他队列

2. 首次是指如果一个连接已经声明一个排他队列,其他连接是不允许建立同名的排他队列,这个和普通队列不同

3. 即使该队列持久化,一旦连接关闭或者客户端退出,该排他队列都会被自动删除

 

自动删除:当连接该队里的消费者,都断开连接后,队列删除,不管队列中是否有数据

声明队列的参数:

队列删除:

Queue.DeleteOk queueDelete(String queue) throws IOException;

Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean isEmpty) throws IOException;

ifUnused:没有被使用的时候

isEmpty:队列为空的时候

队列清空:

PurgeOk queuePurge(String var1) throws IOException;

 

交换器和队列绑定:

绑定:

Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException;

Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

解绑:

Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException;

Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

发送消息:

Channel的basicPublish方法,向RabbitMQ发送消息

void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;

void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body) throws IOException;

void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;

参数:

exchange:交换器名称

routingKey:路由键

props:消息的基本属性

body:消息体

 public static class BasicProperties extends com.rabbitmq.client.impl.AMQBasicProperties {
 
        private String contentType;   //消息类型如(text/plain)
 
        private String contentEncoding; //编码
 
        private Map<String,Object> headers; //header
 
        private Integer deliveryMode; //消息的投递模式
 
        private Integer priority; //优先级
 
        private String correlationId;
 
        private String replyTo;
 
        private String expiration; //过期时间
 
        private String messageId;
 
        private Date timestamp;
 
        private String type;
 
        private String userId;
 
        private String appId;
 
        private String clusterId;

mandatory:true,交换器无法根据自动的类型和路由键找到一个符合条件的队列,那么RabbitMq会调用Basic.Ruturn命令将消息返回给生产都,为false时,出现上述情况消息被直接丢弃

immediate:  true,如果交换器在消息路由到队列时发现没有任何消费者,那么这个消息将不会存和队列,当与路由匹配的所有队列都没有消费者时,会Basic.Return返回给生产者,3.0去掉了immediate  参数

消费消息:

消费消息有两种模式:推 basicConsume()、拉basicGet()

推模式:

String basicConsume(String queue, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, Map<String, Object> arguments, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, String comsumenrTag, Consumer callback) throws IOException;
String basicConsume(String queue, boolean autoAck, String comsumenrTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, Consumer callback) throws IOException;

参数:

autoAck:是否自动确认,false不需要自动确认(发送完消息就直接删除)

consumerTag:消费者标签,用来区分多个消费者,可以打印那个消费者消费的消息

noLocal:设置true表示不能奖同一个Connection中生产者的消息传递给那个Connection中的消费者

exclusive:设置是否排他

arguments:设置消费的其他参数

callback:设置消息回调函数,用来处理RabbitMQ推送过来的消息

public static void push() throws Exception {
        Address[] addresses = new Address[]{new Address(IP_ADDRESS, PORT)};
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUsername("rabbitstudy");
        factory.setPassword("123456");

        //这里的连接方式与生产者的略有不同,注意辨别区别
        Connection connection = factory.newConnection(addresses); //创建连接
        final Channel channel = connection.createChannel(); //创建信道
        channel.basicQos(2);
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
                    throws IOException {
                System.out.println("recv message:"+ new String(body));
                System.out.println("RoutingKey:"+envelope.getRoutingKey());
                System.out.println("ContentType:"+properties.getContentType());
                System.out.println("DeliveryTag:"+envelope.getDeliveryTag()); //消息在队列中的下标
                System.out.println("------------------------------");
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME, false, consumer); //设置autoAck为false

        //等待回调行数执行完毕之后,关闭资源
        channel.close();
        connection.close();
    }

拉模式:

basicGet()单条获取消息,但是basicGet不能用于for循环中代替basicConsume

public static void pull() throws Exception {
        Address[] addresses = new Address[]{new Address(IP_ADDRESS, PORT)};
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUsername("rabbitstudy");
        factory.setPassword("123456");

        //这里的连接方式与生产者的略有不同,注意辨别区别
        Connection connection = factory.newConnection(addresses); //创建连接
        final Channel channel = connection.createChannel(); //创建信道
        channel.basicQos(10);
        GetResponse basicGet = channel.basicGet(QUEUE_NAME, false);
        System.out.println(new String(basicGet.getBody()));

        channel.basicAck(basicGet.getEnvelope().getDeliveryTag(), true); //确认消费完成

        //等待回调行数执行完毕之后,关闭资源
//      channel.close();
//      connection.close();
    }

 

参考文档:

https://www.jianshu.com/p/b8e97606e309

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值