1.大多应用中,可经过消息服务中间件来提高系统异步通讯、扩展解耦能力java
2.消息服务中两个重要概念:web
消息代理(message broker)即消息服务器 和目的地(destination)spring
当消息发送者发送消息之后,将由消息代理接管,消息代理保证消息传递到指定目的地。docker
3.消息队列主要有两种形式的目的地数据库
1.队列(queue):点对点消息通讯(point-to-point)api
2.主题(topic):发布(publish)/订阅(subscribe)消息通讯浏览器
场景1:异步处理服务器
1)网络
用户依次执行,在150ms后获得消息,缺点:发送时间很慢,发送邮件和注册短信不是下一ms立马执行的;多线程
2)
当用户将信息写入数据库使用多线程方式并发执行两种操做,时间相应100ms
3)
当用户将消息写进数据库,可将要使用的信息写入消息队列(这个操做是很短的),而后立马返回响应信息,用户感知55ms后,发送邮件和发送短信能够从消息队列中异步读取。
场景2:应用解耦
可将两个系统抽取出来,若是要使用将信息写入消息队列中,其余的系统只负责取;
场景3:流量削峰
10万人秒杀1w件商品,若是将全部的请求都处理,服务器会卡死,解决方法:用户秒杀请求发送,直接进入消息队列,可将消息设置为定长,10w用户谁快谁先进入队列,进步了的立马抛弃,至关于抢占了一个座位,而后再进行下一步处理。。。
消息发送者发送消息,消息代理将其放入一个队列中,消息接收者从队列中获取消息内容,消息读取后被移出队列
消息只有惟一的发送者和接受者,但并非说只能有一个接收者
注意:一旦B从消息队列中取出信息,则理解会删除,C、D、没法接收到
发送者(发布者)发送消息到主题,多个接收者(订阅者)监听(订阅)这个主题,那么就会在消息到达时同时收到消息
一、JMS(Java Message Service)JAVA消息服务:
基于JVM消息代理的规范。ActiveMQ、HornetMQ是JMS实现
二、AMQP(Advanced Message Queuing Protocol)
高级消息队列协议,也是一个消息代理的规范,兼容JMS
RabbitMQ是AMQP的实现
对比:
JMS | AMQP | |
---|---|---|
定义 | Java api | 网络线级协议 |
跨语言 | 否 | 是 |
跨平台 | 否 | 是 |
Model | 提供两种消息模型: (1)、Peer-2-Peer (2)、Pub/sub | 提供了五种消息模型: (1)、direct exchange (2)、fanout exchange (3)、topic change (4)、headers exchange (5)、system exchange 本质来说,后四种和JMS的pub/sub模型没有太大差异,仅是在路由机制上作了更详细的划分; |
支持消息类型 | 多种消息类型: TextMessage MapMessage BytesMessage StreamMessage ObjectMessage Message (只有消息头和属性) | byte[] 当实际应用时,有复杂的消息,能够将消息序列化后发送。 |
综合评价 | JMS 定义了JAVA API层面的标准;在java体系中,多个client都可以经过JMS进行交互,不须要应用修改代码,可是其对跨平台的支持较差; | AMQP定义了wire-level层的协议标准;自然具备跨平台、跨语言特性。 |
区别之一:两种规范提供的消息通讯机制都是基于点对点和发布订阅式,只是AMQP将发布订阅又分为4种, fanout exchange、topic change、headers exchange、system exchange
spring-jms:提供了对JM的支持
spring-rabbit:提供了对AMQP的支持
须要ConnectionFactory的实现来链接消息代理
提供JmsTemplate、RabbitTemplate来发送消息
两个注解
@JmsListener(JMS)、
@RabbitListener(AMQP)注解在方法上监听消息代理发布的消息
前提要@EnableJms、@EnableRabbit开启支持
Spring Boot自动配置
自动配置类
–JmsAutoConfiguration
–RabbitAutoConfiguration
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue Protocol)的开源实现。
消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其余消息的优先权)、delivery-mode(指出该消息可能须要持久性存储)等。
消息的生产者,也是一个向交换器发布消息的客户端应用程序。
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
Exchange有4种类型:direct(默认),fanout, topic, 和headers,不一样类型的Exchange转发消息的策略有所区别
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每一个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有本身的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在链接时指定,RabbitMQ 默认的 vhost 是 / 。
表示消息队列服务器实体
AMQP 中消息的路由过程和 Java 开发者熟悉的 JMS 存在一些差异,AMQP 中增长了 Exchange 和 Binding 的角色。生产者把消息发布到 Exchange 上,消息最终到达队列并被消费者接收,而 Binding 决定交换器的消息应该发送到那个队列。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-09Ll3Gzs-1571051304979)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1571050571215.png)]
Exchange类型
**Exchange分发消息时根据类型的不一样分发策略有区别,目前共四种类型:**direct、fanout、topic、headers。headers 匹配 AMQP 消息的 header 而不是路由键, headers 交换器和 direct 交换器彻底一致,但性能差不少,目前几乎用不到了,因此直接看另外三种类型:
1)Direct Exchange
消息中的路由键(routing key)若是和 Binding 中的 binding key 一致,
交换器就将消息发到对应的队列中。路由键与队列名彻底匹配,若是一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是彻底匹配、单播的模式。
2)Fanout Exchange
每一个发到 fanout 类型交换器的消息都会分到全部绑定的队列上去。fanout
交换器不处理路由键,只是简单的将队列绑定到交换器上,每一个发送到交换器的消息都会被转发到与该交换器绑定的全部队列上。很像子网广播,每台子网内的主机都得到了一份复制的消息。fanout
类型转发消息是最快的。
3)Topic Exchange
topic 交换器经过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列须要绑定到一个模式上。它将路由键和绑定键的字符串切分红单词,这些单词之间用点隔开。它一样也会识别两个通配符:符号“#”和符号“”。#匹配0个或多个单词**,****匹配一个单词。
下载:运行docker,输入命令docker pull rabbitmq:management(带有管理界面的RabbitMq)
docker pull rabbitmq:management
查看rabbitmq:
启动:**
docker上安装rabbitmq带界面的,manangment, (有两个端口)
5672:主机的5672映射到容器的5672
15672:管理界面访问web界面的
启动rabbitmq
docker run -d -p 5672:5672 -p 15672:15672 --name myrabbitmq 27764c8758a0
查看运行的容器:
浏览器访问:
这里密码用户名为guest
基于下图进行测试:
建立交换器(exchange)
添加消息队列(queues)
Binding规则
测试发送消息
1)dircet Exchange
queue接受到消息:
2)fanout exchange
每一个队列都能收到消息
3)topic exchange
根据匹配规则接收