RocketMQ 配置指南

739 阅读21分钟

一、引言

在当今分布式系统盛行的时代,RocketMQ 作为一款高性能、高可用的分布式消息中间件,犹如桥梁般连接着各个服务模块,在构建可靠、高效的系统架构中扮演着举足轻重的角色。其丰富的配置项如同精密仪器的调节旋钮,正确设置这些配置,能够让 RocketMQ 在不同的业务场景中发挥出最佳性能。本文将深入 RocketMQ 的世界,按影响的模块详细介绍其相关配置的作用与设置方式,帮助大家更好地掌握和运用这一强大工具。

二、NameServer 配置

2.1 基础配置项

NameServer 作为 RocketMQ 的服务发现与路由中心,其基础配置至关重要。

NameServer 地址:这是 Producer、Consumer 和 Broker 与 NameServer 进行通信的关键信息。在代码中,一般通过 namesrvAddr 变量来指定。例如在 Java 应用中,使用 RocketMQ 客户端时,可在配置文件或代码中设置,如 producer.setNamesrvAddr("http://192.168.1.100:9876");。若有多个 NameServer 节点,地址之间用分号分隔,如 "http://192.168.1.100:9876;http://192.168.1.101:9876"。其作用在于为各组件提供统一的注册与发现服务地址,确保消息发送、接收以及 Broker 的管理等操作能够准确找到对应的 NameServer。

监听端口:NameServer 默认监听端口为 9876,在 NettyServerConfig 类中可进行配置。通过修改 listenPort 属性值,如 NettyServerConfig.setListenPort(9877);,可以改变 NameServer 监听的端口。此端口决定了 NameServer 在网络中接收来自其他组件连接请求的端口号,合理设置能避免端口冲突,保障 NameServer 正常提供服务。

2.2 集群配置要点

在生产环境中,为提高 NameServer 的可用性和可靠性,通常会搭建 NameServer 集群。

多 NameServer 节点组成集群时,每个节点的配置需保持一致,包括上述的基础配置项。每个 Broker 在启动时,会向集群中的所有 NameServer 节点注册自身信息,并定时发送心跳包以维持连接。这要求所有 NameServer 节点的网络必须畅通,且配置的可连接性相同。

在配置客户端(Producer 和 Consumer)时,需要将所有 NameServer 节点的地址都配置进去,这样客户端在获取 Broker 路由信息时,若与某个 NameServer 节点连接失败,能自动切换到其他节点。例如在 Spring Boot 集成 RocketMQ 的配置中,可以通过如下方式配置多个 NameServer 地址:

<bean id="rocketMQClientConfig" class="org.apache.rocketmq.spring.core.RocketMQClientConfig">
    <property name="namesrvAddr" value="192.168.1.100:9876;192.168.1.101:9876"/>
</bean>

此外,由于 NameServer 集群中的节点是对等的,不存在主从关系,它们之间也不会进行数据同步,每个节点都保存了完整的路由信息。因此,在部署时要确保每个节点的硬件资源(如 CPU、内存、磁盘等)能够满足业务高峰期的负载需求,避免因单个节点性能瓶颈而影响整个集群的稳定性。

三、Broker 配置

3.1 网络相关配置

监听端口:Broker 通过监听端口接收来自 Producer、Consumer 和其他 Broker 的请求。在 broker.properties 文件中,可通过 listenPort 属性设置,默认值为 10911。例如,若要将监听端口改为 10912,可在配置文件中添加 listenPort=10912。这个端口就像是 Broker 的 “大门”,外界的通信请求都通过此端口进入。若端口被占用,Broker 将无法正常启动,所以在部署时要确保该端口未被其他程序使用。同时,在防火墙设置中,需要开放此端口,以保证外部组件能够顺利连接到 Broker。

IP 地址:当服务器存在多个网卡时,需要指定 Broker 对外服务的 IP 地址。在 broker.properties 中,使用brokerIP1来设置,如 brokerIP1=192.168.1.100。若不设置,Broker 可能会绑定到错误的 IP 地址,导致 Producer 和 Consumer 无法正确连接。特别是在云服务器环境中,内外网 IP 的设置需格外注意,要确保设置的 IP 地址是可被外部访问到的,否则消息的发送和接收将无法正常进行。

