一发一存一消费,没有最好的消息队列中间件(简称消息中间件),只有最合适的消息中间件。
消息队列经常使用的使用场景:php
非实时性
:当不须要当即得到结果,可是并发量又须要进行控制的时候,差很少就是须要使用消息队列的时候。主要解决了应用耦合、异步处理、流量削锋等问题。应用耦合
:多应用间经过消息队列对同一消息进行处理,避免调用接口失败致使整个过程失败;(如:订单->库存)异步处理
:多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减小处理时间;(点对多场景,广播场景(注册发短信,发邮件)等等)限流削峰
:应用于秒杀或抢购活动中,避免流量过大致使应用系统挂掉的状况;(根据服务承受度设置队列大小,超过了就返回活动结束了,我们常常各大商城秒杀,内心尚未点B数吗)减小压力,避免服务挂掉。消息驱动的系统
:系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理;(分工处理(各自对应相应的队列),灵活应用(收到就处理/定时处理))消息队列是异步RPC的主要手段之一java
两种模式:python
点对点
:每一个消息只有一个消费者(Consumer),不可重复消费(一旦被消费,消息就再也不在消息队列中)发布/订阅
:公众号(Topic),大伙(订阅者)订阅关注以后,公众号运营平台(发布者)发布信息后,大伙就都收到信息了,这里其实还分pull/push的。一个是主动推送,一个是被动拉取基于发布/订阅模式作扩展就是横向扩展,多个队列及消费分组订阅(提升消费能力)
pull
:主动权在于消费方,优势是按需消费(吃自助餐,能吃多少拿多少),并且服务端队列堆积的消息处理也相对简单(不用记录状态啊,状态都消费端);缺点就是消息延迟(不知道啥时候去拉取更新),这时候有小伙伴会问,那为啥不叫服务端通知一下呢(有句话叫不在其位不谋其政,服务端通知必然要记录通知状态和增长之间的通讯带宽;固然也能够根据实际状况来选择和push组合起来用(男女搭配干活不累嘛)来提升消息的实时性)push
:主动权就在服务方了,优势是实时性高,服务端能够统一管理来进行负载,不过也容易致使慢消费(就得考虑消费方受不受得了,毕竟你说你了解,但也只有对方才清楚你有多了解);缺点就是发送消息的状态是集中式管理,压力大啊(要分发消息还要记录状态还要作备份,又当爹来又当妈,你说累不累)对于顺序消息,这种场景有限且成本过高的方式就得慎重考虑了,对那种全局有序但容许出现小偏差的场景(日志推送),pull模式就很是适合了(因此说kafka为啥经常使用于日志处理、大数据等方面),要问为何?本身去领悟
实际开发中消息中间件选型基于几个方面:c++
功能
:这个就多了,优先级队列、延迟队列(划分不一样的延迟队列来避免从新排序消耗性能,缺点嘛本身悟)、死信队列(放没有推送成功的)、消费模式(pull/push)、广播消费、消息回溯(可追溯嘛,否则被卖了都不知道是谁)、消息堆积+持久化、消息追踪(链路条,方便定位)、消息过滤(根据规则过滤啊,不一样类别消息发送到不一样topic)、多协议支持(通用性)、跨语言支持(流行程度)、流量控制(嘿嘿嘿,上面有)、消息顺序性(还要再说一遍?)、安全机制(身份认证,权限认证(读写))、消息幂等性(承诺知道不,答应人家的事就必定要作到)、事务性消息(不想说)等性能
:通常是指其吞吐量(统一大小的消息体和不一样大小的消息体生产和消耗能力),性能和功能不少时候是相悖的,鱼和熊掌不可兼得。高可靠、高可用
:先说可靠,主要在于消息的持久化这一块(消息只要写入就必定会被消费,不会由于故障致使数据丢失(这个就很好测试出来了吧))。若是是从系统的角度来看就得从总体的维度去衡量了(不能单单只靠消息中间件自己,要从生产端、服务端、消费端三个维度去保障)。运维
:一般有审核评估啊、监控啊、报警提醒啊、容灾啊、扩容啊、升级部署等等,一方面看中间件支撑的维度,一方面就看结合自动化运维的难易度社区力度及生态发展
:这个好理解吧,使用开源框架最开始基本上愉快的奔跑,但时不时的总会掉坑里,能不能爬出来一方面看自身的实力,一方面就看社区的力度了成本
: 尽可能贴合团队自身的技术栈体系,让一个C栈的团队去深挖zeroMQ总比scala编写kafka要容易的多先贴一个图(网上Q来的),一些功能支不支持主要取决于它使用的模式,看完上面详细说明应该就比较清楚
git
先从比较有表明性的两个MQ(rabbitMQ,kafka),功能对比(图仍是Q来的)
github
应用方面:web
架构模型方面:redis
AMQP协议
,RabbitMQ的broker由Exchange,Binding,queue组成,其中exchange和binding组成了消息的路由键;客户端Producer经过链接channel和server进行通讯,Consumer从queue获取消息进行消费(长链接,queue有消息会推送到consumer端,consumer循环从输入流读取数据)。rabbitMQ以broker为中心;有消息的确认机制。吞吐量:shell
可用性方面:数据库
集群负载均衡方面:
基于erlang开发
是采用Erlang语言实现的AMQP协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息。RabbitMQ发展到今天,被愈来愈多的人承认,这和它在可靠性、可用性、扩展性、功能丰富等方面的卓越表现是分不开的。
优势:
缺点:
基于java开发
是Apache出品的、采用Java语言编写的彻底基于JMS1.1规范的面向消息的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通讯。不过因为历史缘由包袱过重,目前市场份额没有后面三种消息中间件多,其最新架构被命名为Apollo,(京东的消息中间件就是基于activeMQ开发的)
优势:
缺点:
基于C开发
号称史上最快的消息队列,基于C语言开发。ZeroMQ是一个消息处理队列库,可在多线程、多内核和主机之间弹性伸缩,虽然大多数时候咱们习惯将其纳入消息队列家族之中,可是其和前面的几款有着本质的区别,ZeroMQ自己就不是一个消息队列服务器,更像是一组底层网络通信库,对原有的Socket API上加上一层封装而已。
优势:
缺点:
基于java开发(阿里消息中间件)
是阿里开源的消息中间件,目前已经捐献个Apache基金会,它是由Java语言开发的,具有高吞吐量、高可用性、适合大规模分布式系统应用等特色,经历过双11的洗礼,实力不容小觑。
优势:
缺点:
基于Scala和Java开发
起初是由LinkedIn公司采用Scala语言开发的一个分布式、多分区、多副本且基于zookeeper协调的分布式消息系统,现已捐献给Apache基金会。它是一种高吞吐量的分布式发布订阅消息系统,以可水平扩展和高吞吐率而被普遍使用。目前愈来愈多的开源分布式处理系统如Cloudera、Apache Storm、Spark、Flink等都支持与Kafka集成。
优势:
缺点:
Redis的PUB/SUB机制,即发布-订阅模式。利用的Redis的列表(lists)数据结构。比较好的使用模式是,生产者lpush消息,消费者brpop消息,并设定超时时间,能够减小redis的压力。只有在Redis宕机且数据没有持久化的状况下丢失数据,能够根据业务经过AOF和缩短持久化间隔来保证很高的可靠性,并且也能够经过多个client来提升消费速度。但相对于专业的消息队列来讲,该方案消息的状态过于简单(没有状态),且没有ack机制,消息取出后消费失败依赖于client记录日志或者从新push到队列里面。
redis不支持分组(这点很重要,在作负载均衡的时候劣势就体现出来),不过能够彻底当作一个轻量级的队列使用,但redis他爹作了disque,能够去试一试。
几个重要概念:
使用过程:
单机
RabbitMQ 安装须要依赖 Erlang 环境
因此先安装erlang,再安装rabbitMQ,中间确定会遇到不少问题,不一样的环境问题不同,大多数是依赖包的问题,自行补齐就好了。
rabbitmq默认建立的用户guest,密码也是guest,这个用户默认只能是本机访问,从外部访问须要添加上面的配置。建议删除guest用户
配置外部访问
# rabbitmq.config文件默认是没有的,这里是直接新建 vi rabbitmq.config # 添加下面内容 [{rabbit, [{loopback_users, []}]}]. 复制代码
删除guest用户
rabbitmqctl delete_user guest 复制代码
添加用户
rabbitmqctl add_user <username> <newpassword> 复制代码
给新增用户赋予超级管理员权限
rabbitmqctl set_user_tags <username> administrator 复制代码
启动服务(建议后台模式运行)
service rabbitmq-server start & 复制代码
开启管理UI(建议后台模式运行)
rabbitmq-plugins enable rabbitmq_management & 复制代码
访问:ip:15672,用新添加的用户登录
几个重要概念:
单机
Kafka使用Zookeeper来维护集群信息,因此须要先安装zookeeper,而zookeeper是由java编写的,因此须要先安装jdk
下载地址:kafka.apache.org/downloads
# 下载解压 mkdir kafka && cd kafka wget http://mirrors.shuosc.org/apache/kafka/1.0.0/kafka_2.11-1.0.0.tgz tar -xzf kafka_2.11-1.0.0.tgz cd kafka_2.11-1.0.1 # 启动zookeeper bin/zookeeper-server-start.sh config/zookeeper.properties # 启动kafka bin/kafka-server-start.sh config/server.properties # 建立Topic test bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test # 参数描述: # create: 建立Topic # zookeeper:zookeeper集群信息,多个用,分开 # replication-factor:复制因子 # partitions:分区信息 # topic:主题名 # 向topic发送消息 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test > 随便输入 # 向topic获取消息 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning # 就能看到前面输入的消息了 复制代码
Kafka监控工具
kafka没有自带的web ui,这里使用KafkaOffsetMonitor, 程序一个jar包的形式运行,部署较为方便。只有监控功能,使用起来也较为安全。
KafkaOffsetMonitor托管在Github上,能够经过Github下载。 下载地址:github.com/Morningstar…
# 下载好以后cd到KafkaOffsetMonitor所在目录,能够直接启动,也能够编写shell脚原本启动 java -cp KafkaOffsetMonitor-assembly-0.4.1-SNAPSHOT.jar com.quantifind.kafka.offsetapp.OffsetGetterWeb --port 8089 --zk 127.0.0.1:2181 --refresh 5.minutes --retain 1.day 复制代码
编写脚本启动
mkdir kafka-monitor.sh chmod +x kafka-monitor.sh vi kafka-monitor.sh # 把以前启动的命令复制进来,如: #! /bin/bash java -Xms512M -Xmx512M -Xss1024K \ -cp KafkaOffsetMonitor-assembly-0.4.1-SNAPSHOT.jar \ com.quantifind.kafka.offsetapp.OffsetGetterWeb \ --zk localhost:2181 \ --port 8089 \ --refresh 10.seconds \ --retain 5.days # 保存,而后就能够启动脚本了 复制代码
zk :zookeeper主机地址,若是有多个,用逗号隔开
port :应用程序端口(没设置的话,日志里面会输出随机的端口号)
refresh :应用程序在数据库中刷新和存储点的频率
retain :在db中保留多长时间
dbName :保存的数据库文件名,默认为offsetapp
github上详细参数说明:
访问:ip:端口
Topic:订阅的主题 Partition:分区编号 Offest:表示该parition已经消费了多少条message logSize:表示该partition已经写了多少条message Lag:表示有多少条message没有被消费。 Owner:表示消费者 Created:该partition建立时间 Last Seen:消费状态刷新最新时间。