19、Spring Cloud ——Spring Cloud Bus之RabbitMQ介绍

为什么需要使用消息中间件?
我们把Spring Cloud Bus称为消息总线,在使用微服务的时候,我们不可避免的需要在服务之间来做调用,调用的方式有很多种,之前用的Feign、RestTemplate只是其中之一而已,一般来说使用Feign或者RestTemplate来调用一个方法,调用完之后,很短时间内就能知道调用的结果。但是有一些调用我并不想马上就知道结果,甚至说没办法马上就知道结果,比如说发短信验证码,已发送,60秒之内没收到验证码再重新发送,它不告诉你一定就发送成功了,是因为它自己也不知道有没有发送成功。只是说发送的方法已经调用了,至于发送成功了还是失败了,它也不知道。60秒之后没收到,再重试就行了。像这种请求我们就可以使用消息中间件来进行通信。

消息中间件的作用
比如说我要发送一封邮件,我可以先把邮件的要发送的内容以及相关信息,先丢到消息中间件上面去,然后有一个微服务它就不同的去消费这个消息中间件上面的消息,它从这个消息中间件目前最新的信息,看一下有没有邮件让它发,有的话就发送,没有的话就继续等待。然后其他的微服务,它想发邮件,都只需要给这个消息中间件仍一条消息就行了,剩下的事情就不用管了,这可以实现微服务之间的解耦。

Spring Cloud Bus也是微服务架构系统中的必备组件。Spring Cloud Bus可以将分布式系统的节点与轻量级消息代理链接,然后可以实现广播状态更改(例如配置更改)或广播其他管理指令。Spring Cloud Bus就像一个分布式执行器,用于扩展的Spring Boot应用程序,但也可以用作应用程序之间的通信通道。那么这里就涉及到了消息代理,目前流行的消息代理中间件有不少,Spring Cloud Bus支持RabbitMQ和Kafka。现在我们来看看RabbitMQ。

RabbitMQ的安装
RabbitMQ很多人在第一次用的时候,会普遍遇到一个问题,就是安装的问题,因为这个是基于Erlang语言编写的,Erlang的话还要安装它的开发环境(类似于jdk),Erlang环境的话又有一个很麻烦的版本问题,所以很多人经常在这个地方安装失败。这里我们就使用docker来安装.
首先启动docker容器:

systemctl start docker

然后安装并启动rabbitmq

docker run -d --hostname my-rabbit --name some-rabbit -P rabbitmq:3-management

我们可以看到它暴露的端口情况如下:
在这里插入图片描述15672端口(映射到32769)是后台管理的端口,5672端口(映射到32771)是通信的端口,即一会儿用Java代码去发消息的时候往5672端口上面发。

所以可以通过192.168.78.4:32769访问到后台管理端口:
在这里插入图片描述默认的用户名和密码都是guest,使用用户名密码登录后跳转到如下页面:
19、Spring Cloud ——Spring Cloud Bus之RabbitMQ介绍_第1张图片这样就算是启动成功了,现在可以来发送消息了,先创建一个简单的例子来看一下:

首先重新创建一个名为bus的Module并且加入如下依赖:
19、Spring Cloud ——Spring Cloud Bus之RabbitMQ介绍_第2张图片
然后在这个新建项目的application.properties中加上如下配置:

spring.application.name=rabbitmq
#这个端口是指通信的端口
spring.rabbitmq.port=32771
spring.rabbitmq.password=guest
spring.rabbitmq.username=guest
spring.rabbitmq.host=192.168.78.4

RabbitMQ实际上比ActiveMQ使用起来要复杂很多,这也是AcitiveMQ目前用的比较少的原因之一,它目前主要是在一些分布事务里面会用到,其他地方已经很少去用它了。RabbitMQ和ActiveMQ实际上也代表两种消息中间件的流派。ActiveMQ是属于JMS(Java消息服务),所以你在用ActiveMQ的时候,你会发现和jdbc比较像,没有哪个东西是new出来的,它的实现在你加进来的ActiveMQ的驱动里面。JMS规范是从api的层面规范的,在Java领域没问题,但是不支持跨平台。RabbitMQ满足的是amqp规范,这个amqp是从协议领域规范的,它是支持跨平台的,而且它的消息还分为5种不同的类型。

发送消息在RabbitMQ中有一个现成的封装好的对象AmqpTemplate,通过AmqpTemplate我们可以直接向某一个消息队列发送消息创建一个名为Sender的类作为消息生产者:

@Component
public class Sender {

    @Autowired
    AmqpTemplate amqpTemplate;

    public void sendMsg(String msg){
        //convertAndSend()就是转换加发送,因为要发的是一个msg对象,
        // 这个方法可以自动把字符串转成msg对象,
        // 第一个参数是消息队列的名字,第二个参数就是要发送的内容
        this.amqpTemplate.convertAndSend("com.sxt",msg);
        
    }
}

注入AmqpTemplate,然后利用AmqpTemplate向一个名为hello的消息队列中发送消息。

然后再创建一个消息消费者Receiver:

@Component
//要监听的队列名字
@RabbitListener(queues = "com.sxt")
public class Receiver {
    //有消息来了就通过@RabbitHandler,消息就进到下面的方法里面去
    @RabbitHandler
    public void receive(String msg){
        System.out.println("receive:"+msg);
    }
}

@RabbitListener(queues = “com.sxt”)注解表示该消息消费者监听com.sxt这个消息队列,@RabbitHandler注解则表示 receive方法是用来处理接收到的消息的,我们这里收到消息后直接打印即可。

然后需要在创建一个消息队列的bean(即一个Queue对象),这里我为了方便(其实就是懒),就直接在启动类中写了:
19、Spring Cloud ——Spring Cloud Bus之RabbitMQ介绍_第3张图片然后启动项目,启动前一定要保证你的RabbitMQ已经启动了。启动后我们能发现,在RabbitMQ的Queues中了:
19、Spring Cloud ——Spring Cloud Bus之RabbitMQ介绍_第4张图片
然后在单元测试中创建一个进行测试
19、Spring Cloud ——Spring Cloud Bus之RabbitMQ介绍_第5张图片然后执行这个test,我们发现这边已经成功收到了消息:

在这里插入图片描述

你可能感兴趣的:(Spring,Cloud,Spring,Cloud)