参考资料:
官网
《RocketMQ实战与原理解析》杨开元著
RocketMQ发展历史
RocketMq是一个由阿里巴巴开源的消息中间件, 2012年开源,2017年成为apache顶级项目。
它的核心设计借鉴了Kafka,所以我们在了解RocketMQ的时候,会发现很多和kafka相同的特性。同时呢,Rocket在某些功能上和kafka又有较大的差异,接下来我们就去了解RocketMQ
- (1)支持集群模式、负载均衡、水平扩展
- (2)亿级别消息对接能力
- (3)采用零拷贝的原理,顺序写盘,随机读
- (4)底层通信框架采用Netty NIO
- (5)NameServer代替Zookeeper,实现服务寻址和服务协调
- (6)消息失败重试机制、消息可查询
- (7)强调集群无单点、可扩展,任意一个点高可用,水平可扩展
- (8)经过多次双十一的考验(万亿级消息)
- (9)支持事务性消息
RocketMQ 于长轮询的拉取方式
RocketMQ 是使用 Java 语言开发的,更容易找到技术人员进行定制开发
为什么选择RocketMQ
RocketMQ架构
和kafka架构类似,其中zookeeper替换成NameServier
在rocketmq的早版本(2.x)的时候,是没有namesrv组件的,用的是zookeeper做分布式协调和服务发现,但是后期阿里数据根据实际业务需求进行改进和优化,自组研发了轻量级的namesrv,用于注册Client服务与Broker的请求路由工作,namesrv上不做任何消息的位置存储,
频繁操作zookeeper的位置存储数据会影响整体集群性能
RocketMQ由四部分组成官网文档
- NameServer 可集群部署
节点之间无任何信息同步。提供轻量级的服务发现和路由
- Broker(消息中转角色,负责存储消息,转发消息) 部署相对复杂
Broker 分为Master 与Slave,一个Master 可以对应多个Slave,但是一个Slave 只能对应一个Master,Master 与Slave 的对应关系通过指定相同BrokerName,不同的BrokerId来定 义,BrokerId为0 表示Master,非0 表示Slave。Master 也可以部署多个。
- Producer,生产者
拥有相同 Producer Group 的 Producer 组成一个集群, 与Name Server 集群中的其中一个节点(随机选择)建立长连接,定期从Name Server 取Topic 路由信息,并向提供Topic服务的Master 建立长连接,且定时向Master 发送心跳。Producer 完全无状态,可集群部署。
- Consumer,消费者
接收消息进行消费的实例,拥有相同 Consumer Group 的 Consumer 组成
一个集群,与Name Server 集群中的其中一个节点(随机选择)建立长连接,定期从Name Server 取 Topic 路由信息,并向提供Topic 服务的Master、Slave 建立长连接,且定时向Master、Slave 发送心跳。Consumer既可以从Master 订阅消息,也可以从Slave 订阅消息,订阅规则由Broker 配置决定。
要使用rocketmq,至少需要启动两个进程,nameserver、broker,前者是各种topic注册中心,后者
是真正的broker
RocketMQ的安装
单机环境
启动nameserver
> unzip rocketmq-all-4.6.0-source-release.zip
> cd rocketmq-all-4.6.0/
> cd distribution/target/apache-rocketmq
> nohup sh bin/mqnamesrv &
> tail -f ~/logs/rocketmqlogs/namesrv.log
The Name Server boot success...
# namesever默认端口是9876
启动broker
# [-c可以指定broker.conf配置文件]。默认情况下会加载conf/broker.conf
# -n 表示指定当前broker对应的命名服务地址:默认情况下broker监听的是10911端口
> nohup sh bin/mqbroker -n localhost:9876 &
# 如果提示找不到文件,则打开当前目录下的nohup.out日志文件查看
> tail -f ~/logs/rocketmqlogs/broker.log
The broker[%s, 172.30.30.233:10911] boot success...
内存不足问题
这是因为bin 目录下启动 nameserv 与 broker 的 runbroker.sh 和 runserver.sh 文件中默认分配的内存太大,rocketmq比较耗内存,所以默认分配的内存比较大,而系统实际内存却太小导致启动失败,通常像虚拟机上安装的 CentOS 服务器内存可能是没有高的,只能调小。实际中应该根据服务器内存情况,配置一个合适的值
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 8589934592 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /data/program/rocketmq-all-4.5.0-bin-release/bin/hs_err_pid6465.log
解决办法
修改runbroker.sh和runbroker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g -Xmn512g"
Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。
Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值, 就会抛出OutOfMemory异常。
xmn 年轻代的heap大小,一般设置为Xmx的3、4分之一
Topic问题
No route info of this topic 异常
rocketMQ的broker默认配置 autoCreateTopicEnable=false
解决:
- 在
broker.conf
配置中添加autoCreateTopicEnable=true
- 在rocketmq的
Dashboard
预先配置topic
生成生不建议开启
autoCreateTopicEnable=true
Broker的注册IP问题
由于centos中以后多个ip地址,broker选择一个ip将其注册到namesrv上,其中选择的ip有可能连不通
在配置中添加brokerIP1=192.168.0.111
查看启动日志看下是否是你需要注册的ip
发送&接收消息
> export NAMESRV_ADDR=localhost:9876
> sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
SendResult [sendStatus=SEND_OK, msgId= ...
> sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
ConsumeMessageThread_