赞
踩
Message Queue -消息队列,队列这个东西就是类似一个list的结构。
1:数据可以从队列的头进入,从队列尾部出,这种是先进先出的队列;
2:数据从队列头部入队,然后也是从列头取数据,这种就是先进后出的队列;也是典型的栈结构
3:数据既可以从列头、列尾入队和出队,那么这种就是双端队列
1.大多数应用中,可通过消息服务中间件来提升系统异步通信能力,扩展解耦能力,
2.消息服务中间件中有两个重要的概念:消息代理(message broker就是部署了MQ的服务器)、目的地(destination)
3.当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地。
4.点对点式
5. 发布订阅式
6.JMS(JAVA Message Service)JAVA消息服务
7.AMQP(Advanced Message Queuing Protocol)
高级消息队列协议,也是一个消息代理的规范,兼容JMS
RabbitMQ是AMQP的实现
JAVA的JDK中是自带队列的,但是是基于内存级别的队列,无法脱离项目单独使用;在现在分布式横行的时代,需要一个公共的中间件,如A服务存,B服务、C服务需要取,那么就可以使用消息中间件-RabbitMQ
RabbitMQ由来: RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue Protocol)的开源实现。
核心概念:
Message
消息是不具名的,它由消息头和消息体组成,消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing- key(路由键) 、priority (相对于其他消息的优先权)、delivery-mode
(指出该消息可能需要持久性存储)等。
Publisher
消息的生产者,也是一个向交换器发布消息的客户端应用程序。
Exchange
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。Exchange有4种类型: direct(默认),
fanout, topic,和headers,不同类型的Exchange转发消息的策略有是有区别的
Queue
逍息队列,用来保存逍息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队,。消息存在
列量面,等得消费者连接到这个队列将消息取走。
Binding
绑定消息队列和交换机的关系。就是基王路由和交换机和消息队列连及起来的路由规则,所以可以将交换机理解为一个由绑定构成的路由表。Exchange和Queue的绑定可以是多对多的关系。
Connection
网络连接,比如一个TCP连接
Channel
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚举接, AMQP命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成,因为对于操作统来说建立和销毁TCP都是非常需贵的开销,所以引人了信道的概念,以复用一条TCP连接。
Consumer
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在连接时指定,RabbitMQ默认的vhost是/
Broker
表示消息队列服务器实体
一个客户端只会建立一条连接,此链接为长连接,虚拟主机是相互隔离的,这里建立长链接的优点:一旦当消费者掉线后,链接中断后消息代理服务器能够立马感知到有消费者下线,这是的派发消息就会存储起来,不会造成消息的大面积丢失
异步处理
1.同步模式:注册数据写入数据库->发送注册邮件->发送短信验证码=累计耗时150ms
2.异步线程模式:注册数据写入数据库异步执行->发送邮件+发送短信(这里可以是使用任务编排,只需要等待耗时最长的)=累计耗时100ms
3.队列模式:注册数据写入数据库->直接写入消息队列<-邮件服+短信服同时监听并执行业务=累计耗时55ms
应用解耦
传统方式:订单系统处理完了调用库存系统,只要库存系统升级,那么订单系统就需要跟着修改
消息中间件方式:订单系统下了订单,直接将消息投递到消息队列,库存系统收到订阅消息后自动处理对应逻辑!
流量控制
针对高并发请求,当大量请求进来时,服务端业务处理耗时长了会阻塞,可能就会导致服务器资源耗尽,导致宕机!此时可以使用消息中间将这些请求存入消息队列中,服务端真正处理业务逻辑的服务器就去订阅消息队列,从消息队列中一个一个消息取出来执行对应的任务!
docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management
4369,25672(Erlang发现&集群端口)
5672,5671(AMQP端口)
15672(web管理后台端口)
61613,61614(STOMP协议端口)
1883,8883(MQTT协议端口)
RabbitMQ官网
访问地址http://192.168.0.177:15672 用户名/密码:guest
Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct, fanout, topic, headers,headers匹配AMOP消息的header而不是路由键, headers交换器和direct交换器完全一致,但性能差很多,目前几乎用不到了,所以直接看另外三种类型
direct
消息中的路由键(routing key)如果和Binding中的binding-key一致,交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为. “dog”,则只转发routing key标记为"dog"的消息,不会转发"dog.puppy",也不会转发"dog-guard"等等。它是完全匹配、单播的模式。
fanout
每个发到fanout类型交换器的消息都会分到所有绑定的队列上去。fanout交换器不处理路由键,只是简单的将队列绑定到交换器上,每个发送到交换器的消息都公被转发到与该交换器绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息. fanout类型转发消息是最快的。
topic
交换器通过模式匹配分配消息的路山键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“*”。#匹配0个或多个单词, *匹配一个个单词。
创建一个交换机
Type:交换机的类型
Durability:持久化类型,默认的就是持久化的,(就是重启后还存在)
Auto delete:是否自动删除(如果是,交换器将在至少一个队列或交换器绑定到这个队列或交换器之后删除自己,然后解除所有队列或交换器的绑定。)
Internal:是否是内部交换机,默认不是(如果是内部交换机的话那么就不能收发消息,只能作为内部的路由或者转发使用)
创建一个队列
Type:交换机的类型
Durability:持久化类型,默认的就是持久化的,(就是重启后还存在)
Auto delete:是否自动删除(如果是,交换器将在至少一个队列或交换器绑定到这个队列或交换器之后删除自己,然后解除所有队列或交换器的绑定。)
交换机-队列绑定
点击进入创建好的交换机
交换机可以和交换机绑定,也可以和队列绑定,如果绑定的是交换机,那么消息就会传递给绑定的交换机,然后到达绑定的队列
Routing key:路由键
1.创建4个队列
3.绑定队列
绑定test队列
绑定test.a
绑定test.b
绑定pp.a
初始化队列数据列表
发送消息,测试绑定的那些队列能收到消息
查看队列
这里使用的是直接类型交换机-direct所以是只有路由键完全相等才能接收消息
查看队列接收的消息,点击test.a,进入队列!
消息时取出来了,我们回到队列列表中!
发现队列中的消息还在!原因是取消息的时候类型的问题
第一次获取消息的类型是获取消息然后有从新塞回队列,这次是获取到消息不从新塞回队列!
再次查看队列情况!
队列中的消息被消费了
这个就是将消息传递到所有绑定的队列!
创建一个fanout类型交换机
绑定所有队列
使用test.a发送测试消息
查看队列情况
4个队列都能收到消息,这里使用的是fanout广播类型的,就算路由键不写那么与其交换机绑定的所有队列都能收到消息
创建topic交换机
绑定队列
test.#:这种路由键会匹配以test开头的后面任意单词
*.a:这是前面必须有一个任意单词,后面以a结尾的
路由键为test.a发送测试消息
查看队列情况
这里所有队列都收到了消息,原因是test、test.a、test.b匹配到路由键中的test;pp.a则匹配到路由键中的a,所有所有队列都能收到消息!
路由键为hello.a发送消息
查看队列情况
这里只有pp.a队列能收到消息!因为他的路由键是*.a那么hello.a就只能匹配到pp.a,这里容易搞混和test.a的关系,exchanges.topic交换机中和test.a使用的是test.#绑定的路由键,而这个路由键是必须以test开头,所以hello.a是无法匹配上test.#路由建绑定的队列的!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。