消息队列,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 知识点的一些简要介绍,不 ...
随机推荐
- python3(五) if
age = 20 if age >= 18: print('your age is', age) print('adult') # 如果if语句判断是True,就把缩进的两行print语句执行了 ...
- 数据库里账号的密码,需要怎样安全的存放?—— 密码哈希(Password Hash)
最早在大学的时候,只知道用 MD5 来存用户的账号的密码,但其实这非常不安全,而所用到的哈希函数,深入挖掘,也发现并不简单-- 一.普通的 Hash 函数 哈希(散列)函数是什么就不赘述了. 1.不推 ...
- 逻辑对象中时间类型 保存时 隐藏bug
开发功能中的一些逻辑对象中的一些时间 属性,在保存数据库时有一个隐藏的bug,假如 我vo属性定义的就是date 类型,那我定时保存数据库时可能就会出错,eq:假如这个属性隔天要重置一些东西,表中这个 ...
- ffmpeg使用ss与t参数对视频进行剪辑
ffmpeg能够实现对视频进行剪辑操作,ss为指定视频剪切开头的起始时间,t制定视频的总长度,ss与t的单位均为:秒. ffmpeg -ss 7200 -i 1080p.mp4 -c copy -t ...
- JMF 下载安装与测试 测试成功
本来就是想在自己写的java里面加入实习的摄像头监控,然后个各种百度了一下,就用JMF来弄了,不过这个东西貌似比较旧,网上的资料虽然说有,但是也不是太多,并且遇到的一下问题也不能解决,总之经过了一天的 ...
- 深度学习之文本分类模型-前馈神经网络(Feed-Forward Neural Networks)
目录 DAN(Deep Average Network) Fasttext fasttext文本分类 fasttext的n-gram模型 Doc2vec DAN(Deep Average Networ ...
- Gatling 条件判断
在使用Gatling的过程中,当前置接口异常,无法获取到数据作为其他接口的请求参数室,接口是不能请求的.或者通过feeder获取的数据要区分不同的情况请求不同的接口.此时,使用gatling的判断语句 ...
- Linux下nginx自启动配置
1.在linux系统的/etc/init.d/目录下创建nginx文件 vim /etc/init.d/nginx 在脚本中添加一下命令(内容主要参考官方文档) #!/bin/sh # # nginx ...
- 2. node xlsx的使用
1. 使用xlsx模块 const xlsx = require('xlsx'); //excel async exportexcel() { let arrayData = [ ['姓名', '电话 ...
- UML 建模工具的安装与使用
一. 实验目的1) 学习使用 EA(Enterprise Architect) 开发环境创建模型的一般方法: 2) 理解 EA 界面布局和元素操作的一般技巧: 3) 熟悉 UML 中的各种图的建立和表 ...