rabbitmq入门

一 、什么是消息队列

消息队列可以看作是一个存放消息的容器,当我们需要使用消息的时候,直接从容器中取出消息供自己使用即可。中间件

二、 为什么要用消息队列

  1. 通过异步处理提高系统性能(减少响应所需时间)。

  2. 削峰/限流

  3. 降低系统耦合性。

三 、使用消息队列带来的一些问题

  • 系统可用性降低: 系统可用性在某种程度上降低,为什么这样说呢?在加入 MQ 之前,你不用考虑消息丢失或者说 MQ 挂掉等等的情况,但是,引入 MQ 之后你就需要去考虑了!

  • 系统复杂性提高: 加入 MQ 之后,你需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题!

  • 一致性问题: 我上面讲了消息队列可以实现异步,消息队列带来的异步确实可以提高系统响应速度。但是,万一消息的真正消费者并没有正确消费消息怎么办?这样就会导致数据不一致的情况了!

四 JMS VS AMQP

4.1 JMS

JMS(JAVA Message Service,java 消息服务)是 java 的消息服务,JMS 的客户端之间可以通过 JMS 服务进行异步的消息传输。

 

ActiveMQ 就是基于 JMS 规范实现的。

4.2 AMQP

AMQP,即 Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准 高级消息队列协议(二进制应用层协议),是应用层协议的一个开放标准,为面向消息的中间件设计,兼容 JMS。

4.3 JMS vs AMQP

对比方向JMSAMQP
定义Java API协议
跨语言
跨平台
支持消息类型提供两种消息模型:①Peer-2-Peer;②Pub/sub提供了五种消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本质来讲,后四种和 JMS 的 pub/sub 模型没有太大差别,仅是在路由机制上做了更详细的划分;
支持消息类型支持多种消息类型 ,我们在上面提到过byte[](二进制)

五、 RabbitMQ 核心概念

1.2.2 Exchange(交换器)

在 RabbitMQ 中,消息并不是直接被投递到 Queue(消息队列) 中的,中间还必须经过 Exchange(交换器) 这一层,Exchange(交换器) 会把我们的消息分配到对应的 Queue(消息队列) 中。

Exchange(交换器) 用来接收生产者发送的消息并将这些消息路由给服务器中的队列中,如果路由不到,或许会返回给 Producer(生产者) ,或许会被直接丢弃掉 。

RabbitMQ 的 Exchange(交换器) 有4种类型,不同的类型对应着不同的路由策略direct(默认)fanout, topic, 和 headers


生产者将消息发给交换器的时候,一般会指定一个 RoutingKey(路由键),用来指定这个消息的路由规则,而这个 RoutingKey 需要与交换器类型和绑定键(BindingKey)联合使用才能最终生效

生产者将消息发送给交换器时,需要一个RoutingKey,当 BindingKey 和 RoutingKey 相匹配时,消息会被路由到对应的队列中。

1.2.3 Queue(消息队列)

Queue(消息队列) 用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。

多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin,即轮询)给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理,这样避免消息被重复消费。

1.2.4 Broker(消息中间件的服务节点)

对于 RabbitMQ 来说,一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ 服务节点,或者RabbitMQ服务实例。大多数情况下也可以将一个 RabbitMQ Broker 看作一台 RabbitMQ 服务器。

1.2.5 Exchange Types(交换器类型)

① fanout

fanout 类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中,不需要做任何判断操作,所以 fanout 类型是所有的交换机类型里面速度最快的。fanout 类型常用来广播消息。

② direct

direct 类型的Exchange路由规则也很简单,它会把消息路由到那些 Bindingkey 与 RoutingKey 完全匹配的 Queue 中。

③ topic

前面讲到direct类型的交换器路由规则是完全匹配 BindingKey 和 RoutingKey ,但是这种严格的匹配方式在很多情况下不能满足实际业务的需求。topic类型的交换器在匹配规则上进行了扩展,它与 direct 类型的交换器相似,也是将消息路由到 BindingKey 和 RoutingKey 相匹配的队列中,但这里的匹配规则有些不同,它约定:

  • RoutingKey 为一个点号“.”分隔的字符串(被点号“.”分隔开的每一段独立的字符串称为一个单词),如 “com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”;

  • BindingKey 和 RoutingKey 一样也是点号“.”分隔的字符串;

  • BindingKey 中可以存在两种特殊字符串“”和“#”,用于做模糊匹配,其中“”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)。

④ headers(不推荐)

headers 类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的 headers 属性进行匹配

六、实操

1.创建交换器

2.docker部署遇到的问题

问题一:访问交换机时报错

Management API returned status code 500

问题二:访问channel时报错

Stats in management UI are disabled on this node

解决方法:

 

问题三、连接RabbitMQ异常: com.rabbitmq.client.ShutdownSignalException: connection error; protocol meth

原因:权限不够。

解决方法:rabbitmqctl set_permissions -p "/" username "." "." ".*"

 

 

3.springboot整合rabbitmq

1.创建springboot项目,添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        

2.配置文件

spring:
  rabbitmq:
    host: 192.168.36.131
    username: root
    password: root

3.编写测试类

@SpringBootTest
class RabbitmqDemoApplicationTests {
​
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Test
    public void send(){
        //使用的点对点发送:direct路由
        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
        map.put("fd","hshahh");
        map.put("duo",new String());
        map.put("数组", Arrays.asList("fd",3));
        //convertAndSend直接把对象序列化发送
        rabbitTemplate.convertAndSend("exchanges.direct","jd",map);
    }
​
    @Test
    public void receive(){
        //序列化接收
        Object jd = rabbitTemplate.receiveAndConvert("jd");
        System.out.println(jd.getClass());
        System.out.println(jd);
    }
​
    @Test
    public void fanoutSend(){
        rabbitTemplate.convertAndSend("exchanges.fanout","",new Book("fesf",33));
    }
​
}

4.编写序列化json的转换器

@Configuration
public class MyConverter {
​
    @Bean
    public MessageConverter converter(){
        return new Jackson2JsonMessageConverter();
    }
}
​
//按Ctrl+Alt+B 显示子类

5.启动rabbitmq

6.消息监听

@Service
public class BookService {
​
    //监听队列
    @RabbitListener(queues="jd.emps")
    public void receive(Book book){
        System.out.println("收到: "+book);
    }
    
    @RabbitListener(queues="jd")
    public void receive2(Message message){
        System.out.println(message.getBody());
        System.out.println(message.getMessageProperties());
    }
}
​
​
//开启rabbit的注解配置
@EnableRabbit
@SpringBootApplication
public class RabbitmqDemoApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(RabbitmqDemoApplication.class, args);
    }
}
​

7.自动配置

1.rabbitAutoConfiguration

2.有自动配置了连接工厂ConnectionFactory

3.RabbitProperties,封装了RabbitMQ配置

4.RabbitTemplate:给RabbitMQ发送和接收消息

5.AmqpAdmin系统管理功能组件

8.使用AmqpAdmin创建交换器和队列

@Test
public void create(){
    //创建交换器
    //amqpAdmin.declareExchange(new DirectExchange("ampqadmin.exchange"));
​
    //创建队列
    //amqpAdmin.declareQueue(new Queue("ampqadmin",true));
​
    //绑定
    amqpAdmin.declareBinding(new Binding("ampqadmin", Binding.DestinationType.QUEUE,"ampqadmin.exchange","amqpadmin.#",null));
​
    //删除
    amqpAdmin.deleteExchange("");
    amqpAdmin.deleteQueue("");
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值