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的更多相关文章

  1. 消息队列rabbitmq/kafka

    12.1 rabbitMQ 1. 你了解的消息队列 rabbitmq是一个消息代理,它接收和转发消息,可以理解为是生活的邮局.你可以将邮件放在邮箱里,你可以确定有邮递员会发送邮件给收件人.概括:rab ...

  2. nodejs操作消息队列RabbitMQ

    一. 什么是消息队列 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已.其主要用途:不同进程Process/ ...

  3. 用过消息队列?Kafka?能否手写一个消息队列?懵

    是否有同样的经历?面试官问你做过啥项目,我一顿胡侃,项目利用到了消息队列,kafka,rocketMQ等等. 好的,那请开始你的表演,面试官递过一支笔:给我手写一个消息队列!!WHAT? 为了大家遇到 ...

  4. 消息队列比较-rabbitmq/kafka/rocketmq/ONS

    主要是比较这几种队列中间件: rabbitmq kafka rocketmq ONS 分以下几个维度来比较 高并发 毫无疑问KAFKA发消息的速度是最快的 ROCKETMQ/ONS次之 rabbitm ...

  5. 消息队列--RabbitMQ(一)

    1.消息队列概述 可以理解为保存消息的一个媒介/或者是个容器,与之相关有两个概念(即生产者(Publish)与消费者(Consumer)).所谓生产者,就是生产创造消息的一方,那么,消费者便是从队列中 ...

  6. kafka学习笔记(一)消息队列和kafka入门

    概述 学习和使用kafka不知不觉已经将近5年了,觉得应该总结整理一下之前的知识更好,所以决定写一系列kafka学习笔记,在总结的基础上希望自己的知识更上一层楼.写的不对的地方请大家不吝指正,感激万分 ...

  7. (一)RabbitMQ消息队列-RabbitMQ的优劣势及产生背景

    原文:(一)RabbitMQ消息队列-RabbitMQ的优劣势及产生背景 本篇并没有直接讲到技术,例如没有先写个Helloword.我想在选择了解或者学习一门技术之前先要明白为什么要现在这个技术而不是 ...

  8. C#中使用消息队列RabbitMQ

    在C#中使用消息队列RabbitMQ 2014-10-27 14:41 by qy1141, 745 阅读, 2 评论, 收藏, 编辑 1.什么是RabbitMQ.详见 http://www.rabb ...

  9. node使用消息队列RabbitMQ一

    基础发布和订阅 消息队列RabbitMQ使用 1 安装RabbitMQ服务器 安装erlang服务 下载地址 http://www.erlang.org/downloads 安装RabbitMQ 下载 ...

  10. 消息队列与Kafka

    2019-04-09 关键词: 消息队列.为什么使用消息队列.消息队列的好处.消息队列的意义.Kafka是什么 本篇文章系本人就当前所掌握的知识关于 消息队列 与 kafka 知识点的一些简要介绍,不 ...

随机推荐

  1. Linux下配置mail使用外部SMTP发送邮件

    修改/etc/mail.rc,增加两行:指定外部的smtp服务器地址.帐号密码等. # vi /etc/mail.rc set from=demo@qq.com smtp=smtp.qq.com se ...

  2. Python logging日志打印

    1.logging常用函数Logger.setLevel():设置日志级别Logger.addHandler()和Logger.removeHandler():添加和删除一个handlerLogger ...

  3. L26 使用卷积及循环神经网络进行文本分类

    文本情感分类 文本分类是自然语言处理的一个常见任务,它把一段不定长的文本序列变换为文本的类别.本节关注它的一个子问题:使用文本情感分类来分析文本作者的情绪.这个问题也叫情感分析,并有着广泛的应用. 同 ...

  4. 详解 stream流

    在本人之前的博文中,我们学习了 I/O流.NIO流的相关概念. 那么,在JDK8的更新内容中,提出了一个新的流 -- stream流 那么,现在,本人就来讲解下这个流: 目录 stream流 常用AP ...

  5. Upload-Labs 实验操作记录

    0x01 安装 下载:https://github.com/c0ny1/upload-labs 环境:简单搭建phpstudy环境即可,记得在upload-labs根目录下创建该文件夹 0x02 文件 ...

  6. Springboot:员工管理之修改员工(十(8))

    构建员工修改请求 com\springboot\controller\EmployeeController.java /*调转到员工修改页 携带员工信息 restful风格*/ @GetMapping ...

  7. mac 使用记录

    iterm 配合 lrzsz 实现 上传下载

  8. Redis分布式锁的正确姿势

    1. 核心代码: import redis.clients.jedis.Jedis; import java.util.Collections; /** * @Author: qijigui * @C ...

  9. Docker 安装 Jenkins , 并解决初始安装插件失败

    安装 Jenkins 后,初始化下载插件总是失败,导致安装不成功,重试好几次都是卡在安装插件那. 这里记录下 Docker 下怎么安装 Jenkins ,并解决初始安装插件失败问题. 安装插件失败,其 ...

  10. centos7在命令行下安装图形界面

    yum groupinstall "GNOME Desktop" "Graphical Administration Tools" ln -sf /lib/sy ...