3.2 存储相关配置

存储路径:Broker 的存储路径决定了消息、索引等数据的存放位置。在 broker.properties 中, storePathRootDir 指定了根存储路径,例如 storePathRootDir=/data/rocketmq/store。同时,storePathCommitLog、storePathConsumeQueue、storePathIndex 等分别指定了 CommitLog 文件、消费队列文件和消息索引文件的存储路径。合理选择存储路径至关重要,建议选择磁盘空间充足、I/O 性能良好的磁盘分区。若磁盘空间不足,可能导致消息无法写入,进而影响整个系统的正常运行。另外,不同类型的数据分路径存储,有助于提高数据管理和维护的效率。

文件大小:CommitLog 文件和 ConsumeQueue 文件的大小可通过配置进行调整。 mapedFileSizeCommitLog 用于设置 CommitLog 每个文件的大小,默认值为 1GB,即 mapedFileSizeCommitLog=1073741824。mapedFileSizeConsumeQueue 设置 ConsumeQueue 每个文件默认存储的消息条数,默认值为 30W 条 ,可根据业务情况调整。合适的文件大小设置能平衡存储管理和性能。较小的文件大小便于文件的滚动和清理,但可能会增加文件数量,影响 I/O 性能;较大的文件大小则相反,可能会在文件清理时产生较长的停顿时间。

刷盘策略:刷盘策略决定了消息何时从内存持久化到磁盘,分为同步刷盘(SYNC_FLUSH)和异步刷盘(ASYNC_FLUSH),在 broker.properties 中通过 flushDiskType 设置,默认值为 ASYNC_FLUSH。同步刷盘在消息写入磁盘后才返回成功响应,能保证消息不丢失,但会降低写入性能;异步刷盘则是消息写入内存后就返回成功响应,由后台线程异步将内存中的数据刷盘,存在一定的消息丢失风险。在对消息可靠性要求极高的场景,如金融交易场景,应选择同步刷盘;而在对性能要求较高,且能容忍少量消息丢失的场景,如一般的日志收集场景,异步刷盘更为合适。

3.3 集群与主从配置

集群模式:RocketMQ 支持多种集群模式,如单 Master 模式、多 Master 模式、多 Master 多 Slave 模式。在 broker.properties 中,通过 brokerClusterName 指定所属集群名称,如 brokerClusterName=rocketmq-cluster。单 Master 模式适用于测试环境,存在单点故障问题;多 Master 模式配置简单,单个 Master 宕机或重启维护对应用影响较小,但单台机器宕机期间,该机器上未被消费的消息不可订阅;多 Master 多 Slave 模式又分为异步复制和同步双写两种,异步复制模式下 Master 写入消息后立即返回成功 ACK,无需等待 Slave 同步,当 Master 宕机后 Slave 能自动切换为 Master,但可能存在少量消息丢失;同步双写模式下 Master 会等待 Slave 同步数据成功后才返回成功 ACK,消息可靠性更高,但性能相对较低,且目前版本 Master 宕机后 Slave 不会自动切换到 Master 。在生产环境中,需根据业务对性能、可靠性和消息实时性的要求,选择合适的集群模式。

主从配置:在多 Master 多 Slave 模式中,通过 brokerRole 设置 Broker 角色,取值为ASYNC_MASTER(异步复制 Master)、SYNC_MASTER(同步双写 Master)、SLAVE。brokerId 用于标识 Broker,0 表示 Master,大于 0 表示 Slave 。例如,若要将一个 Broker 配置为异步复制的 Master,可在 broker.properties 中设置 brokerRole=ASYNC_MASTER 和 brokerId=0。主从配置使得在 Master 出现故障时,Slave 能够接替其工作,保证系统的可用性。同时,主从之间的数据同步方式(同步复制或异步复制)也会影响系统的性能和消息可靠性,需要根据实际业务场景进行权衡配置 。

