一:RocketMQ主要组成
RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分构成。
可以部署成单机使用,结构图如下:
随着业务量的增加,使用集群的部署的方式进行水平扩展,且无单点障碍(NameServer是无状态的,无论是生产者,消费者都是通过NameServer进行通信的)。
NameServer: 以轻量级的方式提供服务发现和路由功能,每个NameServer存有全量的路由信息,提供对等的读写服务,支持快速扩缩容。
Broker: 负责消息存储,支持消息的拉取PULL以及推送PUSH,同时可严格保证消息的有序性。
Topic: 表示消息的第一级类型,比如帅车的项目可分成:订单消息、车辆消息......消息必须指定Topic。
Tag:表示消息的第二级类型,比如订单消息又可以分为:交易创建消息,交易完成消息..... 一条消息可以没有Tag。RocketMQ提供2级消息分类,方便大家灵活控制。
Queue:一个topic下,我们可以设置多个queue(消息队列)。当我们发送消息时,需要要指定该消息的topic。RocketMQ会轮询该topic下的所有队列,将消息发送出去。
消息订阅与消费的不同类型
Push Consumer:由服务端主动推送消息给向Consumer对象注册了Listener接口的方法。
Pull Consumer:由业务端主动使用Consumer拉取消息的方向向服务端拉取消息。
Producer Group:发送同类型消息的一个生产者的组,例如:订单消息发送者组。
Consumer Group:订阅了同一个Topic,甚至是同一个Tag的消费者组。
广播消息:一条消息被多个Consumer消费,即使这些Consumer属于同一个Consumer Group,消息也会被Consumer Group中的每个Consumer都消费一次。在广播消费中的Consumer Group概念可以认为在消息划分方面无意义。
集群消费:一个Consumer Group中的Consumer实例平均分摊消费消息。例如某个Topic有 9 条消息,其中一个Consumer Group有 3 个实例(可能是 3 个进程,或者 3 台机器),那么每个实例只消费其中的 3 条消息。
二:配置参数,部署
1:先从Apache官网下载对应文档http://rocketmq.apache.org/
2:虚拟机的准备,安装好JDK,使用java –version测试环境是否正常。
3:iptable或firewall 开放9876(NameServer使用),10911(Broker使用,仅内部使用)端口。
4:创建消息队列运行时,存放文件的目录如下:
/data/rocket/store/commitlog 队列的提交信息
/data/rocket/store/consumequeue 消息组的相关信息
/data/rocket/store/index 队列偏移量
5: 修改MQ默认的日志存放的位置
mkdir /data/rocketmq/logs
cd /data/rocketmq/conf && sed -i 's#${user.home}#/data/rocketmq#g' *.xml
6:创建目录 mkdir /data/rocket用与放置MQ的运行文件。
Rocketmq的文件目录如下图:
进入到conf目录进行broker.conf配置文件。目前使用单机环境,只需要配置该文件。
注意:线上的环境中:autoCreateTopicEnable=true必须要关闭。
7:准备好MQ的WEB管理控制台,开源的控制台。
https://github.com/apache/rocketmq-externals rocketmq-console
8:虚拟机的网络配置,见下图:
WEB控制台注意修改配置文件中的nameserver地址如上图。
三:MQ的启动。
1:启动的顺序必须为先启动NameServer ---- Broker --- Console。
关机的顺序反之(Console可以不关)
2:mkdir /data/rocket/logs ---- 用与放启动后的日志
启动NameServer
nohup /data/rocket/bin./mqnamesrv >/data/rocket/logs/mqnamesrv.log 2>&1 &
启动Broker
nohup ./mqbroker -c /data/rocket/conf /broker.conf >/dev/null 2>&1 &
注意:
启动之前一定要配置JVM参数,默认的内存参数比较大,会报JVM OUTOFMEMORY
/bin/runbroker.sh
/bin/runnamesrv.sh
启动Console:
nohup java –jar rocketmq-console-ng-1.0.0.jar &
通过以下地址可以访问http://192.168.2.143:8080 端口在项目打包的时候可以修改,记得开放端口。
以及对Producer,Consumer的信息查看及相应的操作功能。
四:JAVA-API的使用。
1:原生的java-api使用。
Maven
RocketMQ-JAVA客户端可以发送 顺序消息,广播消息,异步消息等,具体请参考官网的详细示例
(作为对rocketmq支持消息类型的了解,项目中请使用spring-boot-start-rocketmq)
http://rocketmq.apache.org/docs/simple-example/
2:使用Spring-boot-start-rocketmq
Maven
引入maven依赖包的客户端。
引入MQ的实体类RO,发送消息如需将实体类对象RO写到mq-entity包中进行统一的管理。
使用方式:
1:客户端使用sping-boot-start-rocket封装,使用注解的方式进行配置注入,支持"${}"点位符
application.properties文件中配置
#nameservice的地址---必须配置
spring.rocketmq.name-server-address=192.168.2.143:9876;
#生产者组的名称 ---- 不配置自动设置为UUID,为了区分最好是设置
spring.rocketmq.producer-group=start-first
#发送消息的超时,默认是3秒
spring.rocketmq.send-msg-timeout=3000
2:目前设计为 每一个子项目使用一个topic,可以在配置文件中配置,这样直接引用配置文件减少配错topic的情况。不同业务下的消息使用tags来区分。
每一个子项目只需要一个生产者(Message对象中设置消息的topic,tags)
@MQProducer
public class AsyncProducer extends AbstractMQProducer {
继承AbstractMQProducer父类,可以进入看下里边有各种类型消息的发送方法。
3:消费者使用
通过@MQConsumer注解,指定消费组,topic,tag,消费模式(集群,顺序)。
需要重写process()方法,进行真实业务的处理(如下图:)
3:消息的实体类示例 (注意:实体RO必须写在mq-entity包中,统一管理)
public class Order implements Serializable {
private static final long serialVersionUID = 2253396327802486362L;
/*订单号*/
private String OrderId;
/*订单人*/
private String orderName;
/*订单金额*/
private String orderCount;
4:发送的示例
使用MessageBuilder工具类可以快递的创建Message对象。
Message对象重要成员属性包括
topic:消息主题
tags:消息主题的二级标识
body:消息主体,对应mq-entity中的实体类实例
五:Java-api在使用过程中的注意事项。
Producer
1:在同一个(子)项目中最好使用一个topic,消息的子类型使用tags来做区分。只有在生产者区分了tags,消费者才能通过tags从broker订阅过滤消息。
2:消息实体最好设置一个唯一的key,作用一:可以方便查询漏消费的消息,重复消费的消息。作用二:对于要求局部有序的消息,可以通过key进行hash取值确保顺序性。
3:对于消息不可丢失应用:发送或者消费失败的消息打印详细的日志。甚至对消费失败的消息存入mysql。
4:对于不关注消息是否发送成功的应用,可以使用sendOneWay的方式发送消息,提高吞吐量。
Consumer:
1:消费过程做到去重(不能完全保证没有重复消息,尤其是重新发送机制+网络原因)
2:不可丢失的消息的应用必须做到谨慎处理。