一文弄懂RabbitMq的使用

RabbitMq的基本使用

简介

首先RabbitMq是什么?

RabbitMq是一个用Erlang编写的实现了高级消息队列协议的开源消息代理软件

消息队列又是什么?

大白话说就是一个装了消息的队列,一个人在消息队列的一边放入消息,另外一个人在对列的另一边取消息来作出相应的行为。通过消息队列,两人之间的交互是异步的。

高级消息队列协议又是什么?

高级消息队列协议,英文名Advanced Message Queuing Protocol。说白了就是一套公开的消息队列的协议,用来统一规范消息队列的开发。与此类似,Java也有一套消息队列的标准叫JMS,但是由于JMS是Java专属的,无法跨语言。

RabbitMq安装

这里直接用Docker来安装RabbitMq,使用Arch来安装相对较麻烦,需要修改一些文件的权限,当然你不会使用docker也没有关系,只需要安装好doker,配置好一个docker镜像,然后执行一下的指令即可(Docker具体教程正在路上。。。)

$ sudo docker pull docker.io/rabbitmq:3.8-management  # 拉取rabbitmq镜像
$ sudo docker images # 查看rabbitmq的镜像号,我这里是镜像号的前三个数字是800
$ sudo docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672 800 # 端口15672用于开启一个网页的控制端,一个则是RabbitMq使用的端口,根据上面查到的镜像号换掉800

RabbitMq的基本组件

RabbitMq_01

看一下这张图(自己画的,有点简陋)

publisher:消息的发布者

exchange:消息的路由器,每个路由器有一个routing key,不同的exchange与queue有不同的绑定规则

  • direct:一对一的方式,可绑定多个queue,每次发送只能发送到routing key相同的queue
  • fanout:一对多,直接发送到所有与该exchange绑定的queue
  • topic:一对多,直接按照一定规则匹配对绑定的queue进行发送比如excahnge的routing key为news.* ,queue有名为news.usa news.china mail.usa 三个queue,那么news.usa news.china就成功匹配了,***** 是指模糊匹配一个单词,你还可以使用**##**表示模糊匹配所有
  • header:根据header进行发送

queue(exchange后面连接的部分):队列

channel:复用连接的信道

receiver:消息的接收者

broker:指整个RabbitMq服务器,即exchange+queue

vhost:上图没有指出,RabbitMq内部可以划分出独立的host,每个host有自己的exchange和queue,可以通过vhost实现一定的权限控制

使用控制台

RabbitMq提供了一个控制台网页供操作

地址是:http://127.0.0.1:15672/

默认用户名:guest

默认密码:guest

RabbitMq_02

你可以通过这个控制台来使用模拟使用RabbitMq,创建不同的exchanges和queues,将他们相互绑定,验证上述的exchange转发规则

SpringBoot 使用 RabbitMq

开启一个新的项目

RabbitMq_03

引入SpringWeb和RabbitMq

spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

配置一下application.propertities,当然上面的配置都是默认配置,不写问题也不大

声明exchange和queue

使用单元测试,测试一下exchange和queue的声明

@SpringBootTest
class MqApplicationTests {

    @Autowired
    AmqpAdmin amqpAdmin; //自动注入一个AmqpAdmin用来声明exchange和queue

    @Test
    void test(){
        //声明一个direct exchange
        amqpAdmin.declareExchange(new DirectExchange("direct.news.china" ));

        //声明一个fanout exchange
        amqpAdmin.declareExchange(new FanoutExchange("fanout.news"));

        //声明一个topic exchange
        amqpAdmin.declareExchange(new TopicExchange("topic.mail"));

        //声明一个名为news.china的queue
        amqpAdmin.declareQueue(new Queue("news.china"));

        //声明一个名为news.usa的queue
        amqpAdmin.declareQueue(new Queue("news.usa"));

        //声明一个名为mail.china的queue
        amqpAdmin.declareQueue(new Queue("mail.china"));

        //声明一个名为mail.usa的ququ
        amqpAdmin.declareQueue(new Queue("mail.usa"));
    }

}

代码执行成功之后,查看网页控制台,可发现上面声明的exchange和queue已经出现

RabbitMq_04

RabbitMq_05

绑定exchange和queue

可以使用BindBuilder创建Binding,也可以直接new

