Spring整合rabbitmq实践(一):基础

Spring整合rabbitmq实践(一):基础,第1张

起因:在实际项目开发过程中,需要使用RabbitMQ来实现消息队列的功能,但仅仅实现功能之后并不能对自己满足,既然学一次,就要更深的了解她,吃一吃架构方面的相关内容,提升自己。

RabbitMQ在镜像集群中,机器其实是平行关系,所有的节点都是互相复制的

场景描述:

A是Master

B是Slave

A正常运行,B宕机了,只需要启动B即可,B就会自动加入集群

A和B都宕机了,只要A在B之前启动就可以了

A和B都宕机了,A启动不起来了,即便是B启动了,有可以B直接启动不了啦

B和C都加入了A为Master的集群,这个时候都需要将B和C从A的集群中forget,B和C启动不起来了

RabbitMQv32版本以后提供了一个离线清除集群节点的命令参数,也就是节点无法启动状态下

HAProxy是一款提供高可用的负载均衡器(之前大家都是使用的Nginx居多,upstream反向代理实现负载均衡非常容易),HAProxy可以基于TCP四层(Lvs也是TCP四层的),>ThingsBoard设计为:
扩展性:可水平扩展的平台使用领先的开源技术构建。
容错性:没有单点故障集群中的每个节点都是相同的。
健壮性:单个服务器节点可以根据使用情况处理以万级别的设备,集群可以处理数百万级别设备。
自定义:使用可自定义的部件和规则引擎节点可以轻松添加新功能。
持久化:永远不会丢失你的数据。
参见如下架构图及关键组件和相关接口。
通信
ThingsBoard提供了基于MQTT、>前提:比如两个节点A和B组成一个镜像队列

场景1: A先停, B后停
方案1: 该场景下B是Master,只要先启动B,再启动A即可。或者先启动A,再30秒之内启动B接口恢复镜像队列

场景2: A、B同时停机
方案2:该场景可能由于机房断电等原因造成的,只需在30秒之内连续启动A和B即可恢复镜像

场景3:A先停,B后停,且A无法恢复
方案3: 该场景是1场景的加强版,因为B是Master,所以等B起来以后,在B节点调用控制台命令: rabbitmqctl forget_cluster_node A 解除与A的Cluster关系,再将新的Slave节点加入B即可重新恢复镜像队列

场景4: A先停,B后停,且B无法恢复
方案4:该场景是场景3的加强版,比较难处理,原因是因为Master节点无法恢复,早在31x时代之前没有什么好的解决方案,但是现在已经有解决方案了,在342以后的版本。因为B是主节点,所有直接启动A是不行的,当A无法启动的时候,也就没办法在A节点上调用之前的 rabbitmqctl forget_cluster_node B 命令了。新版本中 forget_cluster_node 支持--offline参数

这就意味着允许rabbitmqctl在理想节点上执行该命令,迫使RabbitMQ在未启动Slave节点中选择一个节点作为Master。当在A节点执行 rabbitmqctl forget_cluster_node --offline B 时,RabbitMQ会mock一个节点代表A,执行 forget_cluster_node 命令将B剔除cluster,然后A就可以正常的启动了,最后将新的Slave节点加入A即可恢复镜像队列

场景5:A先停、B后停,且A、B均无法恢复,但是能得到A或B的磁盘文件
方案5:这种场景更加难处理,只能通过恢复数据的方式去尝试恢复,将A与B的数据文件模式在$RABBIT_HOME/var/lib/目录中,把它拷贝到新的节点对应的mulxia,再将新的节点hostname改成A或B的hostname,如果是A节点(Slave)的磁盘文件,则按照场景4处理即可,如果是B节点(Master)的磁盘文件,则按照场景3处理即可,最后新的Slave加入新节点后完成恢复。

场景6:A先停、B后停,且A、B均无法恢复,且得不到A和B的磁盘文件

恩,你可以直接跑路了o(╯□╰)o

11、什么是RabbitMQ?

RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成,因此也是继承了这些优点。

12、什么是AMQP

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。它从生产者接收消息并递送给消费者,在这个过程中,根据规则进行路由,缓存与持久化。

AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如: Python 、Ruby、NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

13、RabbitMQ的基础概念

14、RabbitMQ的特性

21、环境:两台Ubuntu1604主机
1027053 rabbitmq-1
10270130 rabbitmq-2

必须保证各个主机名之间可以ping通
22、安装Erlang

23、安装rabbitmq

24、安装完成后,验证一下服务是否正常

搭建好的rabbitmq默认是没有配置文件的,需要我们来手动添加

Rabbitmq的一些运行脚本存放在 /usr/sbin 下面

25、开启web管理插件

251、创建一个用户nova,并设置密码为123456

252、查看现有用户表

这个时候nova用户是不能访问web管理插件的,需要配置用户角色,用户角色可分为五类,超级管理员, 监控者, 策略制定者, 普通管理者以及其他。