四、Producer 配置

4.1 基本属性配置

生产者组名:生产者组名用于标识一组 Producer,在创建 DefaultMQProducer 实例时设置,如DefaultMQProducer producer = new DefaultMQProducer("myProducerGroup");。它的作用主要体现在事务消息场景中,当 Producer 发送事务消息后,若发生崩溃或重启,同一生产者组内的其他 Producer 能够继续处理未完成的事务,确保事务的最终一致性。同时,在运维管理方面,通过生产者组名可以方便地对相关 Producer 进行监控和管理。

发送超时时间:通过 producer.setSendMsgTimeout(3000);设置,单位为毫秒,默认值是 3000ms。此参数决定了 Producer 发送消息时等待 Broker 响应的最长时间。若在超时时间内未收到 Broker 的响应,Producer 会抛出异常,提示发送失败。合理设置发送超时时间,能够在网络波动时避免 Producer 长时间等待,及时处理发送失败的情况,保证系统的响应性能。例如,在网络状况较好且对消息发送实时性要求较高的场景中,可以适当缩短超时时间;而在网络环境复杂、容易出现延迟的场景中,则需要适当延长超时时间 。

NameServer 地址:这是 Producer 与 NameServer 建立连接的关键配置,通过producer.setNamesrvAddr("http://192.168.1.100:9876");http://192.168.1.101:9876");设置,支持配置多个地址,地址间用分号分隔。Producer 通过该地址向 NameServer 获取 Broker 的路由信息,从而确定消息发送的目标 Broker。在多机房部署或对可用性要求极高的场景中,配置多个不同机房的 NameServer 地址,可以有效避免因单个 NameServer 故障导致 Producer 无法获取路由信息,保障消息发送的稳定性。

4.2 消息发送策略配置

消息重试:RocketMQ 为 Producer 提供了强大的消息重试机制,以确保消息尽可能成功发送。

同步发送重试:通过 producer.setRetryTimesWhenSendFailed(3);设置同步发送失败时的重试次数,默认重试 2 次,即最多尝试发送 3 次。当发送过程中出现 RemotingException(网络通信异常)、MQClientException(客户端异常)和部分 MQBrokerException(Broker 端异常)时,Producer 会自动重试发送消息,且不会选择上次失败的 Broker,而是尝试向其他 Broker 发送,最大程度保证消息不丢失。例如在网络抖动导致消息发送失败的情况下,重试机制能够自动重新发送消息,提高消息发送的成功率。但需要注意的是,重试次数过多可能会导致消息发送延迟增加,因此要根据业务场景合理设置重试次数。

异步发送重试:使用 producer.setRetryTimesWhenSendAsyncFailed(2);设置异步发送失败时的重试次数,默认也是 2 次。与同步发送重试不同,异步重试仅在同一个 Broker 上进行重试,且不保证消息一定不丢失。这是因为异步发送本身更注重发送的效率,在某些对消息可靠性要求相对较低,但对发送性能要求较高的场景中,这种重试方式能够在一定程度上保证消息发送的成功率,同时避免过多的重试操作对性能产生过大影响。

消息刷盘失败重试:通过 producer.setRetryAnotherBrokerWhenNotStoreOK(true);开启,默认值为 false。当消息刷盘(主或备)超时或 Slave 不可用(返回状态非SEND_OK)时,若开启此配置,Producer 会尝试将消息发送到其他 Broker。在对消息可靠性要求极高的场景,如金融交易消息的发送,开启此配置能确保即使在某些 Broker 出现刷盘问题或 Slave 不可用的情况下,消息依然有机会成功发送到其他健康的 Broker,保障消息的可靠存储和传输。

