深入了解RocketMQ集群架构原理以及高可用集群搭建详细过程
RocketMQ
RocketMQ简单介绍
RocketMQ是阿里巴巴在2012年开源的分布式消息中间件,目前已经捐赠给Apache基金会,于2016年11月成为 Apache 孵化项目,并于2017年9月25日成为 Apache 的顶级项目。其前身是MetaQ (Metamorphosis),它并不遵循任何规范(如JMS,AMQP等),但是参考了各种规范与同类产品的设计思想,其主要借鉴的产品是Apache Kafka。
中间件是位于平台(硬件和操作系统)和应用之间的通用服务,这些服务具有标准的程序接口和协议。针对不同的操作系统和硬件平台,中间件可以有符合接口和协议规范的多种实现。
RocketMQ=Rocket Message Queue也就是消息队列,作为经历过多次阿里巴巴双十一这种“超级工程”的洗礼并有稳定出色表现的国产中间件,以其高性能、低延时和高可靠等特性近年来也已经被越来越多的国内企业使用。其主要特点有:
- 支持发布/订阅(Pub/Sub)和点对点(P2P)消息模型
- 在一个队列中可靠的先进先出(FIFO)和严格的顺序传递 (RocketMQ可以保证严格的消息顺序,而ActiveMQ无法保证)
- 支持拉(pull)和推(push)两种消息模式 (Push好理解,比如在消费者端设置Listener回调;而Pull,控制权在于应用,即应用需要主动的调用拉消息方法从Broker获取消息,这里面存在一个消费位置记录的问题(如果不记录,会导致消息重复消费))
- 单一队列百万消息的堆积能力 (RocketMQ提供亿级消息的堆积能力,这不是重点,重点是堆积了亿级的消息后,依然保持写入低延迟)
- 支持多种消息协议,如 JMS、MQTT 等
- 分布式高可用的部署架构,满足至少一次消息传递语义 (RocketMQ原生就是支持分布式的,而ActiveMQ原生存在单点性)
- 提供 docker 镜像用于隔离测试和云集群部署
- 提供配置、指标和监控等功能丰富的Dashboard
- 组(Group)有Producer/Consumer Group。 ActiveMQ中并没有Group这个概念,而在RocketMQ中理解Group的机制很重要。通过Group机制,让RocketMQ天然的支持消息负载均衡!比如某个Topic有9条消息,其中一个Consumer Group有3个实例(3个进程 OR 3台机器),那么每个实例将均摊3条消息!(注意RocketMQ只有一种模式,即发布订阅模式。)
- 消息失败重试机制、高效的订阅者水平扩展能力、强大的API、事务机制等等
基本概念
- Message Model,RocketMQ主要由 Producer、Broker、Consumer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。ConsumerGroup 由多个Consumer 实例构成。
- Producer,生产者Producer的作用就是将业务应用系统生成的消息发送给brokers。生产者本身既可以产生消息,如读取文本信息等,也可以对外提供接口,由外部应用来调用接口,再由生产者将收到的消息发送到 MQ。RocketMQ提供了多种发送范例:同步,异步和单向。
- Producer Group,官网的解释:具有相同角色的生产者被分在同一个组。简单来说就是多个发送同一类消息的生产者称之为一个生产者组。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。
- Consumer,消息消费者,消费 MQ 上的消息的应用程序就是消费者,至于消息是否进行逻辑处理,还是直接存储到数据库等取决于业务需要。要具体需求具体分析。一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费。
- Pull Consumer,拉取式消费(Pull Consumer),Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。一旦获取了批量消息,应用就会启动消费过程。
- Push Consumer,推动式消费(Push Consumer),Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高。
- Consumer Group,消费者组,和生产者类似,消费同一类消息的多个 consumer 实例组成一个消费者组。消费者组是一个很棒的概念,通过它,在消息消耗方面实现负载平衡和容错的目标非常容易。要注意的是,消费者组的消费者实例必须订阅完全相同的Topic。RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。
- Clustering,集群消费(Clustering),集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息。
- Broadcasting,广播消费(Broadcasting),广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。
- Normal Ordered Message,普通顺序消息(Normal Ordered Message),普通顺序消费模式下,消费者通过同一个消费队列收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。
- Strictly Ordered Message,严格顺序消息(Strictly Ordered Message),严格顺序消息模式下,消费者收到的所有消息均是有顺序的。
- Topic,Topic 是生产者传递消息而消费者提取消息的类别,是一种消息的逻辑分类,比如说你有订单类的消息,也有库存类的消息,那么就需要进行分类,一个是订单 Topic 存放订单相关的消息,一个是库存 Topic 存储库存相关的消息。具体来说,一个Topic可能有零个,一个或多个生产者向其发送消息,相反,生产者也可以发送消息到不同的Topic。从消费者的角度来看,一个主题可以由零个,一个或多个消费者组订阅。与此类似,消费者组可以订阅一个或多个Topic,只要该组的实例保持其订阅一致即可。
- Message,Message 是消息的载体,生产和消费数据的最小单位,一个 Message 必须指定 topic,相当于寄信的地址。RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。系统提供了通过Message ID和Key查询消息的功能。Message 还有一个可选的 tag 设置,以便消费端可以基于 tag 进行过滤消息。也可以添加额外的键值对,例如你需要一个业务 key 来查找 broker 上的消息,方便在开发过程中诊断问题。
- Tag, 为消息设置的标志,用于同一主题下区分不同类型的消息。换句话说是子主题,为用户提供了额外的灵活性。一般在相同业务模块中通过引入标签来标记不同用途的消息。标签将有助于保持代码整洁和一致,标签还可以简化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。
- Broker,Broker 是RocketMQ系统的主要组成部分,是RocketMQ系统的主要角色,它接收从生产者发送的消息,进行存储,并为消费者拉取消息的请求做好准备。它还存储与消息相关的元数据,包括消费者组,消费者进度偏移量offset和主题/队列信息。
- Name Server,Name Server 充当了路由信息的提供者,为 producer 和 consumer 提供路由信息。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。
特性
- 订阅与发布,消息的发布是指某个生产者向某个topic发送消息;消息的订阅是指某个消费者关注了某个topic中带有某些tag的消息,进而从该topic消费数据。
- 消息顺序,消息有序指的是一类消息消费时,能按照发送的顺序来消费。例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成。消费时要按照这个顺序消费才能有意义,但是同时订单之间是可以并行消费的。RocketMQ可以严格的保证消息有序。顺序消息分为全局顺序消息与分区顺序消息,全局顺序是指某个Topic下的所有消息都要保证顺序;部分顺序消息只要保证每一组消息被顺序消费即可。全局顺序 对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费。 适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景;分区顺序 对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。 Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。 适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。
- 消息过滤,RocketMQ的消费者可以根据Tag进行消息过滤,也支持自定义属性过滤。消息过滤目前是在Broker端实现的,优点是减少了对于Consumer无用消息的网络传输,缺点是增加了Broker的负担而且实现相对复杂。
- 消息可靠性,RocketMQ支持消息的高可靠,影响消息可靠性的几种情况:
1、Broker非正常关闭;
2、Broker异常Crash;
3、OS Crash;
4、机器断电,但是能立即恢复供电情况;
5、机器无法开机(可能是cpu、主板、内存等关键设备损坏);
6、磁盘设备损坏
1、2、3、4 四种情况都属于硬件资源可立即恢复情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。
5、6属于单点故障,且无法恢复,一旦发生,在此单点上的消息全部丢失。RocketMQ在这两种情况下,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。注:RocketMQ从3.0版本开始支持同步双写。 - 至少一次,至少一次(At least Once)指每个消息必须投递一次。Consumer先Pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息,所以RocketMQ可以很好的支持此特性。
- 回溯消费,回溯消费是指Consumer已经消费成功的消息,由于业务上需求需要重新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。并且重新消费一般是按照时间维度,例如由于Consumer系统故障,恢复后需要重新消费1小时前的数据,那么Broker要提供一种机制,可以按照时间维度来回退消费进度。RocketMQ支持按照时间回溯消费,时间维度精确到毫秒。
- 事务消息,RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败。RocketMQ的事务消息提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的最终一致。
- 定时消息,定时消息(延迟队列)是指消息发送到broker后,不会立即被消费,等待特定时间投递给真正的topic。 broker有配置项messageDelayLevel,默认值为“1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”,18个level。可以配置自定义messageDelayLevel。注意,messageDelayLevel是broker的属性,不属于某个topic。发消息时,设置delayLevel等级即可:msg.setDelayLevel(level)。level有以下三种情况:
1、level == 0,消息为非延迟消息;
2、1<=level<=maxLevel,消息延迟特定时间,例如level == 1,延迟1s;
3、level > maxLevel,则level== maxLevel,例如level==20,延迟2h;
定时消息会暂存在名为SCHEDULE_TOPIC_XXXX的topic中,并根据delayTimeLevel存入特定的queue,queueId = delayTimeLevel – 1,即一个queue只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。broker会调度地消费SCHEDULE_TOPIC_XXXX,将消息写入真实的topic。
需要注意的是,定时消息会在第一次写入和调度写入真实topic时都会计数,因此发送数量、tps都会变高。 - 消息重试,Consumer消费消息失败后,要提供一种重试机制,令消息再消费一次。Consumer消费消息失败通常可以认为有以下几种情况:
1、由于消息本身的原因,例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。这种错误通常需要跳过这条消息,再消费其它消息,而这条失败的消息即使立刻重试消费,99%也不成功,所以最好提供一种定时重试机制,即过10秒后再重试。
2、由于依赖的下游应用服务不可用,例如db连接不可用,外系统网络不可达等。遇到这种错误,即使跳过当前失败的消息,消费其他消息同样也会报错。这种情况建议应用sleep 30s,再消费下一条消息,这样可以减轻Broker重试消息的压力。
RocketMQ会为每个消费组都设置一个Topic名称为“%RETRY%+consumerGroup”的重试队列(这里需要注意的是,这个Topic的重试队列是针对消费组,而不是针对每个Topic设置的),用于暂时保存因为各种异常而导致Consumer端无法消费的消息。考虑到异常恢复起来需要一些时间,会为重试队列设置多个重试级别,每个重试级别都有与之对应的重新投递延时,重试次数越多投递延时就越大。RocketMQ对于重试消息的处理是先保存至Topic名称为“SCHEDULE_TOPIC_XXXX”的延迟队列中,后台定时任务按照对应的时间进行Delay后重新保存至“%RETRY%+consumerGroup”的重试队列中。 - 消息重投,生产者在发送消息时,同步消息失败会重投,异步消息有重试,oneway没有任何保证。消息重投保证消息尽可能发送成功、不丢失,但可能会造成消息重复,消息重复在RocketMQ中是无法避免的问题。消息重复在一般情况下不会发生,当出现消息量大、网络抖动,消息重复就会是大概率事件。另外,生产者主动重发、consumer负载变化也会导致重复消息。如下方法可以设置消息重试策略:
1、retryTimesWhenSendFailed:同步发送失败重投次数,默认为2,因此生产者会最多尝试发送retryTimesWhenSendFailed + 1次。不会选择上次失败的broker,尝试向其他broker发送,最大程度保证消息不丢。超过重投次数,抛出异常,由客户端保证消息不丢。当出现RemotingException、MQClientException和部分MQBrokerException时会重投。
2、retryTimesWhenSendAsyncFailed:异步发送失败重试次数,异步重试不会选择其他broker,仅在同一个broker上做重试,不保证消息不丢。
3、retryAnotherBrokerWhenNotStoreOK:消息刷盘(主或备)超时或slave不可用(返回状态非SEND_OK),是否尝试发送到其他broker,默认false。十分重要消息可以开启。 - 流量控制,生产者流控,因为broker处理能力达到瓶颈;消费者流控,因为消费能力达到瓶颈。
生产者流控:
1、commitLog文件被锁时间超过osPageCacheBusyTimeOutMills时,参数默认为1000ms,返回流控。
2、如果开启transientStorePoolEnable == true,且broker为异步刷盘的主机,且transientStorePool中资源不足,拒绝当前send请求,返回流控。
3、broker每隔10ms检查send请求队列头部请求的等待时间,如果超过waitTimeMillsInSendQueue,默认200ms,拒绝当前send请求,返回流控。
4、broker通过拒绝send 请求方式实现流量控制。
注意,生产者流控,不会尝试消息重投。
消费者流控:
1、消费者本地缓存消息数超过pullThresholdForQueue时,默认1000。
2、消费者本地缓存消息大小超过pullThresholdSizeForQueue时,默认100MB。
3、消费者本地缓存消息跨度超过consumeConcurrentlyMaxSpan时,默认2000。
消费者流控的结果是降低拉取频率。 - 死信队列,死信队列用于处理无法被正常消费的消息。当一条消息初次消费失败,消息队列会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。
RocketMQ将这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),将存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。在RocketMQ中,可以通过使用console控制台对死信队列中的消息进行重发来使得消费者实例再次进行消费。
深层解析
集群原理
技术架构
RocketMQ架构上主要分为四部分,如上图所示:
- Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
- Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
- NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。
- BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能,Broker包含了以下几个重要子模块。
1、Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
2、Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
3、Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
4、HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
5、Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。
部署架构
RocketMQ 网络部署特点:
- NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。
- Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。 注意:当前RocketMQ版本在部署架构上支持一Master多Slave,但只有BrokerId=1的从服务器才会参与消息的读负载。
- Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic 服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。
- Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,消费者在向Master拉取消息时,Master服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读I/O),以及从服务器是否可读等因素建议下一次是从Master还是Slave拉取。
下面是一张 RocketMQ 的部署结构图,里面涉及了 RocketMQ 核心的四大组件:Name Server、Broker、Producer、Consumer ,每个组件都可以部署成集群模式进行水平扩展。
结合部署架构图,描述集群工作流程:
- 启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。
- Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
- 收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。
- Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。
- Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。
Rocketmq高可用集群搭建详细过程
集群部署方式
单Master模式
只有一个 Master节点,这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用。不建议线上环境使用,可以用于本地测试。
- 优点:配置简单,方便部署;
- 缺点:这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用,不建议线上环境使用;
多Master模式
一个集群无Slave,全是Master,例如2个Master或者3个Master。
- 优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高;
- 缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响;
多Master多Slave模式-异步复制------以这种方式部署集群为例来搭建集群
每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级)。
- 优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样;
- 缺点:Master宕机,磁盘损坏情况下会丢失少量消息;
多Master多Slave模式-同步双写------线上使用的话,推荐使用此模式集群
每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功。
- 优点:数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高;
- 缺点:性能比异步复制模式略低(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机;
集群搭建
环境
介绍一下我们搭建集群的环境:
OS:CentOS Linux release 8.2.2004 (Core)
IP:192.168.0.24(1个master 和 1个slave) 192.168.0.27(1个master 和 1个slave)
jdk:1.8.0_271
git:2.18.2
maven:Apache Maven 3.6.3
防火墙是关闭状态,SELinux是Disabled。
双主双从异步复制集群部署情况
集群搭建过程
创建目录
在192.168.0.24和192.168.0.27两台机器上分别创建:
192.168.0.24:
[root@dxm24 ~]# mkdir -p /data/rocketmq
[root@dxm24 ~]# cd /data/rocketmq/
192.168.0.27:
[root@dxm27 ~]# mkdir -p /data/rocketmq
[root@dxm27 ~]# cd /data/rocketmq/
下载
在192.168.0.24和192.168.0.27两台机器中其中一台上执行wget命令,下载完成之后,scp到另一台机器即可。我们这里在192.168.0.24上执行下载,然后scp到192.168.0.27上。
[root@dxm24 rocketmq]# wget https://mirror.bit.edu.cn/apache/rocketmq/4.7.1/rocketmq-all-4.7.1-bin-release.zip
[root@dxm24 rocketmq]# ll -h
scp到192.168.0.27上:
在192.168.0.24这台机器上执行:
[root@dxm24 rocketmq]# scp rocketmq-all-4.7.1-bin-release.zip root@192.168.0.27:/data/rocketmq/
然后去192.168.0.27的/data/rocketmq目录下查看一下:
[root@dxm27 rocketmq]# ll -h
解压文件到 /usr/local/目录下
两台机器上都要执行
[root@dxm24 rocketmq]# unzip rocketmq-all-4.7.1-bin-release.zip -d /usr/local/
[root@dxm27 rocketmq]# unzip rocketmq-all-4.7.1-bin-release.zip -d /usr/local/
用户和组
两台机器上都要执行
#先检查用户rocketmq和组rocketmq是否存在
#检查组是否存在
cat /etc/group | grep rocketmq
#如果不存在,创建组
groupadd rocketmq
#检查用户rocketmq是否存在
cat /etc/passwd | grep rocketmq
或者
id rocketmq
#如果不存在,创建用户
useradd -g rocketmq rocketmq
创建存储路径
两台机器上都要执行:
在192.168.0.24上执行:
[root@dxm24 rocketmq]# mkdir -p /data/rocketmq/store/{rootdir-a-m,commitlog-a-m,consumequeue-a-m,index-a-m,checkpoint-a-m,abort-a-m,rootdir-b-s,commitlog-b-s,consumequeue-b-s,index-b-s,checkpoint-b-s,abort-b-s}
在192.168.0.27上执行:
[root@dxm27 rocketmq]# mkdir -p /data/rocketmq/store/{rootdir-b-m,commitlog-b-m,consumequeue-b-m,index-b-m,checkpoint-b-m,abort-b-m,rootdir-a-s,commitlog-a-s,consumequeue-a-s,index-a-s,checkpoint-a-s,abort-a-s}
修改hosts
两台服务器都要修改/etc/hosts,加入下面两行:
192.168.0.24 rocketmq-nameserver-1
192.168.0.27 rocketmq-nameserver-2
配置环境变量
两台服务器都要修改/etc/profile,加入下面两行:
export ROCKETMQ_HOME=/usr/local/rocketmq-all-4.7.1-bin-release
export PATH=$ROCKETMQ_HOME/bin:$PATH
使其生效:
[root@dxm24 rocketmq]# source /etc/profile
[root@dxm27 rocketmq]# source /etc/profile
修改RocketMQ配置文件
先查看RocketMQ配置文件有哪些:
[root@dxm27 rocketmq]# ll /usr/local/rocketmq-all-4.7.1-bin-release/conf/
- 2m-2s-async:双主双从异步刷盘(吞吐量较大,但是消息可能丢失)
- 2m-2s-sync:双主双从同步刷盘(吞吐量会下降,但是消息更安全)
- 2m-noslave:双主无从(单点故障),然后还可以直接配置broker.conf,进行单点环境配置
- dledger:用来实现主从切换的。集群中的节点会基于raft协议随机选举出一个leader,其他的就都是follower。通常正式环境都会采用这种方式来搭建集群。
如图,因为我们采用的是双主双从异步复制,默认的rocketmq已经为我们配置了相应配置目录2m-2s-async,所以修改的配置文件是2m-2s-async目录下的配置文件。
192.168.0.24 rocketmq-nameserver-1 角色:broker-a-master & broker-b-slave
所以在192.168.0.24机器上,要修改broker-a.properties和broker-b-s.properties:
[root@dxm24 rocketmq]# cd /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/
[root@dxm24 2m-2s-async]# vim broker-a.properties
broker-a.properties配置如下内容:
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=dxm-rocket-mq-cluster
#broker名字,名字一样的节点就是一组主从节点。注意此处不同的配置文件填写的不一样
brokerName=rocketmq-nameserver-1
#brokerId 0 表示 Master,>0 表示 Slave
brokerId=0
# Broker 对外服务的监听端口
listenPort=10911
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver-1:9876;rocketmq-nameserver-2:9876
# 删除文件时间点,默认凌晨 4点
deleteWhen=04
#文件保留时间,默认 48 小时
fileReservedTime=120
#Broker role有3种:SYNC MASTER、ASYNC MASTER、SLAVE。关键词SYNC和ASYNC表示Master和Slave之间同步消息的机制,SYNC即同步更新,指当Slave和Master消息同步完成后,再返回发送成功的状态。ASYNC即异步更新,master与slave有短暂消息延迟,毫秒级。本文在此使用了异步复制集群模式,线上环境推荐使用同步双写模式,即SYNC_MASTER
brokerRole=ASYNC_MASTER
# 刷盘方式 ASYNC_FLUSH 异步刷盘
flushDiskType=ASYNC_FLUSH
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/data/rocketmq/store/rootdir-a-m
#commitLog 存储路径
storePathCommitLog=/data/rocketmq/store/commitlog-a-m
#消费队列存储路径存储路径
storePathConsumeQueue=/data/rocketmq/store/consumequeue-a-m
#消息索引存储路径
storePathIndex=/data/rocketmq/store/index-a-m
#checkpoint 文件存储路径
storeCheckpoint=/data/rocketmq/store/checkpoint-a-m
#abort 文件存储路径
abortFile=/data/rocketmq/store/abort-a-m
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
broker-b-s.properties配置如下内容:
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=dxm-rocket-mq-cluster
#broker名字,名字一样的节点就是一组主从节点。注意此处不同的配置文件填写的不一样
brokerName=rocketmq-nameserver-2
#brokerId 0 表示 Master,>0 表示 Slave
brokerId=1
# Broker 对外服务的监听端口
listenPort=10921
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver-1:9876;rocketmq-nameserver-2:9876
# 删除文件时间点,默认凌晨 4点
deleteWhen=04
#文件保留时间,默认 48 小时
fileReservedTime=120
#Broker role有3种:SYNC MASTER、ASYNC MASTER、SLAVE。关键词SYNC和ASYNC表示Master和Slave之间同步消息的机制,SYNC即同步更新,指当Slave和Master消息同步完成后,再返回发送成功的状态。ASYNC即异步更新,master与slave有短暂消息延迟,毫秒级。本文在此使用了异步复制集群模式,线上环境推荐使用同步双写模式,即SYNC_MASTER
brokerRole=SLAVE
# 刷盘方式 ASYNC_FLUSH 异步刷盘
flushDiskType=ASYNC_FLUSH
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/data/rocketmq/store/rootdir-b-s
#commitLog 存储路径
storePathCommitLog=/data/rocketmq/store/commitlog-b-s
#消费队列存储路径存储路径
storePathConsumeQueue=/data/rocketmq/store/consumequeue-b-s
#消息索引存储路径
storePathIndex=/data/rocketmq/store/index-b-s
#checkpoint 文件存储路径
storeCheckpoint=/data/rocketmq/store/checkpoint-b-s
#abort 文件存储路径
abortFile=/data/rocketmq/store/abort-b-s
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
192.168.0.27 rocketmq-nameserver-2 角色:broker-b-master & broker-a-slave
所以在192.168.0.27机器上,要修改broker-b.properties和broker-a-s.properties:
[root@dxm27 conf]# cd /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/
[root@dxm27 2m-2s-async]# vim broker-b.properties
broker-b.properties配置如下内容:
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=dxm-rocket-mq-cluster
#broker名字,名字一样的节点就是一组主从节点。注意此处不同的配置文件填写的不一样
brokerName=rocketmq-nameserver-2
brokerIP1=192.168.0.27
#brokerId 0 表示 Master,>0 表示 Slave
brokerId=0
# Broker 对外服务的监听端口
listenPort=10911
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver-1:9876;rocketmq-nameserver-2:9876
# 删除文件时间点,默认凌晨 4点
deleteWhen=04
#文件保留时间,默认 48 小时
fileReservedTime=120
#Broker role有3种:SYNC MASTER、ASYNC MASTER、SLAVE。关键词SYNC和ASYNC表示Master和Slave之间同步消息的机制,SYNC即同步更新,指当Slave和Master消息同步完成后,再返回发送成功的状态。ASYNC即异步更新,master与slave有短暂消息延迟,毫秒级。本文在此使用了异步复制集群模式,线上环境推荐使用同步双写模式,即SYNC_MASTER
brokerRole=ASYNC_MASTER
# 刷盘方式 ASYNC_FLUSH 异步刷盘
flushDiskType=ASYNC_FLUSH
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/data/rocketmq/store/rootdir-b-m
#commitLog 存储路径
storePathCommitLog=/data/rocketmq/store/commitlog-b-m
#消费队列存储路径存储路径
storePathConsumeQueue=/data/rocketmq/store/consumequeue-b-m
#消息索引存储路径
storePathIndex=/data/rocketmq/store/index-b-m
#checkpoint 文件存储路径
storeCheckpoint=/data/rocketmq/store/checkpoint-b-m
#abort 文件存储路径
abortFile=/data/rocketmq/store/abort-b-m
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
broker-a-s.properties配置如下内容:
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=dxm-rocket-mq-cluster
#broker名字,名字一样的节点就是一组主从节点。注意此处不同的配置文件填写的不一样
brokerName=rocketmq-nameserver-1
#brokerId 0 表示 Master,>0 表示 Slave
brokerId=1
# Broker 对外服务的监听端口
listenPort=10921
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver-1:9876;rocketmq-nameserver-2:9876
# 删除文件时间点,默认凌晨 4点
deleteWhen=04
#文件保留时间,默认 48 小时
fileReservedTime=120
#Broker role有3种:SYNC MASTER、ASYNC MASTER、SLAVE。关键词SYNC和ASYNC表示Master和Slave之间同步消息的机制,SYNC即同步更新,指当Slave和Master消息同步完成后,再返回发送成功的状态。ASYNC即异步更新,master与slave有短暂消息延迟,毫秒级。本文在此使用了异步复制集群模式,线上环境推荐使用同步双写模式,即SYNC_MASTER
brokerRole=SLAVE
# 刷盘方式 ASYNC_FLUSH 异步刷盘
flushDiskType=ASYNC_FLUSH
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/data/rocketmq/store/rootdir-a-s
#commitLog 存储路径
storePathCommitLog=/data/rocketmq/store/commitlog-a-s
#消费队列存储路径存储路径
storePathConsumeQueue=/data/rocketmq/store/consumequeue-a-s
#消息索引存储路径
storePathIndex=/data/rocketmq/store/index-a-s
#checkpoint 文件存储路径
storeCheckpoint=/data/rocketmq/store/checkpoint-a-s
#abort 文件存储路径
abortFile=/data/rocketmq/store/abort-a-s
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
注意:
1、同一机器上两个实例的store目录不能相同,否则会报错 Lock failed,MQ already started
2、同一机器上两个实例的listenPort也不能相同。否则会报端口占用的错
修改启动脚本参数
调一下JVM,包括nameserver 和 broker。限于自己机器的配置,参数调小一下。但Rocketmq最少的堆是1g,否则无法启动。两台机器执行相同的操作。
- 修改runserver.sh
[root@dxm24 2m-2s-async]# cd /usr/local/rocketmq-all-4.7.1-bin-release/bin/
[root@dxm24 bin]# vim runserver.sh
修改以下内容:
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
- 修改runbroker.sh
[root@dxm24 bin]# vim runbroker.sh
修改以下内容:
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn1g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g"
最少的堆是1g,由于本地资源有限,我就设置最少了。
启动
要先启动nameserver,再启动broker,两台机器执行相同的操作。
- 启动nameserver,两台机器操作相同
这里我们创建一个启动脚本,也方便后续加入systemctl。
[root@dxm24 bin]# vim /usr/local/rocketmq-all-4.7.1-bin-release/start_rocketmq_nameserver.sh
内容如下:
#!/bin/bash
source /etc/profile
nohup sh /usr/local/rocketmq-all-4.7.1-bin-release/bin/mqnamesrv > /data/rocketmq/store/rocketmqnamesrv.log 2>&1 &
加上可执行权限:
[root@dxm24 bin]# chmod +x /usr/local/rocketmq-all-4.7.1-bin-release/start_rocketmq_nameserver.sh
然后scp到192.168.0.27机器相同目录上一份启动脚本文件。
[root@dxm24 bin]# scp /usr/local/rocketmq-all-4.7.1-bin-release/start_rocketmq_nameserver.sh root@192.168.0.27:/usr/local/rocketmq-all-4.7.1-bin-release/
然后在两台机器分别启动。
- 启动broker,要先启动broker master再启动broker slave。
这里两台机器不一样,所以要一个一个来。每台机器都是一个master和一个slave,所以要写4个启动脚本。
192.168.0.24 rocketmq-nameserver-1 角色:broker-a-master & broker-b-slave
start_broker_a_m.sh:
[root@dxm24 bin]# vim /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_a_m.sh
内容如下:
#!/bin/bash
nohup sh /usr/local/rocketmq-all-4.7.1-bin-release/bin/mqbroker -c /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/broker-a.properties > /data/rocketmq/store/broker-a-m.log 2>&1 &
加上可执行权限:
[root@dxm24 bin]# chmod +x /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_a_m.sh
start_broker_b_s.sh:
[root@dxm24 bin]# vim /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_b_s.sh
内容如下:
#!/bin/bash
nohup sh /usr/local/rocketmq-all-4.7.1-bin-release/bin/mqbroker -c /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/broker-b-s.properties > /data/rocketmq/store/broker-b-s.log 2>&1 &
加上可执行权限:
[root@dxm24 bin]# chmod +x /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_b_s.sh
192.168.0.27 rocketmq-nameserver-2 角色:broker-b-master & broker-a-slave
start_broker_b_m.sh:
[root@dxm27 2m-2s-async]# vim /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_b_m.sh
内容如下:
#!/bin/bash
nohup sh /usr/local/rocketmq-all-4.7.1-bin-release/bin/mqbroker -c /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/broker-b.properties > /data/rocketmq/store/broker-b-m.log 2>&1 &
加上可执行权限:
[root@dxm27 2m-2s-async]# chmod +x /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_b_m.sh
start_broker_a_s.sh:
[root@dxm27 2m-2s-async]# vim /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_a_s.sh
内容如下:
#!/bin/bash
nohup sh /usr/local/rocketmq-all-4.7.1-bin-release/bin/mqbroker -c /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/broker-a-s.properties > /data/rocketmq/store/broker-a-s.log 2>&1 &
加上可执行权限:
[root@dxm27 2m-2s-async]# chmod +x /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_a_s.sh
查看启动状态
上面我们启动完服务之后都看了日志,能确定是启动成功得。不过这里要说的是使用jps指令能看到一个NameSrvStartup进程和两个BrokerStartup进程。
查看集群信息
[root@dxm27 rocketmq-all-4.7.1-bin-release]# mqadmin clusterList --namesrvAddr=192.168.0.27:9876
[root@dxm24 bin]# mqadmin clusterList --namesrvAddr=192.168.0.24:9876
关闭服务
这个关闭服务,我就找其中一个机器一下,大家知道有这个东西就行。
- 关闭nameserver
[root@dxm27 bin]# mqshutdown namesrv
- 关闭broker
[root@dxm27 bin]# mqshutdown broker
部署管理控制台
从Rocket的社区扩展项目中获取一下控制台源码,然后maven打包编译,得到的jar包就是我们要的,然后运行这个jar包即可。我们在其中一台服务器上生成jar包即可。
- 第一步,从git上下载源码:
[root@dxm27 rocketmq]# git clone https://github.com/apache/rocketmq-externals.git
- 第二步,进入rocket-console目录然后使用maven打包编译:
[root@dxm27 rocketmq]# cd rocketmq-externals/rocketmq-console/
[root@dxm27 rocketmq-console]# mvn clean package -Dmaven.test.skip=true
看到这个就说明编译打包完成。在目录下就会多出一个target目录,cd到这个目录下就可以看到jar包。
rocketmq-console-ng-2.0.0.jar就是我们最终要的jar包。
启动console
启动之前,我们还是编写一个启动脚本,不为别的,就是为了方便自己。
拷贝jar包
把rocketmq-console-ng-2.0.0.jar拷贝到/usr/local/rocketmq-all-4.7.1-bin-release/下
[root@dxm27 target]# cp /data/rocketmq/rocketmq-externals/rocketmq-console/target/rocketmq-console-ng-2.0.0.jar /usr/local/rocketmq-all-4.7.1-bin-release/
注意: 在这个项目的application.properties中需要指定nameserver的地址,默认这个属性是空的。我们可以编辑jar包的这个配置文件,在里面配置一下属性,具体操作步骤如下:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# vim rocketmq-console-ng-2.0.0.jar
此时会列出jar里面所有的文件,需要输入/app搜索定位到application.properties配置文件,按一次回车键即可定位到这个配置文件,再按一次回车键即可编辑该配置文件,如图:
此时按i即可对配置文件进行编辑,如图:
rocketmq.config.namesrvAddr可以配置IP,也可以写域名,我们这里之前已经配置了hosts了,所以我们这里改为使用域名,这样写的好处就是以后如果IP地址变了,我们不需要再修改jar包的配置文件,只要修改/etc/hosts配置即可。
ESC,输入:wq保存即可。
前台启动
[root@dxm27 rocketmq-all-4.7.1-bin-release]# java -jar rocketmq-console-ng-2.0.0.jar
说明启动成功。Ctrl+C停止进程,后台启动。
编写启动脚本
[root@dxm27 target]# vim /usr/local/rocketmq-all-4.7.1-bin-release/start_console.sh
内容如下:
#!/bin/bash
nohup java -jar /usr/local/rocketmq-all-4.7.1-bin-release/rocketmq-console-ng-2.0.0.jar &
增加可执行权限:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# chmod +x start_console.sh
执行启动脚本,然后访问IP:8080
[root@dxm27 target]# sh /usr/local/rocketmq-all-4.7.1-bin-release/start_console.sh
查看进程和端口监听情况:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep java | grep console
[root@dxm27 rocketmq-all-4.7.1-bin-release]# netstat -ntlp | grep 8080
访问http://192.168.0.27:8080/
加入systemctl管理并设置开机自启动
其实随着业务的发展现在会使用更多的服务器,每台服务器也会安装更多的服务,手动人为的管理效率非常低下,如果我们加入systemctl管理,那么服务的启动、停止、状态查看等就非常方便,而且为了防止断电之后,还得挨个找服务器启动对应的服务,光找哪些服务在哪些机器上部署就够麻烦的了,这样下去非常耗时,我们设置为开机自启动之后,再怎么断电也不用怕了。
将namesrv加入systemctl管理并设置开机自启动
我们先在192.168.0.27这台服务器上执行,然后在192.168.0.24上执行相同操作即可。
创建namesrv.service服务文件
创建namesrv.service服务文件
[root@dxm27 rocketmq-all-4.7.1-bin-release]# vim /etc/systemd/system/namesrv.service
内容如下:
[Unit]
Description=rocketmq-namesrv
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
User=rocketmq
Group=rocketmq
ExecStart=sh /usr/local/rocketmq-all-4.7.1-bin-release/start_rocketmq_nameserver.sh
ExecStop=/usr/local/rocketmq-all-4.7.1-bin-release/bin/mqshutdown namesrv
PrivateTmp=true
[Install]
WantedBy=multi-user.target
重新加载服务列表
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl daemon-reload
修改属组和属主
因为我们在服务脚本里面指定了用户和组都是rocketmq,所以我们要修改/usr/local/rocketmq-all-4.7.1-bin-release这个目录下和/data/rocketmq/这个目录下所有文件的属组和属主,否则会因为没有权限导致无法执行。修改之前,如图:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# chown -R rocketmq.rocketmq /usr/local/rocketmq-all-4.7.1-bin-release/
[root@dxm27 rocketmq-all-4.7.1-bin-release]# chown -R rocketmq.rocketmq /data/rocketmq/
修改之后:
启动namesrv服务
# 停止上面手动后台启动的namesrv服务
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep java | grep NamesrvStartup
root 3279 0.1 3.1 4139528 119544 pts/0 Sl 19:11 0:13 /usr/local/jdk/bin/java -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC -verbose:gc -Xloggc:/dev/shm/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m -XX:-OmitStackTraceInFastThrow -XX:-UseLargePages -Djava.ext.dirs=/usr/local/jdk/jre/lib/ext:/usr/local/rocketmq-all-4.7.1-bin-release/bin/../lib:/usr/local/jdk/lib/ext -cp .:/usr/local/rocketmq-all-4.7.1-bin-release/bin/../conf: org.apache.rocketmq.namesrv.NamesrvStartup
[root@dxm27 rocketmq-all-4.7.1-bin-release]# kill -9 3279
# 检查是否还存在namesrv进程
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep java | grep NamesrvStartup
# 查询所有服务单元是否有namesrv
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl list-unit-files | grep namesrv
namesrv.service disabled
# 存在,且非开启自启动,使用systemctl启动namesrv服务
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl start namesrv.service
# 查看namesrv服务状态
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl status namesrv.service
Active: active (running) 可以看到namesrv服务已经启动成功。查看进程以及端口的监听情况:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep namesrv
[root@dxm27 rocketmq-all-4.7.1-bin-release]# netstat -ntlp | grep 9876
namesrv设置为开机自启动
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl list-unit-files | grep namesrv
namesrv.service disabled
# disabled表示非开机自启动
# 设置为开机自启动
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl enable namesrv.service
Created symlink /etc/systemd/system/multi-user.target.wants/namesrv.service → /etc/systemd/system/namesrv.service.
# 再次查看
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl list-unit-files | grep namesrv
namesrv.service enabled
# enabled表示是开机自启动,执行重启命令
[root@dxm27 rocketmq-all-4.7.1-bin-release]# reboot
#重启后再次查看namesrv服务已启动完成。
将broker加入systemctl管理并设置开机自启动
我们先在192.168.0.27这台服务器上执行,然后在192.168.0.24上执行相同操作即可。要注意的是两台机器的broker脚本不一样,这个在服务文件修改的时候要注意下。
创建启动broker脚本
这个脚本是用于合并服务器上那两个sh脚本的,这样一来服务文件里面只要执行这个脚本即可。
[root@dxm27 rocketmq-all-4.7.1-bin-release]# vim start_broker.sh
内容如下:
/usr/local/rocketmq-all-4.7.1-bin-release/start_broker_b_m.sh & /usr/local/rocketmq-all-4.7.1-bin-release/start_broker_a_s.sh
增加可执行权限:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# chmod +x start_broker.sh
创建broker.service服务文件
创建broker.service服务文件
[root@dxm27 rocketmq-all-4.7.1-bin-release]# vim /etc/systemd/system/broker.service
内容如下:
[Unit]
Description=rocketmq-broker
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
User=rocketmq
Group=rocketmq
ExecStart=sh /usr/local/rocketmq-all-4.7.1-bin-release/start_broker.sh
ExecStop=/usr/local/rocketmq-all-4.7.1-bin-release/bin/mqshutdown broker
PrivateTmp=true
[Install]
WantedBy=multi-user.target
重新加载服务列表
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl daemon-reload
启动broker服务
# 停止上面手动后台启动的broker服务
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep java | grep broker
root 3310 2.0 14.6 4857392 562184 pts/0 Sl 19:11 3:26 /usr/local/jdk/bin/java -server -Xms1g -Xmx1g -Xmn1g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0 -verbose:gc -Xloggc:/dev/shm/rmq_broker_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m -XX:-OmitStackTraceInFastThrow -XX:+AlwaysPreTouch -XX:MaxDirectMemorySize=15g -XX:-UseLargePages -XX:-UseBiasedLocking [Unit]
-Djava.ext.dirs=/usr/local/jdk/jre/lib/ext:/usr/local/rocketmq-all-4.7.1-bin-release/bin/../lib:/usr/local/jdk/lib/ext -cp .:/usr/local/rocketmq-all-4.7.1-bin-release/bin/../conf: org.apache.rocketmq.broker.BrokerStartup -c /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/broker-b.properties
root 3390 1.9 21.9 5901712 844260 pts/0 Sl 19:11 3:11 /usr/local/jdk/bin/java -server -Xms1g -Xmx1g -Xmn1g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0 -verbose:gc -Xloggc:/dev/shm/rmq_broker_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m -XX:-OmitStackTraceInFastThrow -XX:+AlwaysPreTouch -XX:MaxDirectMemorySize=15g -XX:-UseLargePages -XX:-UseBiasedLocking -Djava.ext.dirs=/usr/local/jdk/jre/lib/ext:/usr/local/rocketmq-all-4.7.1-bin-release/bin/../lib:/usr/local/jdk/lib/ext -cp .:/usr/local/rocketmq-all-4.7.1-bin-release/bin/../conf: org.apache.rocketmq.broker.BrokerStartup -c /usr/local/rocketmq-all-4.7.1-bin-release/conf/2m-2s-async/broker-a-s.properties
[root@dxm27 rocketmq-all-4.7.1-bin-release]# kill -9 3310
[root@dxm27 rocketmq-all-4.7.1-bin-release]# kill -9 3390
# 检查是否还存在broker进程
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep java | grep broker
# 查询所有服务单元是否有broker
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl list-unit-files | grep broker
broker.service disabled
# 存在,且非开启自启动,使用systemctl启动broker服务
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl start broker.service
# 查看broker服务状态
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl status broker.service
Active: active (running) 可以看到broker服务已经启动成功。查看进程以及端口的监听情况:
[root@dxm27 rocketmq-all-4.7.1-bin-release]# ps aux | grep java | grep broker
[root@dxm27 rocketmq-all-4.7.1-bin-release]# netstat -ntlp | grep 10911
[root@dxm27 rocketmq-all-4.7.1-bin-release]# netstat -ntlp | grep 10921
broker设置为开机自启动
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl list-unit-files | grep broker
broker.service disabled
# disabled表示非开机自启动
# 设置为开机自启动
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl enable broker.service
Created symlink /etc/systemd/system/multi-user.target.wants/broker.service → /etc/systemd/system/broker.service.
# 再次查看
[root@dxm27 rocketmq-all-4.7.1-bin-release]# systemctl list-unit-files | grep broker
broker.service enabled
# enabled表示是开机自启动,执行重启命令
[root@dxm27 rocketmq-all-4.7.1-bin-release]# reboot
#重启后再次查看broker服务已启动完成。
搭建过程中遇到的问题
内存不足
rocketmq默认情况下配置的内存都太大,不适合在开发测试环境中使用,所以我们需要根据自己服务器的配置情况适当的调低JVM。主要是修改runbroker.sh里面的参数。
报错Please set the JAVA_HOME variable in your environment, We need java(x64)!
本机明明已经安装了jdk,并且也配置了环境变量,依然提示这个错误信息。
解决方法: 运行which java来查看java的路径,比如为/usr/local/jdk/bin/java。
修改bin/runserver.sh和bin/runbroker.sh和bin/tools.sh,注释掉校验JAVA_HOME语句,并明确指定JAVA路径:
#[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java
#[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
#[ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!"
#export JAVA_HOME
export JAVA="/usr/local/jdk/bin/java"
Broker 重启对客户端的影响
Broker 重启可能会导致正在发往这台机器的的消息发送失败,RocketMQ提供了一种优雅关闭Broker的方法,通过执行以下命令会清除Broker的写权限,过40s后,所有客户端都会更新Broker路由信息,此时再关闭Broker就不会发生发送消息失败的情况,因为所有消息都发往了其他 Broker。
[root@dxm27 rocketmq-all-4.7.1-bin-release]# sh mqadmin wipeWritePerm -b brokerName -n namesrvAddr