rocketmq总结(消息的高可用、中间件选型)

rocketmq总结(消息的高可用、中间件选型)java

 

 

 参考:linux

https://blog.csdn.net/meilong_whpu/article/details/76922456ios

http://blog.51cto.com/sofar/1540874git

https://blog.csdn.net/lunaqi/article/details/78517200程序员

https://mp.weixin.qq.com/s?__biz=MzIwMzg1ODcwMw==&mid=2247487688&idx=1&sn=d1555109750b309a2d96ce3332e8a97b&chksm=96c9a6a8a1be2fbe8e1df2f2bb60a2bfea0e62aaec0633df928432ceed6438a724dd217624cd#rd github

 

 

消息中间件概况

消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走。经过消息队列,应用程序可独立地执行--它们不须要知道彼此的位置、或在继续执行前不须要等待接收程序接收此消息。sql

       在分布式计算环境中,为了集成分布式应用,开发者须要对异构网络环境下的分布式应用提供有效的通讯手段。为了管理须要共享的信息,对应用提供公共的信息交换机制是重要的。数据库

       设计分布式应用的方法主要有:远程过程调用(PRC)-分布式计算环境(DCE)的基础标准成分之一;对象事务监控(OTM)-基于CORBA的面向对象工业标准与事务处理(TP)监控技术的组合;消息队列(MessageQueue)-构造分布式应用的松耦合方法。编程

       (a) 分布计算环境/远程过程调用 (DCE/RPC)vim

       RPC是DCE的成分,是一个由开放软件基金会(OSF)发布的应用集成的软件标准。RPC模仿一个程序用函数引用来引用另外一程序的传统程序设计方法,此引用是过程调用的形式,一旦被调用,程序的控制则转向被调用程序。

       在RPC 实现时,被调用过程可在本地或远地的另外一系统中驻留并在执行。当被调用程序完成处理输入数据,结果放在过程调用的返回变量中返回到调用程序。RPC完成后程序控制则当即返回到调用程序。所以RPC模仿子程序的调用/返回结构,它仅提供了Client(调用程序)和Server(被调用过程)间的同步数据交换。

       (b) 对象事务监控 (OTM)

       基于CORBA的面向对象工业标准与事务处理(TP)监控技术的组合,在CORBA规范中定义了:使用面向对象技术和方法的体系结构;公共的 Client/Server程序设计接口;多平台间传输和翻译数据的指导方针;开发分布式应用接口的语言(IDL)等,并为构造分布的 Client/Server应用提供了普遍及一致的模式。

       (c) 消息队列 (Message Queue)

       消息队列为构造以同步或异步方式实现的分布式应用提供了松耦合方法。消息队列的API调用被嵌入到新的或现存的应用中,经过消息发送到内存或基于磁盘的队列或从它读出而提供信息交换。消息队列可用在应用中以执行多种功能,好比要求服务、交换信息或异步处理等。

       中间件是一种独立的系统软件或服务程序,分布式应用系统借助这种软件在不一样的技术之间共享资源,管理计算资源和网络通信。它在计算机系统中是一个关键软件,它能实现应用的互连和互操做性,能保证系统的安全、可靠、高效的运行。中间件位于用户应用和操做系统及网络软件之间,它为应用提供了公用的通讯手段,而且独立于网络和操做系统。中间件为开发者提供了公用于全部环境的应用程序接口,当应用程序中嵌入其函数调用,它即可利用其运行的特定操做系统和网络环境的功能,为应用执行通讯功能。

       若是没有消息中间件完成信息交换,应用开发者为了传输数据,必需要学会如何用网络和操做系统软件的功能,编写相应的应用程序来发送和接收信息,且交换信息没有标准方法,每一个应用必须进行特定的编程从而和多平台、不一样环境下的一个或多个应用通讯。例如,为了实现网络上不一样主机系统间的通讯,将要求具有在网络上如何交换信息的知识(好比用TCP/IP的socket程序设计);为了实现同一主机内不一样进程之间的通信,将要求具有操做系统的消息队列或命名管道(Pipes)等知识。

       目前中间件的种类不少,如交易管理中间件、面向Java应用的Web应用服务器中间件等,而消息传输中间件(MOM)是其中的一种。它简化了应用之间数据的传输,屏蔽底层异构操做系统和网络平台,提供一致的通信标准和应用开发,确保分布式计算网络环境下可靠的、跨平台的信息传输和数据交换。它基于消息队列的存储-转发机制,并提供特有的异步传输机制,可以基于消息传输和异步事务处理实现应用整合与数据交换。

 

发布-订阅消息模式

1、 订阅杂志

      咱们不少人都订过杂志,其过程很简单。只要告诉邮局咱们所要订的杂志名、投递的地址,付了钱就OK。出版社按期会将出版的杂志交给邮局,邮局会根据订阅的列表,将杂志送达消费者手中。这样咱们就能够看到每一期精彩的杂志了。

 

仔细思考一下订杂志的过程,咱们会发现这样几个特色:一、 消费者订杂志不须要直接找出版社;二、 出版社只须要把杂志交给邮局;三、 邮局将杂志送达消费者。邮局在整个过程当中扮演了很是重要的中转做用,在出版社和消费者相互不须要知道对方的状况下,邮局完成了杂志的投递。
2、 发布-订阅消息模式

       刚刚讲了订阅杂志,下面咱们会讲传统调用模式演化到发布-订阅消息模式。
       有些网站在注册用户成功后发一封激活邮件,用户收到邮件后点击激活连接后才能使用该网站。通常的作法是在注册用户业务逻辑中调用发送邮件的逻辑。这 样用户业务就依赖于邮件业务。若是之后改成短信激活,注册用户业务逻辑就必须修改成调用发送短信的逻辑。若是要注册后给用户加点积分,再加一段逻辑。通过 屡次修改,咱们发现很简单的注册用户业务已经愈来愈复杂,愈来愈难以维护。相信不少开发者都会有相似痛苦的经历。

即便用户业务实现中对其余业务是接口依赖,也避免不了业务变化带来的依赖影响。怎么办?解耦!将注册用户业务逻辑中注册成功后的处理剥离出来。
       再回头看看"订阅杂志",若是没有邮局,出版社就必须本身将杂志送达全部消费者。这种情形就和如今的注册用户业务同样。咱们发现问题了,在用户业务和其余业务之间缺乏了邮局所扮角色。
       咱们把邮局抽象成一个管理消息的地方,叫"消息管理器"。注册用户成功后发送一个消息给消息管理器,由消息管理器转发该消息给须要处理的业务。如今,用户业务只依赖于消息管理器了,它不再会为了注册用户成功后的其余处理而烦恼。