消息压缩:在网络带宽有限的情况下,消息压缩能够有效减少网络传输的数据量,提高消息发送的效率。在 Producer 端,通过 producer.setCompressMsgBodyOverHowmuch(1024);启用消息体压缩功能,这里的 1024 表示当消息体大小超过 1KB 时,RocketMQ 会自动对消息体进行压缩。默认情况下,RocketMQ 使用 GZIP 算法来压缩消息体,当然,也可以通过自定义 Compressor 接口来使用其他压缩算法。例如在一个需要发送大量文本消息的日志收集系统中,开启消息压缩功能后,能够显著减少网络带宽的占用,提高日志消息的传输效率。同时,Broker 接收到压缩的消息后,不会立即解压,而是直接存储或转发给消费者,消费者在接收到被标记为已压缩的消息后,会自动对其进行解压,然后再进行消费,整个过程对业务代码透明,无需额外处理。

批量发送:批量发送消息能够减少 Producer 与 Broker 之间的连接开销,提高消息发送的性能,尤其适用于需要发送大量小消息的场景。生产者需要开启批量发送的功能,通过配置 producer.setMaxMessageSize(4 * 1024 * 1024);设置单个消息的最大大小,通常建议批量消息的总大小不超过 4MB。在发送之前,生产者可以将多个小消息合并成一个大的批量消息,这涉及到创建一个 BatchMessage 对象,并将多个普通的消息添加到这个对象中。每个消息在加入批量消息前,都需要经过序列化(例如使用 Protobuf 或 JSON)转换成字节流形式,并且批量消息会包含每个子消息的元数据,如消息大小、偏移等,以便于后续拆分。例如在电商系统中,向用户批量发送促销通知消息时,采用批量发送功能可以大大提高发送效率,减少系统开销。但需要注意的是,批量发送的消息必须有相同的 Topic,且不能是延时消息。同时,要合理控制每批消息的数量,过多的消息可能会导致内存占用过高或发送失败;过少的消息则无法充分利用批量发送的优势 。

五、Consumer 配置

5.1 消费组与模式配置

消费组设置:消费组是 RocketMQ 中消费者的逻辑分组,在创建 DefaultMQPushConsumer 实例时指定,如DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("myConsumerGroup");。消费组的名称需全局唯一,它的作用在于实现负载均衡和消息重试。同一消费组内的消费者会共同消费一组消息,通过负载均衡机制,将消息分配给组内的不同消费者实例进行处理。例如在电商订单处理系统中,多个订单处理服务实例可以组成一个消费组,共同处理订单相关的消息。当某个消费者实例出现故障时,其他实例可以继续消费未处理的消息,保证消息不丢失。同时,消费组还与消息重试相关,若消费组内某个消费者处理消息失败,RocketMQ 会根据重试策略,将消息重新发送给该消费组内的其他消费者实例进行处理。

消费模式:RocketMQ 支持集群消费和广播消费两种模式。

  • 集群消费:这是默认的消费模式,通过 consumer.setMessageModel(MessageModel.CLUSTERING);设置。在集群消费模式下,同一消费组内的多个消费者实例会分摊消费消息。例如,一个消费组中有 3 个消费者实例,Topic 中有 10 条消息,那么每个消费者实例可能会消费到部分消息(具体分配由负载均衡算法决定)。这种模式适用于需要多个消费者共同处理大量消息,提高处理效率的场景,如电商订单的批量处理、日志的集中分析等。因为在这些场景中,每个消息只需被处理一次,通过集群消费模式可以充分利用多个消费者的并行处理能力,加快消息处理速度。
  • 广播消费:使用 consumer.setMessageModel(MessageModel.BROADCASTING);开启。在广播消费模式下,每个消费者实例都会收到并处理 Topic 中的所有消息。比如,在系统通知场景中,需要将通知消息发送给所有的用户服务实例,此时采用广播消费模式,每个用户服务实例都能接收到完整的通知消息并进行相应处理,确保所有用户都能及时收到通知。

5.2 消息拉取与处理配置

