消息队列,RabbitMQ、Kafka、RocketMQ
1、消息列队概述
1.1消息队列MQ
MQ全称为Messages Queue ,消息队列是应用程序和应用程序之间的通信方法
为什么使用MQ?
在项目中,可将一些无需耗时的操作提取出来,进行异步操作,而这种异步处理方式大大的姐生了服务器的请求响应时间,从而提高了系统的吞吐量。
开发中消息列队通常有以下应用场景
1.任务异步处理
将不需要同步处理的斌且好使长的操作由消息队列通知消息接收方进行异步处理。提高了应用的响应时间
2.应用程序解耦合
MQ相当于一个中介,生产放通过MQ与消费方交互,它将应用程序进行解耦合

1.2AMQP和JMS
MQ是消息通信模型;实现MQ的大致有两种主流方式:AMQP、JMS
1.2.1AMQP
六种消息模式
AMQP是高级消息队列协议,是一个进程间传递异步消息的网络协议,更准确的说是一种binary wire-level protocol(链接协议)。这是和JMS的本质区别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式
1.2.2JMS
两种消息模式
JMS即JAVA消息服务应用程序接口,是一个java平台中关于面向消息中间件的API,用于在两个应用程序之间,或分布系统中发送消息,进行异步通信
1.2.3AMOP 与 JMS 区别
· JMS 是定义了统的接口,来对消息摄作进行统一,AMQP是通过规定协议来统一统一数据交互的格式
· JMS 限定了必须使用 Java 语宫: AMQP只是协议,不规定实现方式.因此是跨语宫的.
· JMS 规定了两种消息模式(点对点模式,订阅模式):而 AMQP的消息模式更加丰富
1.3消息队列产品
市场上常见的息队列有如下:
目前市面上成熟主流的MQ有Kafka、RocketMQ、RabbitMQ,我们这里对每款款MQ做一个简介绍。
1.3.1 Kafka
所有开源的MQ,吞吐量最强的,天然支持集群,消息堆积能力非常强悍
Apache下的一个子项目,使用scala语言实现的一个高性能分布式Publish/Subscribe消息队列系统
1.快速持久化:通过磁盘顺序读写与零拷贝机制,可以在0(1)的系统开销下进行消息持久化
2.高吞吐:在一台普通的服务器上即可以达到10W/s的吞吐速率。
3.高堆积:支持topoc下消费者较长时间离线,消息堆积量大
4.完全的分布式系统:Brocker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡
5.支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分系统,但又要求实时处理的限制,这是一个可行的解决方案
1.3.2 RocketMQ
RocketMQ国产阿里的,经过双十一的检验。也非常强悍,基于java语言写的
RocketMQ的前身是Metaq,当Metaq3.0发布时,产品名称改为RocketMQ.RocketMQ是一款分布式、队列模型的消息中间件
1.能够保证严格的消息顺序
2.提供丰富的消息拉取模式
3.高效的订阅水平扩展能力
4.实时的消息订阅机制
5.支持事务消息
6.亿级消息堆积能力
1.3.3RabbitMQ
使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP,SMTP,STOMP,正是如此使它变得非常重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由,负载均衡、数据持久化都有很好的支持。多用于进行企业级的ESB整合。
1.4RabbitMQ
RabbitMQ是erlang语言开发,基于AMQP(Advanced Message Queue高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的涌信方法,消息队列在分布式系统开发中应用非常广乏
RabbitMQ官方地址:http://www.rabbitmq.com/
RabbitMQ提供了6种模式:
1.简单模式
2.work工作模式
3.publish/Subscribe发布与订阅模式
4.Routing路由模式
5.Topics主题模式
6.RPC远调用模式(远程调用,不太算MQ;不作介绍)

简单模式
一个生产者,一个消费者

工作模式
一个生产者、2个消费者。
一个消息只能被一个消费者获取。

订阅模式
解读:
1、1个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机。交换机分别都发送给队列
4、每个队列都要绑定到交换机
5、生产者发送的消息,经过交换机,到达队列,实现,一个消息被多个消费者获取的目的
注意:一个消费者队列可以有多个消费者实例,只有其中一个消费者实例会消费
交换机(图中X):只负责转发消息,不具备储备消息的能力。一方面接收生产者P的消息,另一方面处理消息(发送给队列,或者特定队列,或者丢弃),取决于交换机的类别
交换机的类别:
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定的队列中
Topic:通配符,把消息交给符合routing pattern(路由模式)的队列

路由模式
1.队列与交换机的绑定,不能是任意绑定了,而是要指定一个routingkey(路由key)
2.消息的发送方在 向 Exchange(交换机图中X)发送消息时,也必须指定消息的RoutingKey
3.交换机不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routing与消息的Routing Key 完全一致,才会接收到消息

图解:
P:生产者
X:交换机
C1:消费者,指定所在队列需要routing key为error的消息
C2:消费者,指定所在队列需要routing key为info,erroe,warning的消息
通配符模式(主题模式)
可以根据Routingkey把消息路由到不同的队列。只不过通配符类型交换机可以让队列在绑定routing key的时候使用通配符
routingkey一般都是由一个或多个单词组成,多个单词之间以‘.’点分割,例如:item.add.hello
通配符规则:
#:匹配一个或多个词
*:匹配一个词
举例:
item.#:能够匹配item.index.add或者item.index
itrm.*:只能匹配item.index或者item.xxx

2.安装及配置RabbitMQ
用户角色
1、超级管理员(administrator)
可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
2、监控者(monitoring)
可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
3、策略制定者(policymaker)
可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
4、普通管理者(management)
仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
5、其他
无法登陆管理控制台,通常就是普通的生产者和消费者。
3.python使用RabbitMQ
轮询消费模式
此模式下,发送队列的一方把消息存入mq的指定队列后,若有消费者端联入相应队列,即会获取到消息,并且队列中的消息会被消费掉。
若有多个消费端同时连接着队列,则会已轮询的方式将队列中的消息消费掉。
接下来是代码实例:
producer生产者
# !/usr/bin/env python
import pika
credentials = pika.PlainCredentials('admin','123456')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'192.168.56.19',5672,'/',credentials))
channel = connection.channel()
# 声明queue
channel.queue_declare(queue='balance')
# n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
routing_key='balance',
body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()
发送过队列后,可在MQ服务器中查看队列状态
[root@localhost ~]# rabbitmqctl list_queues
Listing queues ...
hello 1
consumer消费者
# _*_coding:utf-8_*_
__author__ = 'Alex Li'
import pika
credentials = pika.PlainCredentials('admin','123456')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'192.168.56.19',5672,'/',credentials))
channel = connection.channel()
# You may ask why we declare the queue again ‒ we have already declared it in our previous code.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
# was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs.
channel.queue_declare(queue='balance')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback,
queue='balance',
no_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
接收队列后,查看一下队列状态
[root@localhost ~]# rabbitmqctl list_queues
Listing queues ...
hello 0
队列持久化
当rabbitMQ意外宕机时,可能会有持久化保存队列的需求(队列中的消息不消失)。
producer
# Cheng
# !/usr/bin/env python
import pika
credentials = pika.PlainCredentials('admin','123456')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'192.168.56.19',5672,'/',credentials))
channel = connection.channel()
# 声明queue
channel.queue_declare(queue='durable',durable=True)
# n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
routing_key='durable',
body='Hello cheng!',
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent
)
)
print(" [x] Sent 'Hello cheng!'")
connection.close()
执行后查看队列,记下队列名字与队列中所含消息的数量
[root@localhost ~]# rabbitmqctl list_queues
Listing queues ...
durable 1
#重启rabbitmq
[root@localhost ~]# systemctl restart rabbitmq-server
#重启完毕后再次查看
[root@localhost ~]# rabbitmqctl list_queues
Listing queues ...
durable #队列以及消息并未消失
执行消费者代码
cunsumer
# Cheng
# _*_coding:utf-8_*_
__author__ = 'Alex Li'
import pika
credentials = pika.PlainCredentials('admin','123456')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'192.168.56.19',5672,'/',credentials))
channel = connection.channel()
# You may ask why we declare the queue again ‒ we have already declared it in our previous code.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
# was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs.
channel.queue_declare(queue='durable',durable=True)
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(callback,
queue='durable',
#no_ack=True
)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
可正确接收到信息。
再次查看队列的情况。
[root@localhost ~]# rabbitmqctl list_queues
Listing queues ...
durable 0
广播模式
当producer发送消息到队列后,所有的consumer都会收到消息,需要注意的是,此模式下producer与concerned之间的关系类似与广播电台与收音机,如果广播后收音机没有接受到,那么消息就会丢失。
建议先执行concerned
concerned
# _*_coding:utf-8_*_
__author__ = 'Alex Li'
import pika
credentials = pika.PlainCredentials('admin','123456')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'192.168.56.19',5672,'/',credentials))
channel = connection.channel()
channel.exchange_declare(exchange='Clogs',
type='fanout')
result = channel.queue_declare(exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive=True会在使用此queue的消费者断开后,自动将queue删除
queue_name = result.method.queue
channel.queue_bind(exchange='Clogs',
queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
channel.start_consuming()
producer
import pika
import sys
credentials = pika.PlainCredentials('admin','123456')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'192.168.56.19',5672,'/',credentials))
channel = connection.channel()
channel.exchange_declare(exchange='Clogs',
type='fanout')
message = ' '.join(sys.argv[1:]) or "info: Hello World!"
channel.basic_publish(exchange='Clogs',
routing_key='',
body=message)
print(" [x] Sent %r" % message)
connection.close()
消息队列,RabbitMQ、Kafka、RocketMQ的更多相关文章
- 消息队列rabbitmq/kafka
12.1 rabbitMQ 1. 你了解的消息队列 rabbitmq是一个消息代理,它接收和转发消息,可以理解为是生活的邮局.你可以将邮件放在邮箱里,你可以确定有邮递员会发送邮件给收件人.概括:rab ...
- nodejs操作消息队列RabbitMQ
一. 什么是消息队列 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已.其主要用途:不同进程Process/ ...
- 用过消息队列?Kafka?能否手写一个消息队列?懵
是否有同样的经历?面试官问你做过啥项目,我一顿胡侃,项目利用到了消息队列,kafka,rocketMQ等等. 好的,那请开始你的表演,面试官递过一支笔:给我手写一个消息队列!!WHAT? 为了大家遇到 ...
- 消息队列比较-rabbitmq/kafka/rocketmq/ONS
主要是比较这几种队列中间件: rabbitmq kafka rocketmq ONS 分以下几个维度来比较 高并发 毫无疑问KAFKA发消息的速度是最快的 ROCKETMQ/ONS次之 rabbitm ...
- 消息队列--RabbitMQ(一)
1.消息队列概述 可以理解为保存消息的一个媒介/或者是个容器,与之相关有两个概念(即生产者(Publish)与消费者(Consumer)).所谓生产者,就是生产创造消息的一方,那么,消费者便是从队列中 ...
- kafka学习笔记(一)消息队列和kafka入门
概述 学习和使用kafka不知不觉已经将近5年了,觉得应该总结整理一下之前的知识更好,所以决定写一系列kafka学习笔记,在总结的基础上希望自己的知识更上一层楼.写的不对的地方请大家不吝指正,感激万分 ...
- (一)RabbitMQ消息队列-RabbitMQ的优劣势及产生背景
原文:(一)RabbitMQ消息队列-RabbitMQ的优劣势及产生背景 本篇并没有直接讲到技术,例如没有先写个Helloword.我想在选择了解或者学习一门技术之前先要明白为什么要现在这个技术而不是 ...
- C#中使用消息队列RabbitMQ
在C#中使用消息队列RabbitMQ 2014-10-27 14:41 by qy1141, 745 阅读, 2 评论, 收藏, 编辑 1.什么是RabbitMQ.详见 http://www.rabb ...
- node使用消息队列RabbitMQ一
基础发布和订阅 消息队列RabbitMQ使用 1 安装RabbitMQ服务器 安装erlang服务 下载地址 http://www.erlang.org/downloads 安装RabbitMQ 下载 ...
- 消息队列与Kafka
2019-04-09 关键词: 消息队列.为什么使用消息队列.消息队列的好处.消息队列的意义.Kafka是什么 本篇文章系本人就当前所掌握的知识关于 消息队列 与 kafka 知识点的一些简要介绍,不 ...
随机推荐
- 《MySQL实战45讲》学习笔记4——MySQL中InnoDB的索引
索引是在存储引擎层实现的,且在 MySQL 不同存储引擎中的实现也不同,本篇文章介绍的是 MySQL 的 InnoDB 的索引. 下文将以这张表为例开展. # 创建一个主键为 id 的表,表中有字段 ...
- intellJ svn控制错误
电脑突然蓝屏了,重启打开intellj 后原本好好的项目是可以用intellj更新或者提交的,现在却都不能了,如图: 如上图:svn地址里是空白的,应该显示: 那到底是什么情况呢,就因为电脑崩溃了in ...
- Redis学习三:Redis高可用之哨兵模式
申明 本文章首发自本人公众号:壹枝花算不算浪漫,如若转载请标明来源! 感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫 22.jpg 前言 Redis 的 Sentinel 系统用于管理多个 Redi ...
- 怎么在执行Python脚本时,密码等敏感信息也不让它出现
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...
- U - Obtain a Permutation CodeForces - 1294E 思维
题解: 注意每一列与每一列之间互不影响,所以贪心地求出没一列的最小操作值,然后累加起来. 怎么求没一列的最小值呢?维护一个数组same表示其中same[i]=j表示将该序列向上翻滚i次有j个元素归位, ...
- 安卓虚拟定位软件Fake Location重大更新
前段时间网上找安卓虚拟定位的软件,找了很久,大部分都是多开修改APP,或者是不可用的,最后在KUAN找到一个作者Lerist做的虚拟定位软件 Fake Location ,配合作者本人的一键解锁sys ...
- Matlab学习-(2)
1. 文件读取 在编写一个matlab项目时候,通常要导入很多不同格式的数据,下面我们来学习不同的导入函数.(1) 保存工作区MATLAB支持工作区的保存.用户可以将工作区或工作区中的变量以文件的形式 ...
- [YII2] 文件上传类
//测试文件上传类 public function actionCreate() { $model = new Lvyou(); $upload_model = new \app\models\Upl ...
- 移动(appium)自动化测试-爬虫的另一种手段
appium自动化测试环境搭建: 1.Python环境(推荐2.7)和jdk. 2.Adb工具的下载:自己单独下载adb.夜神模拟器自带和Android sdk 3.Apk安装介质:真机.Androi ...
- ubuntu17.10安装lnmp安装包的核心问题-gcc版本、g++版本
大致碰到的问题都是这样,不是php安装失败,就是MySQL安装失败,或者Nginx也安装失败 基本上是花式报错.后来在军哥的论坛中找到了这个帖子:https://bbs.vpser.net/viewt ...