注册用户的改造就是借鉴了"订阅杂志"这样原始的模式。咱们再进一步抽象,用户业务就是消息的"生产者",它将消息发布到消息管理器。邮件业务就是 消息的"消费者",它将收到的消息进行处理。邮局能够订阅不少种杂志,杂志都是经过某种编号来区分;消息管理器也能够管理多种消息,每种消息都会有一个 "主题"来区分,消费者都是经过主题来订阅的。

发布-订阅消息模式已经呈如今咱们面前,利用它能够产生更灵活、更松散耦合的系统。

 

MQ相关概念

1.消息(Message)

消息是MQ中最小的概念,本质上就是一段数据,它能被一个或者多个应用程序所理解,是应用程序之间传递的信息载体。

2.队列(Queue)

2.1本地队列

本地队列按照功能可划分为初始化队列,传输队列,目标队列和死信队列。

初始化队列用做消息触发功能。

传输队列只是暂存待传的消息,条件许可的状况下,经过管道将消息传送到其余的队列管理器。

目标队列是消息的目的地,能够长期存放消息。

若是消息不能送达目标队列,也不能再路由出去,则被自动放入死信队列保存。

2.2别名队列&远程队列

只是一个队列定义,用来指定远端队列管理器的队列。使用了远程队列,程序就不须要知道目标队列的位置。

2.3模型队列

模型队列定义了一套本地队列的属性结合,一旦打开模型队列,队列管理器会按照这些属性动态地建立出一个本地队列。

3.队列管理器(Queue Manager)

队列管理器是一个负责向应用程序提供消息服务的机构,若是把队列管理器比做数据库,那么队列就是其中一张表。

4.通道(Channel)

通道是两个管理器之间的一种单向点对点的的通讯链接,若是须要双向交流,能够创建一对通道。

5.监听器(listner)

MQ产品的特性

可靠性传输

这个特色能够说是消息中间件的立足之本,对于应用来讲,只要成功把数据提交给消息中间件,那么关于数据可靠传输的问题就由消息中间件来负责。

不重复传输

不重复传播也就是断点续传的功能,特别适合网络不稳定的环境,节约网络资源。

异步性传输

异步性传输是指,接受信息双方没必要同时在线,具备脱机能力和安全性。

消息驱动

接到消息后主动通知消息接收方。

支持事务

应用程序能够把一些数据更新组合成一个工做单元,这些更新一般是逻辑相关的,为了保障数据完整性,全部的更新必须同时成功或者同时失败)。 

MQ适用场景介绍

MQ消息队列是应运松偶合的概念而产生的,主要以队列和发布订阅为消息传输机制,以异步的方式将消息可靠的传输到消费端的一种基础产品。

它被普遍的应用与跨平台、跨系统的分布式系统之间,为它们提供高效可靠的异步传输机制。

  • 消息通道(Message Channel)

       使用MQ将彼此协做的客户端和服务端链接起来,使他们能够交换消息。

如客户端与服务端须要安全可靠的交互,能够将一个MQ的队列做为安全通道,是客户端与服务端可以安全高效的进行异步通信。

  • 消息总线(Message Bus)

      对于由许多独立开发的服务组成的分布式系统,假若要将它们组成一个完整的系统,这些服务必须可以可靠地交互,同时,为了系统的健壮性,

每一个服务之间又不能产生过度紧密的依赖关系,这样就能够经过消息总线将不一样的服务链接起来,容许它们异步的传递数据。

 

  • 消息路由(Message Router)

       经过消息路由,能够将发送到MQ指定队列的消息根据规则路由到不一样的队列。

此外,JMS规范还支持经过selector条件,对消息进行过滤,能够用多个消费者消费同一个队列的消息,每一个消费者只消费本身感兴趣的消息。

  • 发布/订阅(Publicsher/Subscriber)

      发布/订阅模式用于一对多的通信,当消息发布者向一个主题(Topic)发送一条消息后,该主题的全部订阅者都会收到这条消息。

 

 

 

 

RocketMQ存储篇—高可用

在集群模式的部署方式中,Master与Slave配对是经过指定相同的brokerName参数来配对,Master的BrokerId必须是0,Slave的BrokerId必须是大于0的数。一个Master下面能够挂载多个Slave,同一个Master下的多个Slave经过指定不一样的BrokerId来区分。有4种部署方式:

部署方式 优势 缺点 备注
单个Master模式 一旦Broker重启或者宕机时,会致使整个服务不可用,不建议线上环境使用;    
多个Master模式 配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即便机器宕机不可恢复状况下,因为RAID10磁盘很是可靠,消息也不会丢(异步刷盘丢失少许消息,同步刷盘一条不丢),性能最高。 单台机器宕机期间,这台机器上未被消费的消息在机器恢复以前不可订阅,消息实时性会收到影响。 当使用多master无slave的集群搭建方式时,master的brokerRole配置必须为ASYNC_MASTER。若是配置为SYNC_MASTER,则producer发送消息时,返回值的SendStatus会一直是SLAVE_NOT_AVAILABLE。
多Master多Slave模式——异步复制 即便磁盘损坏,消息丢失的很是少,但消息实时性不会受影响,由于Master宕机后,消费者仍然能够从Slave消费,此过程对应用透明,不须要人工干预,性能同多Master模式几乎同样。 Master宕机,磁盘损坏状况,会丢失少许信息。  
多Master多Slave模式——同步双写 数据与服务都无单点,Master宕机状况下,消息无延迟,服务可用性与数据可用性都很是高; 性能比异步复制模式稍低,大约低10%左右,发送单个消息的RT会稍高,目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能。  

在集群模式下,为了保证高可用,必需要保证备用Broker与主用Broker信息是一致的,在备用Broker初始化时设置的了定时任务,每一个60秒调用SlaveSynchronize.syncAll()方法发起向主用Broker进行一次config类文件的同步,而消息数据的同步由主备Broker经过心跳检测的方式完成,每隔5秒进行一次心跳。 主用Broker提供读写服务,而备用Broker只提供读服务。

 

刷盘方式

同步刷盘:在消息到达MQ后,RocketMQ须要将数据持久化,同步刷盘是指数据到达内存以后,必须刷到commitlog日志以后才算成功,而后返回producer数据已经发送成功。