可登陆管理控制台(启用management plugin的情况下),可查看所有的信息,并且可以对用户,策略(policy)进行 *** 作。

可登陆管理控制台(启用management plugin的情况下),同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)

可登陆管理控制台(启用management plugin的情况下), 同时可以对policy进行管理。但无法查看节点的相关信息。

仅可登陆管理控制台(启用management plugin的情况下),无法看到节点信息,也无法对策略进行管理。

无法登陆管理控制台,通常就是普通的生产者和消费者。

将nova添加到administrator用户组

此时的nova用户只能通过本地来登录其他的IP无法直接使用这个账号。所以需要对他进行授权,使用户nova /(可以访问虚拟主机) 中所有资源的配置、写、读权限以便管理其中的资源

查看用户授权

253、开启web管理插件并重启rabbitmq服务

以下为关闭插件命令

通过浏览器访问 [>现在的系统已经离不开消息队列,我们可以用他做异步,做解耦,做流处理,做可靠传输。市面上的消息队列也有很多,比如阿里云的oss,RocketMQ,ZeroMQ,RabbitMQ,Kafka等,甚至Java中的List也可以称为一个简单的消息队列,种类如此繁多,我们该如何选择呢?现在主流的消息队列可以分为两类,一类以kafka为代表,一类以RabbitMQ为代表,二者有很多相似的地方,也都有各自的优势。

那我们平时构建系统的时候,该选择哪种消息队列呢?这里我们将RbbitMQ与kafka做一下对比(因为他们都是spring默认集成的消息队列),以便于我们做出最优的选择。

RabbitMQ:关于rabbit的详细介绍这里不说,感兴趣的可以看我之前的文章,一句话rabbit作为传统意义上的消息队列,基于AMQP协议开发,倾向于做按各种规则的消息转发。

Kafka:关于kafka的详细介绍会在以后的文章里写,因为刚开始用,想深入了解后再写出来。kafka更倾向于一个流式管道的概念,消息从一处流向另一处,吞吐量比rabbit更高。

接下来通过俩张图来理解他俩的设计与区别。

首先来看rabbit,他通过broker来进行统一调配消息去向,生产者通过指定的规则将消息发送到broker,broker再按照规则发送给消费者进行消费,消费者方可以选择消费方式为pull或者是broker主动push,支持的消费模式也有多种,点对点,广播,正则匹配等。

Kafka主要为高吞吐量的订阅发布系统而设计,主要追求速度与持久化。kafka中的消息由键、值、时间戳组成,kafka不记录每个消息被谁使用,只通过偏移量记录哪些消息是未读的,kafka中可以指定消费组来实现订阅发布的功能。

了解了二者大体的区别以后,我们再来看具体的适用场景。

Kafka:

1从A系统到B系统的消息没有复杂的传递规则,并且具有较高的吞吐量要求。

2需要访问消息的历史记录的场景,因为kafak是持久化消息的,所以可以通过偏移量访问到那些已经被消费的消息(前提是磁盘空间足够,kafka没有将日志文件删除)

3流处理的场景。处理源源不断的流式消息,比较典型的是日志的例子,将系统中源源不断生成的日志发送到kafka中。

rabbit:

1需要对消息进行更加细粒度的控制,包括一些可靠性方面的特性,比如死信队列。

2需要多种消费模式(点对点,广播,订阅发布等)

3消息需要通过复杂的路由到消费者。

最后是关于性能方面,众所周知,kafka的吞吐量优于rabbit,大约是100k/sec,而rabbit大约是20k/sec,但是这个不应该成为我们选择的主要原因,因为性能方面的瓶颈都是可以通过集群方案来解决的。

最后要说的是,没有最好的队列,只有最合适的队列。

参考:Understanding When to use RabbitMQ or Apache Kafka

消息总线屏蔽了消息发送、路由、分组、存储、消费负载、通信、高可用等一系列技术问题,对业务开发者来说只需要调用生产者或消费者SDK即可,简化了接入流程并提升了可靠性。
消息总线整体架构图如下图所示

为保证消息在整个流程中减少复杂度,将消息体设计为如下统一结构

通过前面的介绍,可以了解到生产者发送的消息在经过Broker(SKD)时进行了路由、分组,具体策略如下:

消息经过Broker默认会进入一个RealTime Queue的队列中,Deliver集群中会有多个Listener监听RealTime Queue,在Deliver服务内,通过Dispatcher来控制消息并发及总数,当某种消息的发送量超过阈值时,就会触发处罚策略,将消息转发到Async Queue中,避免消费Worker都被同一个类型的消息占用,而Async Queue会被独立的Deliver服务监听进行消费,不影响RealTime Queue的消费,如果投递失败则会进入Retry Queue,满足一定条件后将会继续投递

为了保证消费时的高可用,Deliever集群在负责进行消费协议转换之外,也做了一些策略来保证消费端的高可用


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/13089909.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-30
下一篇 2023-05-30

发表评论

登录后才能评论

评论列表(0条)

保存