拉取间隔:消费者从 Broker 拉取消息的时间间隔可通过配置进行调整。虽然在 RocketMQ 中, DefaultMQPushConsumer 是基于长轮询机制从 Broker 拉取消息,但在一些特定场景下,开发者可能希望对拉取间隔有更精确的控制。通过自定义拉取策略或者使用 DefaultMQPullConsumer 时,可以设置拉取间隔。合理设置拉取间隔能平衡系统资源消耗和消息处理及时性。若拉取间隔过短,会增加网络请求次数,消耗过多系统资源;若拉取间隔过长,可能导致消息处理延迟,影响业务的实时性。例如在对实时性要求极高的金融交易系统中,拉取间隔需要设置得较短,以确保交易消息能够及时被处理;而在一些对实时性要求不高的日志收集系统中,拉取间隔可以适当延长,减少系统资源的消耗。

线程数配置:包括最小消费线程数 consumeThreadMin 和最大消费线程数 consumeThreadMax,在 DefaultMQPushConsumer 中可通过 consumer.setConsumeThreadMin(20);和 consumer.setConsumeThreadMax(50);设置,默认值分别为 20 和 64 。这些线程用于处理从 Broker 拉取到的消息。当消息量较大时,适当增加线程数可以提高消息处理速度;但线程数过多可能会导致系统资源竞争激烈,影响系统稳定性。比如在一个订单处理系统中,在促销活动期间,订单消息量剧增,此时可以适当增加消费线程数,以加快订单处理速度,避免消息积压;而在日常业务量较小时,保持较少的线程数,以节省系统资源。

批量消费配置:通过设置 pullBatchSize 指定每次从 Broker 拉取的消息数量,如consumer.setPullBatchSize(32);,默认值为 32。设置 consumeMessageBatchMaxSize 确定每次批量消费时一次性处理的消息条数,例如 consumer.setConsumeMessageBatchMaxSize(32);,默认值也是 32 。批量消费能够减少网络请求次数,提高消费效率,尤其适用于处理大量小消息的场景。例如在物联网设备数据采集场景中,设备会产生大量的小数据消息,采用批量消费方式,可以将多个消息一次性拉取并处理,大大提高数据处理的效率。但需要注意的是,批量消费时要确保每个消息的处理逻辑相互独立,并且要处理好批量消费中可能出现的部分消息处理失败的情况 。

六、安全相关配置

6.1 ACL 权限配置

在当今复杂的网络环境下,消息系统的安全性至关重要。RocketMQ 从 4.4 版本开始引入了 ACL(Access Control List)权限控制机制,通过对用户或应用程序的访问权限进行精细管理,为消息队列的数据安全筑起了一道坚固的防线。

ACL 机制通过在 conf/plain_acl.yml 文件中配置账号、密码和权限信息,实现对不同用户访问 RocketMQ 资源的细粒度控制。比如,在一个电商系统中,可能存在订单处理、库存管理、用户通知等多个业务模块,每个模块对 RocketMQ 的访问需求各不相同。通过 ACL 机制,可以为每个模块分配独立的账号,并根据其业务需求设置相应的权限。订单处理模块可能需要对订单相关 Topic 具备读写权限,以便及时发送和接收订单消息;库存管理模块则可能只需要对库存变更 Topic 有写入权限,而对其他 Topic 没有访问权限。

具体配置步骤如下:首先,在 plain_acl.yml 文件中定义用户信息,包括 accessKey(类似用户名)、secretKey(类似密码),以及对 Topic 和 ConsumerGroup 的权限设置。例如:

accounts:
  - accessKey: rocket0001Mq
    secretKey: 1234asdf
    whiteRemoteAddress: 192.168.0.102
    admin: false
    defaultTopicPerm: DENY
    defaultGroupPerm: SUB
    topicPerms:
      - topicA: DENY
      - topicB: PUB|SUB
      - topicC: SUB
    groupPerms:
      - groupA: DENY
      - groupB: PUB|SUB
      - groupC: SUB
  - accessKey: rocketAdminMq
    secretKey: admin1234asdf
    whiteRemoteAddress: 192.168.1.*
    admin: true

上述配置定义了两个用户,一个普通用户 rocket0001Mq,对 topicA 无权限,对 topicB 有发布和订阅权限,对 topicC 仅有订阅权限;另一个管理员用户 rocketAdminMq,拥有所有资源的访问权限,且其 IP 地址限制在192.168.1.* 网段。