异步刷盘:是指数据到达内存以后,返回producer说数据已经发送成功。,而后再写入commitlog日志。

commitlog:

commitlog就是来存储全部的元信息,包含消息体,相似于Mysql、Oracle的redolog,因此主要有CommitLog在,Consume Queue即便数据丢失,仍然能够恢复出来。

consumequeue:记录数据的位置,以便Consume快速经过consumequeue找到commitlog中的数据

 

分布式消息队列RocketMQ部署与监控

==========================================================================================

1、RocketMQ简介

==========================================================================================

RocketMQ是一款分布式、队列模型的消息中间件,具备如下特色:

一、支持严格的消息顺序;

二、支持Topic与Queue两种模式;

三、亿级消息堆积能力;

四、比较友好的分布式特性;

五、同时支持Push与Pull方式消费消息;

 

更多介绍能够参考如下连接:

https://github.com/alibaba/RocketMQ/wiki

http://blog.csdn.net/a19881029/article/details/34446629

http://singlefly.blog.51cto.com/4658189/1368579

 

本文采用双Master的架构模式。

 

==========================================================================================

2、服务器分布

==========================================================================================

1、相关说明

IP地址

主机名

机型

角色

架构模式

10.217.121.123

rocketmq-master1

128G内存

nameserver、brokerserver

Master1(双Master模式)

10.217.122.31

rocketmq-master2

128G内存

nameserver、brokerserver

Master2(双Master模式)

 

2hosts信息添加

# vim /etc/hosts

10.217.121.123  mqnameserver1

10.217.122.31    mqnameserver2

10.217.121.123  rocketmq-master1

10.217.122.31    rocketmq-master2

 

3、系统环境

CentOS 6.3

 

4、整体架构

wKioL1PuQE3DcTjUAAE4E08WEfw644.jpg

 

==========================================================================================

3、RocketMQ安装与配置

==========================================================================================

1JDK安装

http://download.oracle.com/otn-pub/java/jdk/7u65-b17/jdk-7u65-linux-x64.tar.gz

# tar xvzf jdk-7u65-linux-x64.gz -C /usr/local

# rm -f jdk-7u65-linux-x64.gz

# cd /usr/local && ln -s jdk1.7.0_65 jdk

# cd /usr/local/bin && ln -s /usr/local/jdk/bin/java

 

2RocketMQ安装

https://github.com/alibaba/RocketMQ/releases

# tar xvzf alibaba-rocketmq-3.1.7.tar.gz -C /usr/local

# mv alibaba-rocketmq alibaba-rocketmq-3.1.7

# ln -s alibaba-rocketmq-3.1.7 rocketmq

# rm alibaba-rocketmq-3.1.7.tar.gz

# ll /usr/local

wKiom1PuP2TDorXeAAKWNuNdZ7w687.jpg

 

3、环境变量设置

# vim /etc/profile

export PATH=$PATH:/usr/local/bin

 

export JAVA_HOME=/usr/local/jdk

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export PATH=$PATH:$JAVA_HOME/bin

 

export ROCKETMQ_HOME=/usr/local/rocketmq

export PATH=$PATH::$ROCKETMQ_HOME/bin

 

# source /etc/profile

# cd /usr/local/rocketmq/bin && sh os.sh

 

4、主机名设置

(1)Master1服务器

# vim /etc/hosts

10.217.121.123  mqnameserver1

10.217.122.31    mqnameserver2

10.217.121.123  rocketmq-master1

10.217.122.31    rocketmq-master2

 

# sed -i  '/HOSTNAME/d' /etc/sysconfig/network

# echo 'HOSTNAME=rocketmq-master1'  >> /etc/sysconfig/network

# hostname rocketmq-master1

 

(2)Master2服务器

# vim /etc/hosts

10.217.121.123  mqnameserver1

10.217.122.31    mqnameserver2

10.217.121.123  rocketmq-master1

10.217.122.31    rocketmq-master2

 

# sed -i  '/HOSTNAME/d' /etc/sysconfig/network

# echo 'HOSTNAME=rocketmq-master2'  >> /etc/sysconfig/network

# hostname rocketmq-master2

 

5RocketMQ配置

(1)Master1服务器

# vim /usr/local/rocketmq/conf/2m-noslave/broker-a.properties

brokerClusterName=AdpMqCluster

brokerName=broker-a

brokerId=0

namesrvAddr=mqnameserver1:9876;mqnameserver2:9876

defaultTopicQueueNums=4

autoCreateTopicEnable=true

autoCreateSubscriptionGroup=true

listenPort=10911

deleteWhen=04

fileReservedTime=120

mapedFileSizeCommitLog=1073741824

mapedFileSizeConsumeQueue=50000000

destroyMapedFileIntervalForcibly=120000

redeleteHangedFileInterval=120000

diskMaxUsedSpaceRatio=88

 

storePathRootDir=/data/rocketmq/store

storePathCommitLog=/data/rocketmq/store/commitlog

 

maxMessageSize=65536

 

flushCommitLogLeastPages=4

flushConsumeQueueLeastPages=2

flushCommitLogThoroughInterval=10000

flushConsumeQueueThoroughInterval=60000

 

brokerRole=ASYNC_MASTER

flushDiskType=ASYNC_FLUSH

 

checkTransactionMessageEnable=false

 

sendMessageThreadPoolNums=128

pullMessageThreadPoolNums=128

 

(2)Master2服务器

# vim /usr/local/rocketmq/conf/2m-noslave/broker-b.properties

brokerClusterName=AdpMqCluster

brokerName=broker-b

brokerId=1

namesrvAddr=mqnameserver1:9876;mqnameserver2:9876

defaultTopicQueueNums=4

autoCreateTopicEnable=true

autoCreateSubscriptionGroup=true

listenPort=10911

deleteWhen=04

fileReservedTime=120

mapedFileSizeCommitLog=1073741824

mapedFileSizeConsumeQueue=50000000

destroyMapedFileIntervalForcibly=120000

redeleteHangedFileInterval=120000

diskMaxUsedSpaceRatio=88

 

storePathRootDir=/data/rocketmq/store

storePathCommitLog=/data/rocketmq/store/commitlog

 

maxMessageSize=65536

 

flushCommitLogLeastPages=4

flushConsumeQueueLeastPages=2

flushCommitLogThoroughInterval=10000

