消息队列1:RabbitMQ解析并基于Springboot实战
RabbitMQ简介
AMQP:Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。
RabbitMQ 是一个由Erlang语言开发的AMQP的开源实现。(PS:前几天有篇文章介绍了阿里P10的淘宝褚霸,就是erlang大神)。支持多种客户端。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点如下:
1、可靠性
RabbitMQ 使用一些机制来保证可靠性,如持久化,传输确认、发布确认。
2、灵活的路由
在消息进入队列之前,通过Exchange来路由消息。对于典型的路由功能,RabbitMQ 提供了内置的Exchange来实现。针对更复杂的路由功能。可以将多个Exchange 绑定在一起,也通过插件机制实现自己的 Exchange。
3、消息集群
多个RabbitMQ 服务器可以组成一个集群,形成一个逻辑Broker.
4、高可用
队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列任然可用。
5、多种协议
RabbitMQ支持多种消息队列协议。比如STOMP、MQTT等等
6、多语言客户端
RabbitMQ支持多种语言,比如java/Ruby等
7、管理界面
RabbitMQ提供了一个易用的用户界面。使得用户可有监控和管理Broker的许多方面
8、跟踪机制
如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出
9、插件机制
RabbitMQ提供了许多插件,从多方面进行扩展,也可以编写自己的插件
RabitMQ 概念模型
1、Message
消息,消息是不具名的,它由消息头和消息体组成,消息体是不透明的。而消息头则由一系列的可选属性组成。包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等
2、Publisher
消息的生产者,也是一个向交换器发布消息的客户端应用程序
3、Exchange
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
4、Binding
绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则。所以可以将交换器理解成一个由绑定构成的路由表。
5、Queue
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面。等待消息消费者连接到这个队列将其取走。
6、Connection
网络连接
7、Channel
信道,多路复用连接中的一条独立的双向数据流通道。
8、Consumer
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序
9、Virtual Host
虚拟主机、表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost 本质上就是一个mini版的RabbitMQ服务器。拥有自己的队列、交换器、绑定、和权限机制。vhost是AMQP概念的基础。必须在连接时指定,RabbitMQ默认的Vhost是/.
10、Broker
表示消息队列服务器实体。
Exchange 类型
Exchange 有四种类型:Direct、Topic、Headers 和 Fanout 。
- Direct:该类型的行为是“先匹配,再投送”,即在绑定时设定一个 routing_key,消息的routing_key 匹配时,才会被交换器投送到绑定的队列中去。
- Topic:按规则转发消息(最灵活)。
- Headers:设置 header attribute 参数类型的交换机。
- Fanout:转发消息到所有绑定队列。
headers 交换器和 direct 交换器完全一致,但性能差很多,目前几乎用不到了,这里不再详细介绍
Driect
Direct Exchange 是 RabbitMQ 默认的交换机模式,也是最简单的模式,根据 key 全文匹配去寻找队列。
消息中的路由键(routing key)如果和 Binding 中的 binding key 一致, 交换器就将消息发到对应的队列中。路由键与队列名完全匹配.它是完全匹配、单播的模式。
Topic
Topic Exchange 转发消息主要是根据通配符。在这种交换机下,队列和交换机的绑定会定义一种路由模式,那么,通配符就要在这种路由模式和路由键之间匹配后交换机才能转发消息。
在这种交换机模式下:
- 路由键必须是一串字符,用句号(.)隔开,如 agreements.us,或者 agreements.eu.stockholm 等。
topic 和 direct 类似,只是匹配上支持了“模式”,在“点分”的 routing_key
形式中,可以使用两个通配符:
*
表示一个词。#
表示零个或多个词。
Fanout
Fanout Exchange 消息广播的模式,不管路由键或者是路由模式,会把消息发给绑定给它的全部队列,如果配置了routing_key
会被忽略。
代码实战
此部分代码基于springboot进行,全部代码放到github上
Spring Boot 集成 RabbitMQ 非常简单,仅需非常少的配置就可使用,Spring Boot 提供了 spring-boot-starter-amqp 组件对MQ消息支持。
简单使用
(1)配置 pom 包,主要是添加 spring-boot-starter-amqp 的支持。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
(2)配置文件,配置 rabbitmq 的安装地址、端口及账户信息。
spring.application.name=spirng-boot-rabbitmq
spring.rabbitmq.host= localhost
spring.rabbitmq.port= 5672
spring.rabbitmq.username=allen
spring.rabbitmq.password=123456
server.port=8080
(3)定义队列
@Configuration
public class RabbitConfig {
@Bean
public Queue Queue() {
return new Queue("hello");
}
}
(4)发送者
AmqpTemplate 是 Spring Boot 提供的默认实现。
@RestController
public class HelloSender {
@Autowired
private AmqpTemplate amqpTemplate;
@GetMapping(value = "/sendString")
public String sendString() {
//发送消息 String routingKey, Object object
amqpTemplate.convertAndSend("hello", "hello rabbitMQ");
return "消息已发送";
}
@GetMapping(value = "/sendObject")
public String sendObject() {
//发送消息 String routingKey, Object object
UserEntity userEntity = new UserEntity();
userEntity.setName("allen");
userEntity.setAddress("山东济南");
amqpTemplate.convertAndSend("hello", userEntity);
return "消息已发送";
}
(5)接收者
注意使用注解@RabbitListener
,使用 queues 指明队列名称,@RabbitHandler
为具体接收的方法。
@Component
@RabbitListener(queues = "hello")
@Slf4j
public class HelloReceiver {
@RabbitHandler
public void process(String hello) {
log.info("消息接受为:{}",hello);
}
@RabbitHandler
public void process(UserEntity userEntity) {
log.info("消息接受为:{}",userEntity);
}
}
(5)访问结果
com.zhb.direct.HelloReceiver : 消息接受为:hello rabbitMQ
com.zhb.direct.HelloReceiver : 消息接受为:UserEntity(name=allen, address=山东济南)
Topic Exchange
(1)定义队列、交换机并绑定
/**
* @author: curry
* @Date: 2018/9/5
*/
@Configuration
public class TopicRabbitConfig {
final static String message = "topic.message";
final static String messages = "topic.messages";
//定义队列
@Bean
public Queue queueMessage() {
return new Queue(TopicRabbitConfig.message);
}
@Bean
public Queue queueMessages() {
return new Queue(TopicRabbitConfig.messages);
}
//exchange
@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}
//将队列和交换机进行绑定
@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}
@Bean
Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}
}
(2)发送者
/**
* @author: curry
* @Date: 2018/9/5
*/
@RestController
public class Sender {
@Resource
private AmqpTemplate rabbitTemplate;
@GetMapping(value = "send1")
public void send1(){
String context = "hi, i am message1";
rabbitTemplate.convertAndSend("exchange","topic.message",context);
}
@GetMapping(value = "send2")
public void send2(){
String context = "hi, i am message2";
rabbitTemplate.convertAndSend("exchange","topic.messages",context);
}
(3) 接受者
/**
* @author: curry
* @Date: 2018/9/5
*/
@Slf4j
@Component
@RabbitListener(queues = "topic.message")
public class Receiver1 {
@RabbitHandler
public void process(String message) {
log.info("topic Receive1:{}", message);
}
}
/**
* @author: curry
* @Date: 2018/9/5
*/
@Slf4j
@Component
@RabbitListener(queues = "topic.messages")
public class Receiver2 {
@RabbitHandler
public void process(String message) {
log.info("topic Receive2:{}", message);
}
}
其余代码不再演示,完整代码见github
完整代码:github
好了,玩的开心!
参考资料
[1]-https://www.jianshu.com/p/79ca08116d57
消息队列1:RabbitMQ解析并基于Springboot实战的更多相关文章
- rabbitMQ消息队列 – Message方法解析
消息的创建由AMQPMessage对象来创建$message = new AMQPMessage("消息内容");是不是很简单. 后边是一个数组.可以对消息进行一些特殊配置$mes ...
- RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙
消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...
- Spring Boot 揭秘与实战(六) 消息队列篇 - RabbitMQ
文章目录 1. 什么是 RabitMQ 2. Spring Boot 整合 RabbitMQ 3. 实战演练4. 源代码 3.1. 一个简单的实战开始 3.1.1. Configuration 3.1 ...
- 消息队列系统 -- RabbitMQ
消息队列系统 -- RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Que ...
- 消息队列之 RabbitMQ
https://www.jianshu.com/p/79ca08116d57 关于消息队列,从前年开始断断续续看了些资料,想写很久了,但一直没腾出空,近来分别碰到几个朋友聊这块的技术选型,是时候把这块 ...
- 转 消息队列之 RabbitMQ
转 https://www.jianshu.com/p/79ca08116d57 消息队列之 RabbitMQ 预流 2017.05.06 16:03* 字数 4884 阅读 80990评论 18喜欢 ...
- 快速入门分布式消息队列之 RabbitMQ(1)
目录 目录 前言 简介 安装 RabbitMQ 基本对象概念 Message 消息 Producer 生产者 Consumer 消费者 Queue 队列 Exchange 交换机 Binding 绑定 ...
- 消息队列之rabbitmq学习使用
消息队列之rabbitmq学习使用 1.RabbitMQ简介 1.1.什么是RabbitMQ? RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,Rabb ...
- 消息队列之 RabbitMQ【验证通过】
消息队列之 RabbitMQ 预流 关注 22.9 2017.05.06 16:03* 字数 4884 阅读 284691评论 41喜欢 618赞赏 2 关于消息队列,从前年开始断断续续看了些资料, ...
随机推荐
- 浅谈SDN架构下的运维工作
导读 目前国内的网络运维还处于初级阶段,工作人员每天就像救火一样,天天疲于奔命.运维人员只能埋头查找系统运行的日志,耗时耗力,老眼昏花不说,有时候忙了半天还一无所获,作为运维工程师的你,有木有遇到过类 ...
- Python2.7-canlendar
calendar模块的主要功能是针对万年历.星期几的,此外模块内还有方便的判断闰年.获取月份名.星期名的方法 1.模块的类 1.1.calendar.Calendar([firstweekday]) ...
- JAVA 对基础知识的加强
一.我们在写类的时候.设置字段的时候含义: 简单的javabean类: package jd.com.vo; import jd.com.mybaitstest.account; public cla ...
- 关于YARN Node Labels的一点理解
最近在做实验,实验需要进行分区域计算,网上查了资料后发现Yarn Node Labels + Capacity-Scheduler可以实现我的需求 但是当任务提交到capacity-scheduler ...
- php删除文件夹和其下的内容
原文地址:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/05/13/2045158.html <?php function del ...
- C#可空类型(转载)
在程序开发中,有时候需要值类型也为可空类型,比如,在数据库中,我们可以把一个日期Datetime设置为null. 在C# 2.0中就出现了可空类型,允许值类型也可以为空(null),可空类型的实现基于 ...
- 云计算背后的秘密:NoSQL诞生的原因和优缺点
转载收藏一篇对nosql讲解的比较全面的文章:http://blog.csdn.net/xlgen157387/article/details/47908797 这篇文章将和大家聊聊为什么NoSQL会 ...
- Luogu P1113 杂务
终于没有打模板题了. 一道简单的拓扑题目(但记得以前第一次做的时候爆0了). 发现这个做事的过程是按一定顺序的,然后如果一个工作的前面没有任何事情的话,它一定先被完成(如果不的话就不能使时间最小化,其 ...
- 备忘:BLOCK CORRUPTION IN SYSTEM DATAFILE
http://www.onlinedbasupport.com/2010/12/10/block-corruption-in-system-datafile/
- flask前端与后端之间传递的两种数据格式:json与FormData
json格式 双向! 前端 ==>后端:json格式 后端 ==>前端:json格式 html <!-- html部分 --> <form enctype='applic ...