然后,在 broker.conf 文件中开启 ACL 开关,添加 aclEnable=true 配置项 。修改完成后,重启 Broker 使配置生效。

在客户端使用时,无论是 Producer 还是 Consumer,都需要在配置文件中添加 accessKey 和 secretKey 信息。以 Spring Boot 集成 RocketMQ 为例,在application.yml文件中配置如下:

rocketmq:
  name-server: 127.0.0.1:9876
  producer:
    group: groupB
    send-message-timeout: 6000
    access-key: rocketmq2
    secret-key: 12345678

通过这种方式,只有配置了正确accessKey和secretKey的客户端才能访问 RocketMQ,有效防止未经授权的访问,保护消息队列数据的机密性和完整性。

6.2 SSL/TLS 加密配置

在网络传输过程中,消息面临着被窃取、篡改的风险。SSL/TLS 加密技术为 RocketMQ 的消息传输提供了可靠的安全保障,确保数据在网络上传输时的机密性、完整性和身份验证。

SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)是用于保护数据在网络上传输的加密协议,TLS 是 SSL 的继任者,提供了更强的安全性。使用 SSL/TLS 加密后,数据在传输过程中被加密成密文,只有接收方使用相应的密钥才能解密并读取数据,有效防止数据被未授权的第三方窃听。同时,通过证书验证通信双方的身份,防止中间人攻击,确保数据在传输过程中未被篡改。

要在 RocketMQ 中配置 SSL/TLS 加密,首先需要准备好证书,包括 CA 证书、服务器证书和私钥。可以使用openssl工具生成自签名证书,具体步骤如下:

  1. 生成 CA 私钥和自签名证书:
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt
  1. 生成服务器私钥和证书签名请求(CSR):
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
  1. 使用 CA 证书签署服务器证书:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256

证书生成后,在 RocketMQ 的各个组件中进行配置。在 namesrv.properties 文件中添加如下配置:

tls.enable=true
tls.server.keyPath=/path/to/server.key
tls.server.certPath=/path/to/server.crt
tls.server.authClient=true
tls.server.trustCertPath=/path/to/ca.crt

在 broker.properties 文件中也进行类似的配置:

tls.enable=true
tls.server.keyPath=/path/to/server.key
tls.server.certPath=/path/to/server.crt
tls.server.authClient=true
tls.server.trustCertPath=/path/to/ca.crt

对于客户端,以 Java 客户端为例,在代码中添加 SSL/TLS 配置:

Properties properties = new Properties();
properties.setProperty("tls.enable", "true");
properties.setProperty("tls.server.certPath", "/path/to/server.crt");
properties.setProperty("tls.server.keyPath", "/path/to/server.key");
properties.setProperty("tls.server.authClient", "true");
properties.setProperty("tls.trustCertPath", "/path/to/ca.crt");

DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setProperties(properties);
producer.start();

配置完成后,启动 RocketMQ NameServer、Broker 和客户端,通过检查日志确保没有 SSL 相关的错误信息,并可以使用网络抓包工具(如 Wireshark)验证传输数据是否已加密。这样,RocketMQ 在消息传输过程中就具备了强大的安全防护能力,保障了数据的安全传输。

七、总结

RocketMQ 的配置涉及 NameServer、Broker、Producer、Consumer 以及安全等多个模块,每个模块的配置都对其性能和稳定性有着至关重要的影响。

在 NameServer 配置中,正确设置地址和监听端口,合理搭建集群,能确保服务发现与路由的稳定。Broker 配置里,网络、存储、集群与主从等方面的参数设置,需根据业务场景对性能、可靠性的要求进行权衡。Producer 的属性和发送策略配置,保障消息能准确、高效地发送到 Broker。Consumer 的消费组与模式、消息拉取与处理配置,满足不同业务对消息消费的需求。而安全相关的 ACL 权限配置和 SSL/TLS 加密配置,为 RocketMQ 的运行筑牢安全防线。

只有深入理解并合理设置这些配置项,才能让 RocketMQ 在分布式系统中发挥出最大效能,为构建稳定、高效的应用系统提供坚实的支持。