flushConsumeQueueThoroughInterval=60000

 

brokerRole=ASYNC_MASTER

flushDiskType=ASYNC_FLUSH

 

checkTransactionMessageEnable=false

 

sendMessageThreadPoolNums=128

pullMessageThreadPoolNums=128

 

(3)runbroker.sh参数调整

runbroker.sh须要根据内存大小进行适当地调整

JAVA_OPT_1="-server-Xms80g -Xmx80g -Xmn20g -XX:PermSize=1g -XX:MaxPermSize=1g"

 

6、服务启动

# mkdir -p /data/rocketmq/store/commitlog  /data/logs

# cd /usr/local/rocketmq/conf && sed -i  's#${user.home}#/data#g' *.xml

 

(1)、启动NameServermaster1master2

# cd /usr/local/rocketmq/bin

# nohup sh mqnamesrv &

 

(2)、启动BrokerServer Amaster1

# cd /usr/local/rocketmq/bin

# nohup sh mqbroker -c ../conf/2m-noslave/broker-a.properties  >/dev/null 2>&1 &

 

(3)、启动BrokerServer Bmaster2

# cd /usr/local/rocketmq/bin

# nohup sh mqbroker -c ../conf/2m-noslave/broker-b.properties  >/dev/null 2>&1 &

 

# netstat -ntlp

wKioL1PuQKejDpe9AAC166EAySE757.jpg

 

# jps

wKiom1PuP6yBTpSfAAB_ScYujDc698.jpg

 

==========================================================================================

4、RocketMQ服务健康监控

==========================================================================================

1、依赖组件安装

# yum -y install nmap

 

2nameserver监控

# vim /data/scripts/check_nameserver_health.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
 
SRV_PORT="9876"                    ## 端口号
SRV_PROT="tcp"                     ## 协议类型
SRV_NAME="rocketmq_nameserver"     ## 服务名
 
## 是否已正确扫描
SCAN_FLAG=0
 
for ETH_NAME in `/sbin/ifconfig | grep eth1 | awk '{print $1}'`
do
       ETH1_ADDR=`/sbin/ifconfig ${ETH_NAME} | awk -F ':' '/inet addr/{print $2}' | sed 's/[a-zA-Z ]//g'`
       [[ -z "${ETH1_ADDR}" ]] && continue || break
done
 
TMP_SRV_PROT=`echo ${SRV_PROT} | tr '[A-Z]' '[a-z]'`
 
if [[ "${TMP_SRV_PROT}" == "tcp" ]]; then
       PROT_OPT="S"
elif [[ "${TMP_SRV_PROT}" == "udp" ]]; then
       PROT_OPT="U"
else
       echo "未知的协议类型!" && exit1
fi
 