接收@Test
    void binding() {
        //绑定队列news.china 和 交换器direct.news.china , 并且赋予一个routin key:new.china,之后exchange会根据消息的routing key来转发 
        Binding binding1 = BindingBuilder.bind(new Queue("news.china")).to(new DirectExchange("direct.news.china")).with("news.china");
        
        //同上
        Binding binding2 = BindingBuilder.bind(new Queue("news.usa")).to(new DirectExchange("direct.news.china")).with("news.usa");
        
		//绑定队列news.china 到 交换器topic.mail , 并且以new.*作为routing key 匹配
        //当topic.mail接受到这些消息的时候会往news.china转发:消息routing key为 news.global , news.univers , news.china , news.china
        Binding binding3 = BindingBuilder.bind(new Queue("news.china")).to(new TopicExchange("topic.mail")).with("news.*");
        
        //同上
        Binding binding4 = BindingBuilder.bind(new Queue("news.usa")).to(new TopicExchange("topic.mail")).with("news.*");
        
        //同上
        //不过当topic.ma接收接收到这些消息的时候会往news.china转发: 消息routing key为 mail.global , mail.china , mail.usa 
        Binding binding5 = BindingBuilder.bind(new Queue("mail.china")).to(new TopicExchange("topic.mail")).with("mail.*");
        
        //同上
        Binding binding6 = BindingBuilder.bind(new Queue("mail.usa")).to(new TopicExchange("topic.mail")).with("mail.*");
        amqpAdmin.declareBinding(binding1);
        amqpAdmin.declareBinding(binding2);
        amqpAdmin.declareBinding(binding3);
        amqpAdmin.declareBinding(binding4);
        amqpAdmin.declareBinding(binding5);
        amqpAdmin.declareBinding(binding6);
        
        //绑定队列news.usa和交换器fanout.news , fanout.new接收到所有消息都会玩new.usa转发
        amqpAdmin.declareBinding(new Binding("news.usa", Binding.DestinationType.QUEUE, "fanout.news", "fanout.news", null));
        
        //同上
        amqpAdmin.declareBinding(new Binding("news.china", Binding.DestinationType.QUEUE, "fanout.news", "fanout.news", null));
    }

发送消息

@SpringBootTest
public class SendTest {

    @Autowired
    AmqpTemplate amqpTemplate;

    @Test
    void directSend() {
        //向news.china发送一则消息,routing key 为 news.china
        amqpTemplate.convertAndSend("direct.news.china", "news.china", "hello world");
        
        //同上,不过routing key为news.usa
        amqpTemplate.convertAndSend("direct.news.china", "news.usa", "hello world");
    }
}

RabbitMq_06

@SpringBootTest
public class SendTest {

    @Autowired
    AmqpTemplate amqpTemplate;

    @Test
    void topicSend() {
        //topic.mail发送一则消息,routing key 为 news.weather , 由于topic.mail与 队列news.china news.usa 通过news.*进行了模糊匹配
        //news.weather匹配news.*,所以这则消息会被发送到这两个队列
        amqpTemplate.convertAndSend("topic.mail", "news.weather", "today is rainy");
        amqpTemplate.convertAndSend("topic.mail", "mail.work", "ddl is tomorrow");
    }

}

RabbitMq_07

@SpringBootTest
public class SendTest {

    @Autowired
    AmqpTemplate amqpTemplate;


    @Test
    void fanoutSend() {
        //fanout直接将接收到的所有消息发送到与之绑定的队列,所以routing key用test也无所谓
        amqpTemplate.convertAndSend("fanout.news", "test", "get message");
    }
}

RabbitMq_08

接收消息

@SpringBootTest
public class ReceiveTest {

    @Autowired
    AmqpTemplate amqpTemplate;

    
    //首先向fanout.news发数据,保证队列中有数据可取
    @Test
    void fanoutSend() {
        amqpTemplate.convertAndSend("fanout.news", "test", "get message");
    }

    @Test
    void receive(){
        //接收一条news.china中的数据
        Object object = amqpTemplate.receiveAndConvert("news.china");
        System.out.println("Objecct类型:"+object.getClass());
        System.out.println("Object内容:"+object);
    }
}
运行结果:
Objecct类型:class java.lang.String
Object内容:get message

其他

上面只是RabbitMq最基本的使用,有关SpringBoot的更详细的集成和使用以及RabbitMq的Ack机制,将在后续说明.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值