## 最多扫描3次,成功一次便可,以免网络抖动而致使误判
for ((i=0; i<3; i++)); do
       RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${ETH1_ADDR} | grep open`
       [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10
done
 
if [[ ${SCAN_FLAG} -ne 1 ]]; then
       [[ -n `ps aux | grep java | grep namesrv` ]] && kill -9 `ps aux | grep java | awk '/namesrv/{print $2}'`
       cd /usr/local/rocketmq/bin && nohup sh mqnamesrv &
fi

 

3brokerserver监控

# vim /data/scripts/check_brokerserver_health.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
 
SRV_PORT="10911"                      ## 端口号
SRV_PROT="tcp"                        ## 协议类型
SRV_NAME="rocketmq_brokerserver"      ## 服务名
 
## 是否已正确扫描
SCAN_FLAG=0
 
for ETH_NAME in `/sbin/ifconfig | grep eth1 | awk '{print $1}'`
do
       ETH1_ADDR=`/sbin/ifconfig ${ETH_NAME} | awk -F ':' '/inet addr/{print $2}' | sed 's/[a-zA-Z ]//g'`
       [[ -z "${ETH1_ADDR}" ]] && continue || break
done
 
TMP_SRV_PROT=`echo ${SRV_PROT} | tr '[A-Z]' '[a-z]'`
 
if [[ "${TMP_SRV_PROT}" == "tcp" ]]; then
       PROT_OPT="S"
elif [[ "${TMP_SRV_PROT}" == "udp" ]]; then
       PROT_OPT="U"
else
       echo "未知的协议类型!" && exit1
fi
 
## 最多扫描3次,成功一次便可,以免网络抖动而致使误判
for ((i=0; i<3; i++)); do
       RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${ETH1_ADDR} | grep open`
       [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10
done
 
if [[ ${SCAN_FLAG} -ne 1 ]]; then
       [[ -n `ps aux | grep java | grep broker` ]] && kill -9 `ps aux | grep java | awk '/broker/{print $2}'`
       cd /usr/local/rocketmq/bin && nohup sh mqbroker -c ../conf/2m-noslave/broker-a.properties &
fi

 

 

【注意】

以上红色标注部分,在master2上的名称为“broker-b.properties”

 

4crontab信息添加

# touch /var/run/check_rocketmq_nameserver.lock

# touch /var/run/check_rocketmq_brokerserver.lock

 

# echo 'touch /var/run/check_rocketmq_nameserver.lock' >> /etc/rc.d/rc.local

# echo 'touch /var/run/check_rocketmq_brokerserver.lock' >> /etc/rc.d/rc.local

 

# crontab -e

*/2 * * * * (flock --timeout=0 /var/run/check_rocketmq_nameserver.lock /data/scripts/check_nameserver_health.sh >/dev/null 2>&1)

 

*/2 * * * * (flock --timeout=0 /var/run/check_rocketmq_brokerserver.lock /data/scripts/check_brokerserver_health.sh >/dev/null 2>&1)

 

 

 

消息中间件选型时,要关注哪些问题

消息队列中间件(简称消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通讯来进行分布式系统的集成。经过提供消息传递和消息排队模型,它能够在分布式环境下提供应用解耦、弹性伸缩、冗余存储、流量削峰、异步通讯、数据同步等等功能,其做为分布式系统架构中的一个重要组件,有着举足轻重的地位。

目前开源的消息中间件可谓是琳琅满目,能让你们耳熟能详的就有不少,好比 ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ 等。无论选择其中的哪一款,都会有用的不趁手的地方,毕竟不是为你量身定制的。

有些大厂在长期的使用过程当中积累了必定的经验,其消息队列的使用场景也相对稳定固化,或者目前市面上的消息中间件没法知足自身需求,而且也具有足够的精力和人力而选择自研来为本身量身打造一款消息中间件。可是绝大多数公司仍是不会选择重复造轮子,那么选择一款合适本身的消息中间件显得尤其重要。就算是前者,那么在自研出稳定且可靠的相关产品以前仍是会经历这样一个选型过程。

在总体架构中引入消息中间件,势必要考虑不少因素,好比成本及收益问题,怎么样才能达到最优的性价比?虽然消息中间件种类繁多,可是各自都有各自的侧重点,选择合适本身、扬长避短无疑是最好的方式。若是你对此感到无所适从,本文或许能够参考一二。

各种消息队列简述

ActiveMQ 是 Apache 出品的、采用 Java 语言编写的彻底基于 JMS1.1 规范的面向消息的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通讯。不过因为历史缘由包袱过重,目前市场份额没有后面三种消息中间件多,其最新架构被命名为 Apollo,号称下一代 ActiveMQ,有兴趣的同窗可行了解。

RabbitMQ 是采用 Erlang 语言实现的 AMQP 协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息。RabbitMQ 发展到今天,被愈来愈多的人承认,这和它在可靠性、可用性、扩展性、功能丰富等方面的卓越表现是分不开的。

Kafka 起初是由 LinkedIn 公司采用 Scala 语言开发的一个分布式、多分区、多副本且基于 zookeeper 协调的分布式消息系统,现已捐献给 Apache 基金会。它是一种高吞吐量的分布式发布订阅消息系统,以可水平扩展和高吞吐率而被普遍使用。目前愈来愈多的开源分布式处理系统如 Cloudera、Apache Storm、Spark、Flink 等都支持与 Kafka 集成。

RocketMQ 是阿里开源的消息中间件,目前已经捐献个 Apache 基金会,它是由 Java 语言开发的,具有高吞吐量、高可用性、适合大规模分布式系统应用等特色,经历过双 11 的洗礼,实力不容小觑。

ZeroMQ 号称史上最快的消息队列,基于 C 语言开发。ZeroMQ 是一个消息处理队列库,可在多线程、多内核和主机之间弹性伸缩,虽然大多数时候咱们习惯将其纳入消息队列家族之中,可是其和前面的几款有着本质的区别,ZeroMQ 自己就不是一个消息队列服务器,更像是一组底层网络通信库,对原有的 Socket API 上加上一层封装而已。

目前市面上的消息中间件还有不少,好比腾讯系的 PhxQueue、CMQ、CKafka,又好比基于 Go 语言的 NSQ,有时人们也把相似 Redis 的产品也看作消息中间件的一种,固然它们都很优秀,可是本文篇幅限制没法穷极全部,下面会针对性的挑选 RabbitMQ 和 Kafka 两款典型的消息中间件来作分析,力求站在一个公平公正的立场来阐述消息中间件选型中的各个要点。

选型要点概述

衡量一款消息中间件是否符合需求须要从多个维度进行考察,首要的就是功能维度,这个直接决定了你可否最大程度上的实现开箱即用,进而缩短项目周期、下降成本等。若是一款消息中间件的功能达不到想要的功能,那么就须要进行二次开发,这样会增长项目的技术难度、复杂度以及增大项目周期等。

 功能维度

功能维度又能够划分个多个子维度,大体能够分为如下这些:

优先级队列

优先级队列不一样于先进先出队列,优先级高的消息具有优先被消费的特权,这样能够为下游提供不一样消息级别的保证。不过这个优先级也是须要有一个前提的:若是消费者的消费速度大于生产者的速度,而且消息中间件服务器(通常简单的称之为 Broker)中没有消息堆积,那么对于发送的消息设置优先级也就没有什么实质性的意义了,由于生产者刚发送完一条消息就被消费者消费了,那么就至关于 Broker 中至多只有一条消息,对于单条消息来讲优先级是没有什么意义的。

延迟队列

当你在网上购物的时候是否会遇到这样的提示:“三十分钟以内未付款,订单自动取消”?这个是延迟队列的一种典型应用场景。延迟队列存储的是对应的延迟消息,所谓“延迟消息”是指当消息被发送之后,并不想让消费者马上拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。延迟队列通常分为两种:基于消息的延迟和基于队列的延迟。基于消息的延迟是指为每条消息设置不一样的延迟时间,那么每当队列中有新消息进入的时候就会从新根据延迟时间排序,固然这也会对性能形成极大的影响。实际应用中大多采用基于队列的延迟,设置不一样延迟级别的队列,好比 5s、10s、30s、1min、5mins、10mins 等,每一个队列中消息的延迟时间都是相同的,这样免去了延迟排序所要承受的性能之苦,经过必定的扫描策略(好比定时)便可投递超时的消息。

死信队列

因为某些缘由消息没法被正确的投递,为了确保消息不会被无端的丢弃,通常将其置于一个特殊角色的队列,这个队列通常称之为死信队列。与此对应的还有一个“回退队列”的概念,试想若是消费者在消费时发生了异常,那么就不会对这一次消费进行确认(Ack), 进而发生回滚消息的操做以后消息始终会放在队列的顶部,而后不断被处理和回滚,致使队列陷入死循环。为了解决这个问题,能够为每一个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障。实际状况下,回退队列的角色能够由死信队列和重试队列来扮演。

重试队列

重试队列其实能够当作是一种回退队列,具体指消费端消费消息失败时,为防止消息无端丢失而从新将消息回滚到 Broker 中。与回退队列不一样的是重试队列通常分红多个重试等级,每一个重试等级通常也会设置从新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列 Q1,Q1 的从新投递延迟为 5s,在 5s 事后从新投递该消息;若是消息再次消费失败则入重试队列 Q2,Q2 的从新投递延迟为 10s,在 10s 事后再次投递该消息。以此类推,重试越屡次从新投递的时间就越久,为此须要设置一个上限,超过投递次数就入死信队列。重试队列与延迟队列有相同的地方,都是须要设置延迟级别,它们彼此的区别是:延迟队列动做由内部触发,重试队列动做由外部消费端触发;延迟队列做用一次,而重试队列的做用范围会向后传递。

消费模式

消费模式分为推(push)模式和拉(pull)模式。推模式是指由 Broker 主动推送消息至消费端,实时性较好,不过须要必定的流制机制来确保服务端推送过来的消息不会压垮消费端。而拉模式是指消费端主动向 Broker 端请求拉取(通常是定时或者定量)消息,实时性较推模式差,可是能够根据自身的处理能力而控制拉取的消息量。

广播消费

消息通常有两种传递模式:点对点(P2P,Point-to-Point)模式和发布 / 订阅(Pub/Sub)模式。对于点对点的模式而言,消息被消费之后,队列中不会再存储,因此消息消费者不可能消费到已经被消费的消息。虽然队列能够支持多个消费者,可是一条消息只会被一个消费者消费。发布订阅模式定义了如何向一个内容节点发布和订阅消息,这个内容节点称为主题(topic),主题能够认为是消息传递的中介,消息发布者将消息发布到某个主题,而消息订阅者则从主题中订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不须要进行接触便可保证消息的传递,发布 / 订阅模式在消息的一对多广播时采用。RabbitMQ 是一种典型的点对点模式,而 Kafka 是一种典型的发布订阅模式。可是 RabbitMQ 中能够经过设置交换器类型来实现发布订阅模式而达到广播消费的效果,Kafka 中也能以点对点的形式消费,你彻底能够把其消费组(consumer group)的概念当作是队列的概念。不过对比来讲,Kafka 中由于有了消息回溯功能的存在,对于广播消费的力度支持比 RabbitMQ 的要强。

消息回溯

通常消息在消费完成以后就被处理了,以后不再能消费到该条消息。消息回溯正好相反,是指消息在消费完成以后,还能消费到以前被消费掉的消息。对于消息而言,常常面临的问题是“消息丢失”,至因而真正因为消息中间件的缺陷丢失仍是因为使用方的误用而丢失通常很难追查,若是消息中间件自己具有消息回溯功能的话,能够经过回溯消费复现“丢失的”消息进而查出问题的源头之所在。消息回溯的做用远不止与此,好比还有索引恢复、本地缓存重建,有些业务补偿方案也能够采用回溯的方式来实现。

消息堆积 + 持久化

流量削峰是消息中间件的一个很是重要的功能,而这个功能其实得益于其消息堆积能力。从某种意义上来说,若是一个消息中间件不具有消息堆积的能力,那么就不能把它看作是一个合格的消息中间件。消息堆积份内存式堆积和磁盘式堆积。RabbitMQ 是典型的内存式堆积,但这并不是绝对,在某些条件触发后会有换页动做来将内存中的消息换页到磁盘(换页动做会影响吞吐),或者直接使用惰性队列来将消息直接持久化至磁盘中。Kafka 是一种典型的磁盘式堆积,全部的消息都存储在磁盘中。通常来讲,磁盘的容量会比内存的容量要大得多,对于磁盘式的堆积其堆积能力就是整个磁盘的大小。从另一个角度讲,消息堆积也为消息中间件提供了冗余存储的功能。援引 纽约时报的案例,其直接将 Kafka 用做存储系统。

消息追踪

对于分布式架构系统中的链路追踪(trace)而言,你们必定不会陌生。对于消息中间件而言,消息的链路追踪(如下简称消息追踪)一样重要。对于消息追踪最通俗的理解就是要知道消息从哪来,存在哪里以及发往哪里去。基于此功能下,咱们能够对发送或者消费完的消息进行链路追踪服务,进而能够进行问题的快速定位与排查。

消息过滤

消息过滤是指按照既定的过滤规则为下游用户提供指定类别的消息。就以 kafka 而言,彻底能够将不一样类别的消息发送至不一样的 topic 中,由此能够实现某种意义的消息过滤,或者 Kafka 还能够根据分区对同一个 topic 中的消息进行分类。不过更加严格意义上的消息过滤应该是对既定的消息采起必定的方式按照必定的过滤规则进行过滤。一样以 Kafka 为例,能够经过客户端提供的 ConsumerInterceptor 接口或者 Kafka Stream 的 filter 功能进行消息过滤。

多租户

也能够称为多重租赁技术,是一种软件架构技术,主要用来实现多用户的环境下公用相同的系统或程序组件,而且仍能够确保各用户间数据的隔离性。RabbitMQ 就可以支持多租户技术,每个租户表示为一个 vhost,其本质上是一个独立的小型 RabbitMQ 服务器,又有本身独立的队列、交换器及绑定关系等,而且它拥有本身独立的权限。vhost 就像是物理机中的虚拟机同样,它们在各个实例间提供逻辑上的分离,为不一样程序安全保密地容许数据,它既能将同一个 RabbitMQ 中的众多客户区分开,又能够避免队列和交换器等命名冲突。

多协议支持

消息是信息的载体,为了让生产者和消费者都能理解所承载的信息(生产者须要知道如何构造消息,消费者须要知道如何解析消息),它们就须要按照一种统一的格式描述消息,这种统一的格式称之为消息协议。有效的消息必定具备某种格式,而没有格式的消息是没有意义的。通常消息层面的协议有 AMQP、MQTT、STOMP、XMPP 等(消息领域中的 JMS 更多的是一个规范而不是一个协议),支持的协议越多其应用范围就会越广,通用性越强,好比 RabbitMQ 可以支持 MQTT 协议就让其在物联网应用中得到一席之地。还有的消息中间件是基于其自己的私有协议运转的,典型的如 Kafka。

跨语言支持

对不少公司而言,其技术栈体系中会有多种编程语言,如 C/C++、JAVA、Go、PHP 等,消息中间件自己具有应用解耦的特性,若是可以进一步的支持多客户端语言,那么就能够将此特性的效能扩大。跨语言的支持力度也能够从侧面反映出一个消息中间件的流行程度。

流量控制

流量控制(flow control)针对的是发送方和接收方速度不匹配的问题,提供一种速度匹配服务抑制发送速率使接收方应用程序的读取速率与之相适应。一般的流控方法有 Stop-and-wait、滑动窗口以及令牌桶等。

消息顺序性

顾名思义,消息顺序性是指保证消息有序。这个功能有个很常见的应用场景就是 CDC(Change Data Chapture),以 MySQL 为例,若是其传输的 binlog 的顺序出错,好比本来是先对一条数据加 1,而后再乘以 2,发送错序以后就变成了先乘以 2 后加 1 了,形成了数据不一致。

安全机制

在 Kafka 0.9 版本以后就开始增长了身份认证和权限控制两种安全机制。身份认证是指客户端与服务端链接进行身份认证,包括客户端与 Broker 之间、Broker 与 Broker 之间、Broker 与 ZooKeeper 之间的链接认证,目前支持 SSL、SASL 等认证机制。权限控制是指对客户端的读写操做进行权限控制,包括对消息或 Kafka 集群操做权限控制。权限控制是可插拔的,并支持与外部的受权服务进行集成。对于 RabbitMQ 而言,其一样提供身份认证(TLS/SSL、SASL)和权限控制(读写操做)的安全机制。

消息幂等性

对于确保消息在生产者和消费者之间进行传输而言通常有三种传输保障(delivery guarantee):At most once,至多一次,消息可能丢失,但毫不会重复传输;At least once,至少一次,消息毫不会丢,可是可能会重复;Exactly once,精确一次,每条消息确定会被传输一次且仅一次。对于大多数消息中间件而言,通常只提供 At most once 和 At least once 两种传输保障,对于第三种通常很难作到,由此消息幂等性也很难保证。

Kafka 自 0.11 版本开始引入了幂等性和事务,Kafka 的幂等性是指单个生产者对于单分区单会话的幂等,而事务能够保证原子性地写入到多个分区,即写入到多个分区的消息要么所有成功,要么所有回滚,这两个功能加起来可让 Kafka 具有 EOS(Exactly Once Semantic)的能力。

不过若是要考虑全局的幂等,还须要与从上下游方面综合考虑,即关联业务层面,幂等处理自己也是业务层面所须要考虑的重要议题。如下游消费者层面为例,有可能消费者消费完一条消息以后没有来得及确认消息就发生异常,等到恢复以后又得从新消费原来消费过的那条消息,那么这种类型的消息幂等是没法有消息中间件层面来保证的。若是要保证全局的幂等,须要引入更多的外部资源来保证,好比以订单号做为惟一性标识,而且在下游设置一个去重表。

事务性消息

事务自己是一个并不陌生的词汇,事务是由事务开始(Begin Transaction)和事务结束(End Transaction)之间执行的全体操做组成。支持事务的消息中间件并不在少数,Kafka 和 RabbitMQ 都支持,不过此二者的事务是指生产者发生消息的事务,要么发送成功,要么发送失败。消息中间件能够做为用来实现分布式事务的一种手段,但其自己并不提供全局分布式事务的功能。

下表是对 Kafka 与 RabbitMQ 功能的总结性对比及补充说明。

 性能

功能维度是消息中间件选型中的一个重要的参考维度,但这并非惟一的维度。有时候性能比功能还要重要,何况性能和功能不少时候是相悖的,鱼和熊掌不可兼得,Kafka 在开启幂等、事务功能的时候会使其性能下降,RabbitMQ 在开启 rabbitmq_tracing 插件的时候也会极大的影响其性能。消息中间件的性能通常是指其吞吐量,虽然从功能维度上来讲,RabbitMQ 的优点要大于 Kafka,可是 Kafka 的吞吐量要比 RabbitMQ 高出 1 至 2 个数量级,通常 RabbitMQ 的单机 QPS 在万级别以内,而 Kafka 的单机 QPS 能够维持在十万级别,甚至能够达到百万级。

消息中间件的吞吐量始终会受到硬件层面的限制。就以网卡带宽为例,若是单机单网卡的带宽为 1Gbps,若是要达到百万级的吞吐,那么消息体大小不得超过 (1Gb/8)/100W,即约等于 134B,换句话说若是消息体大小超过 134B,那么就不可能达到百万级别的吞吐。这种计算方式一样能够适用于内存和磁盘。

时延做为性能维度的一个重要指标,却每每在消息中间件领域所被忽视,由于通常使用消息中间件的场景对时效性的要求并非很高,若是要求时效性彻底能够采用 RPC 的方式实现。消息中间件具有消息堆积的能力,消息堆积越大也就意味着端到端的时延也就越长,与此同时延时队列也是某些消息中间件的一大特点。那么为何还要关注消息中间件的时延问题呢?消息中间件可以解耦系统,对于一个时延较低的消息中间件而言,它可让上游生产者发送消息以后能够迅速的返回,也可让消费者更加快速的获取到消息,在没有堆积的状况下可让总体上下游的应用之间的级联动做更加高效,虽然不建议在时效性很高的场景下使用消息中间件,可是若是所使用的消息中间件的时延方面比较优秀,那么对于总体系统的性能将会是一个不小的提高。

 可靠性 + 可用性

消息丢失是使用消息中间件时所不得不面对的一个同点,其背后消息可靠性也是衡量消息中间件好坏的一个关键因素。尤为是在金融支付领域,消息可靠性尤其重要。然而说到可靠性必然要说到可用性,注意这二者之间的区别,消息中间件的可靠性是指对消息不丢失的保障程度;而消息中间件的可用性是指无端障运行的时间百分比,一般用几个 9 来衡量。

从狭义的角度来讲,分布式系统架构是一致性协议理论的应用实现,对于消息可靠性和可用性而言也能够追溯到消息中间件背后的一致性协议。对于 Kafka 而言,其采用的是相似 PacificA 的一致性协议,经过 ISR(In-Sync-Replica)来保证多副本之间的同步,而且支持强一致性语义(经过 acks 实现)。对应的 RabbitMQ 是经过镜像环形队列实现多副本及强一致性语义的。多副本能够保证在 master 节点宕机异常以后能够提高 slave 做为新的 master 而继续提供服务来保障可用性。Kafka 设计之初是为日志处理而生,给人们留下了数据可靠性要求不要的不良印象,可是随着版本的升级优化,其可靠性获得极大的加强,详细能够参考 KIP101。就目前而言,在金融支付领域使用 RabbitMQ 居多,而在日志处理、大数据等方面 Kafka 使用居多,随着 RabbitMQ 性能的不断提高和 Kafka 可靠性的进一步加强,相信彼此都能在之前不擅长的领域分得一杯羹。

同步刷盘是加强一个组件可靠性的有效方式,消息中间件也不例外,Kafka 和 RabbitMQ 均可以支持同步刷盘,可是笔者对同步刷盘有必定的疑问:绝大多数情景下,一个组件的可靠性不该该由同步刷盘这种极其损耗性能的操做来保障,而是采用多副本的机制来保证。

这里还要说起的一个方面是扩展能力,这里我狭隘地将此概括到可用性这一维度,消息中间件的扩展能力可以加强其用可用能力及范围,好比前面提到的 RabbitMQ 支持多种消息协议,这个就是基于其插件化的扩展实现。还有从集群部署上来说,归功于 Kafka 的水平扩展能力,其基本上能够达到线性容量提高的水平,在 LinkedIn 实践介绍中就说起了有部署超过千台设备的 Kafka 集群。

 运维管理

在消息中间件的使用过程当中不免会出现各式各样的异常状况,有客户端的,也有服务端的,那么怎样及时有效的进行监测及修复。业务线流量有峰值又低谷,尤为是电商领域,那么怎样前进行有效的容量评估,尤为是大促期间?脚踢电源、网线被挖等事件层出不穷,如何有效的作好异地多活?这些都离不开消息中间件的衍生产品——运维管理。

运维管理也能够进行进一步的细分,好比:申请、审核、监控、告警、管理、容灾、部署等。

申请、审核很好理解,在源头对资源进行管控,既能够进行有效校订应用方的使用规范,配和监控也能够作好流量统计与流量评估工做,通常申请、审核与公司内部系统交融性较大,不适合使用开源类的产品。

监控、告警也比较好理解,对消息中间件的使用进行全方位的监控,便可觉得系统提供基准数据,也能够在检测到异常的状况配合告警,以便运维、开发人员的迅速介入。除了通常的监控项(好比硬件、GC 等)以外,对于消息中间件还须要关注端到端时延、消息审计、消息堆积等方面。对于 RabbitMQ 而言,最正统的监控管理工具莫过于 rabbitmq_management 插件了,可是社区内还有 AppDynamics, Collectd, DataDog, Ganglia, Munin, Nagios, New Relic, Prometheus, Zenoss 等多种优秀的产品。Kafka 在此方面也绝不逊色,好比:Kafka Manager, Kafka Monitor, Kafka Offset Monitor, Burrow, Chaperone, Confluent Control Center 等产品,尤为是 Cruise 还能够提供自动化运维的功能。

无论是扩容、降级、版本升级、集群节点部署、仍是故障处理都离不开管理工具的应用,一个配套完备的管理工具集能够在遇到变动时作到事半功倍。故障可大可小,通常是一些应用异常,也能够是机器掉电、网络异常、磁盘损坏等单机故障,这些故障单机房内的多副本足以应付。若是是机房故障就要涉及异地容灾了,关键点在于如何有效的进行数据复制,对于 Kafka 而言,能够参考 MirrorMarker、uReplicator 等产品,而 RabbitMQ 能够参考 Federation 和 Shovel。

 社区力度及生态发展

对于目前流行的编程语言而言,如 Java、Python,若是你在使用过程当中遇到了一些异常,基本上能够经过搜索引擎的帮助来获得解决,由于一个产品用的人越多,踩过的坑也就越多,对应的解决方案也就越多。对于消息中间件也一样适用,若是你选择了一种“生僻”的消息中间件,可能在某些方面运用的驾轻就熟,可是版本更新缓慢、遇到棘手问题也难以获得社区的支持而越陷越深;相反若是你选择了一种“流行”的消息中间件,其更新力度大,不只能够迅速的弥补以前的不足,并且也能顺应技术的快速发展来变动一些新的功能,这样可让你以“站在巨人的肩膀上”。在运维管理维度咱们说起了 Kafka 和 RabbitMQ 都有一系列开源的监控管理产品,这些正是得益于其社区及生态的迅猛发展。

消息中间件选型误区探讨

在进行消息中间件选型以前能够先问本身一个问题:是否真的须要一个消息中间件?在搞清楚这个问题以后,还能够继续问本身一个问题:是否须要本身维护一套消息中间件?不少初创型公司为了节省成本会选择直接购买消息中间件有关的云服务,本身只须要关注收发消息便可,其他的均可之外包出去。

不少人面对消息中间件时会有一种自研的冲动,你彻底能够对 Java 中的 ArrayBlockingQueue 作一个简单的封装,你也能够基于文件、数据库、Redis 等底层存储封装而造成一个消息中间件。消息中间件作为一个基础组件并无想象中的那么简单,其背后还须要配套的管理运维整个生态的产品集。自研还有会交接问题,若是文档不齐全、运做不规范将会带给新人噩梦般的体验。是否真的有自研的必要?若是不是 KPI 的压迫能够先考虑下这 2 个问题:1. 目前市面上的消息中间件是否都真的没法知足目前业务需求? 2. 团队是否有足够的能力、人力、财力、精力来支持自研?

不少人在作消息中间件选型时会参考网络上的不少对比类的文章,可是其专业性、严谨性、以及其政治立场问题都有待考证,须要带着怀疑的态度去审视这些文章。好比有些文章会在没有任何限定条件及场景的状况下直接定义某款消息中间件最好,还有些文章没有指明消息中间件版本及测试环境就来作功能和性能对比分析,诸如此类的文章均可以唾弃之。

消息中间件犹如小马过河,选择合适的才最重要,这须要贴合自身的业务需求,技术服务于业务,大致上能够根据上一节所说起的功能、性能等 6 个维度来一一进行筛选。更深层次的抉择在于你可否掌握其魂,笔者鄙见:RabbitMQ 在于 routing,而 Kafka 在于 streaming,了解其根本对于本身可以对症下药选择到合适的消息中间件尤其重要。

消息中间件选型切忌一味的追求性能或者功能,性能能够优化,功能能够二次开发。若是要在功能和性能方面作一个抉择的话,那么首选性能,由于整体上来讲性能优化的空间没有功能扩展的空间大。然而对于长期发展而言,生态又比性能以及功能都要重要。

不少时候,对于可靠性方面也容易存在一个误区:想要找到一个产品来保证消息的绝对可靠,很不幸的是这世界上没有绝对的东西,只能说尽可能趋于完美。想要尽量的保障消息的可靠性也并不是单单只靠消息中间件自己,还要依赖于上下游,须要从生产端、服务端和消费端这 3 个维度去努力保证,《RabbitMQ 消息可靠性分析》这篇文章就从这 3 个维度去分析了 RabbitMQ 的可靠性。

消息中间件选型还有一个考量标准就是尽可能贴合团队自身的技术栈体系,虽说没有蹩脚的消息中间件只有蹩脚的程序员,可是让一个 C 栈的团队去深挖 PhxQueue 总比去深挖 Scala 编写的 Kafka 要容易的多。

消息中间件大道至简:一发一存一消费,没有最好的消息中间件,只有最合适的消息中间件。

相关文章
相关标签/搜索