RocketMQ 笔记-转
Astrotrain概述
Astrotrain是基于阿里巴巴开源项目RocketMQ进行封装的分布式消息中间件系统,提供集群环境下的消息生产和消费功能。
RocketMQ介绍
RocketMQ的物理部署结构

Name Server 是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。所有的主题和broker节点信息都由Name Server进行维护。
Broker 是主要的功能单元,处理主题的存储和消费逻辑,Broker会定时同步所有信息至Name Server。
- 一类Producer的集合名称,这类Producer通常发送一类消息,且发送逻辑一致。
- 一类Consumer的集合名称,这类Consumer通常消费一类消息,且消费逻辑一致。Consumer群组内多应用之间消息消费是竞争关系,Consumer群组之间是共享消费,这点非常重要。
RocketMQ存储特点

- Broker上绑定具体的Topic。
- Topic下有多个物理存储队列(Queue),所有存储队列都会存储消息,一个消息只会存储一份。Topic可以分布在不同Broker上。
- 存储队列的选择决定了消费的特性,如果只读写一个队列,那么消费就是顺序的了,否则会是无序的。
消费者Push和Pull的区别
Push模式下的消息是由事件触发,有消息到达时监听器会被调用(MessageListener)。
Pull模式下的消息可以由事件触发,也可以应用主动去拉取消息,没有消息可拉取时返回空。
RocketMQ设计文档
Astrotrain介绍
Astrotrain-Client是对RocketMQ的Producer和Consumer的封装,集中解决了RocketMQ诸多配置信息和使用特性,针对特定需求可以进行二次开发来进行扩展。
Astrotrain的整体结构

Basic Component是Astrotrain对RocketMQ的基础封装,里面包含的生产者和消费者处理消息的逻辑,同时处理了RocketMQ的很多配置信息。
JDBC Message Component是消息事务的功能模块,依赖Basic Component的功能实现。
Astrotrain底层依赖RocketMQ提供消息服务。
业务层只面对Astrotrain暴露的服务。
Astrotrain的逻辑结构

ATClient定义最基础的功能,包括客户端的启动、初始化、关闭的定义。
Pipe是生产者和消费者公共部分的抽象,与具体的Topic进行绑定。
- ATProducer是对生产者的封装,提供基础的消息发送服务。
ATConsumer是对消费者的封装,提供基础的消息消费服务(没有具体的Pipe实现,因为消费是针对Listener的)。
- ATMessage是对外提供的消息体,目前只提供StringMessage,ObjectMessage,后续再进行扩展。
Astrotrain使用示例
对于Astrotrain的使用主要是基于astrotrain-client来实现,目前有两个版本可供使用,1.0和1.0.1,他们之间的区别在于后者提供了一个批量消费的接口,其余的相同,所以以1.0.1的版本为例说。
注意:下面列出的所有配置文件astrotrain-client会默认从ClassPath中进行读取,不需要显式指定。
版本信息
- astrotrain-client-1.0.2版本,2015/02/05
1、开放了tag注册,消费端新增 subscribe(topic,tags,listener) 方法
2、去除了对配置文件的依赖(astrotrain-produce/astrotrain-consumer/astrotrain),使用Spring注入风格注入属性,生产者对应DefaultATProducer,消费者对应DefaultATPushConsumer这两个实体
3、增加BytesMessage支持字节数据消息
4、在消费端可以正常获取发送端设置的key和tag熟悉,通过ATMessage.getProperty() 方法,键值与发送端相同
Maven依赖
<dependency> <groupId>com.zj</groupId> <artifactId>astrotrain-client</artifactId> <version>1.0.1</version></dependency> |
生产端(Producer)
准备资源配置文件astrotrain-producer.properties,生产者配置
astrotrain-producer.properties#生产者群组名称astrotrain.group.name=PleaseRename#应用实例名称astrotrain.instance.name=ProducerAT#namesrv地址,多个之间以分号 ; 分隔astrotrain.namesrv.address=10.10.110.51:9876准备资源文件astrotrain.properties,应用配置
astrotrain.properties#应用标志符astrotrain.appId=app1Java代码,准备POJO。
Order.java12345678910111213141516171819202122232425262728293031323334353637383940414243444546packagecom.zj.astrotrain.demo;importjava.io.Serializable;importjava.util.List;publicclassOrderimplementsSerializable {/****/privatestaticfinallongserialVersionUID = 1L;privatelongid;privateString orderId;privateString cardNo;privateList<String> payments;publiclonggetId() {returnid;}publicvoidsetId(longid) {this.id = id;}publicString getOrderId() {returnorderId;}publicvoidsetOrderId(String orderId) {this.orderId = orderId;}publicString getCardNo() {returncardNo;}publicvoidsetCardNo(String cardNo) {this.cardNo = cardNo;}publicList<String> getPayments() {returnpayments;}publicvoidsetPayments(List<String> payments) {this.payments = payments;}publicString toString(){return"Order [id="+this.id +",orderId="+this.orderId +",cardNo="+this.cardNo+",payments="+this.payments ==null?null:this.payments.size() +"]";}}生产者代码
ProduerDemon.java123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105packagecom.zj.astrotrain.demo;importjava.text.DateFormat;importjava.text.SimpleDateFormat;importjava.util.ArrayList;importjava.util.Date;importjava.util.List;importcom.alibaba.fastjson.JSON;importcom.zj.astrotrain.client.ATMessage;importcom.zj.astrotrain.client.ATProducer;importcom.zj.astrotrain.client.exceptions.ATException;importcom.zj.astrotrain.client.message.ObjectMessage;importcom.zj.astrotrain.client.message.StringMessage;importcom.zj.astrotrain.client.producer.DefaultATProducer;/*** 生成者示例* <pre>需要在 ClassPath 路径下准备 astrotrain-producer.properties 具体配置信息参考 src/main/resources下的配置</pre>***/publicclassProducerDemon {privateDefaultATProducer atProducer;publicProducerDemon() {}publicvoidsetUp() {this.atProducer =newDefaultATProducer();try{this.atProducer.start();}catch(Exception e) {e.printStackTrace();}}/*** 发送字符类型的消息*/publicvoiddoStringMessage() {//获取一个生成者通道,指定TopicATProducer producer =this.atProducer.createProducer("demo");DateFormat format =newSimpleDateFormat("yyyyMMddHHmmss");for(inti =0; i <100; i++){Order order =newOrder();order.setId(i);order.setOrderId(format.format(newDate()) +"_"+ i);order.setCardNo("6221202000111112222");//新建一个StringMessageStringMessage msg =newStringMessage(JSON.toJSONString(order));//为消息设置一个业务标识符,最好是唯一的,方便在调试程序时进行跟踪,可选属性.msg.setProperty(ATMessage.MSG_KEYS, order.getOrderId());try{//进行消息发送,不抛异常的都是正常发送.除非服务端程序Crash,不然不会丢失消息producer.send(msg);}catch(ATException e) {e.printStackTrace();}}}/*** 发送对象类型的消息*/publicvoiddoObjectMessage() {//使用新的主题创建生产者通道ATProducer producer =this.atProducer.createProducer("demo");DateFormat format =newSimpleDateFormat("yyyyMMddHHmmss");for(inti =0; i<100; i++) {//新建一个ObjectMessageObjectMessage msg =newObjectMessage();Order order =newOrder();order.setId(i);order.setOrderId(format.format(newDate()) +"_"+ i);order.setCardNo("6221202000111112222"+ i);List<String> payments =newArrayList<String>();payments.add("payment"+ i);order.setPayments(payments);//设置对象msg.putObject(order);//为消息设置一个业务标识符,最好是唯一的,方便在调试程序时进行跟踪,可选属性.msg.setProperty(ATMessage.MSG_KEYS, order.getOrderId());try{//进行消息发送,不抛异常的都是正常发送.除非服务端程序Crash,不然不会丢失消息producer.send(msg);}catch(ATException e) {e.printStackTrace();}}}publicvoidshutdown() {if(this.atProducer !=null){this.atProducer.shutdown();}}publicstaticvoidmain(String[] args) {ProducerDemon demon =newProducerDemon();demon.setUp();demon.doStringMessage();demon.doObjectMessage();demon.shutdown();}}
消费端(Consumer)
准备资源文件astrotrain-consumer.properties,消费者配置。
astrotrain-consumer.properties#消费者群组名称,与生产者群组没有关联astrotrain.group.name=PleaseRename#消费者示例名称astrotrain.instance.name=ConsumerATbatch#namesrv的地址,多个以分号 ; 分隔astrotrain.namesrv.address=10.10.110.51:9876#消费模式,CLUSTERING and BROADCASTING,defaultis CLUSTERINGastrotrain.consumer.messageModel=CLUSTERING#消费者启动时从那个位置开始消费astrotrain.consumer.consumeFromWhere=CONSUME_FROM_FIRST_OFFSET#消费者线程最小数astrotrain.consumer.consumeThreadMin=10#消费者线程最大数astrotrain.consumer.consumeThreadMax=20#单次消费时一次性消费多少条消息,批量消费接口才有用,可选配置。#astrotrain.consumer.batchMaxSize=30#消费者去broker拉取消息时,一次拉取多少条。可选配置。#astrotrain.consumer.pullBatchSize=100#每次拉取消息的间隔,默认为0,可选配置/#astrotrain.consumer.pullInterval=1000准备资源文件astrotrain.properties,应用配置
astrotrain.properties#应用标志符astrotrain.appId=app2消费者,单个消息消费
ConsumerDemon.java1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374packagecom.zj.astrotrain.demo;importcom.alibaba.fastjson.JSON;importcom.alibaba.rocketmq.client.exception.MQClientException;importcom.zj.astrotrain.client.ATMessage;importcom.zj.astrotrain.client.MessageListener;importcom.zj.astrotrain.client.consumer.DefaultATPushConsumer;importcom.zj.astrotrain.client.message.ObjectMessage;importcom.zj.astrotrain.client.message.StringMessage;/*** 单个消息消费***/publicclassConsumerDemon {privateDefaultATPushConsumer atPushConsumer;publicConsumerDemon() {}publicvoidsetUp() {this.atPushConsumer =newDefaultATPushConsumer();try{//订阅必须在start之前this.atPushConsumer.subscribe("demo",newDemonMessageListener());}catch(MQClientException e) {e.printStackTrace();}}publicvoidstart() {if(this.atPushConsumer !=null) {try{this.atPushConsumer.start();System.in.read();//按任意键退出}catch(Exception e) {e.printStackTrace();}}}publicvoidshutdown() {if(this.atPushConsumer !=null){this.atPushConsumer.shutdown();}}publicstaticvoidmain(String[] args) {ConsumerDemon demon =newConsumerDemon();demon.setUp();demon.start();demon.shutdown();}//单个消息监听接口publicclassDemonMessageListenerimplementsMessageListener {@OverridepublicvoidonMessage(ATMessage message) {try{if(messageinstanceofStringMessage){StringMessage msg = (StringMessage) message;Order order = JSON.parseObject(msg.getMsg(), Order.class);System.out.println(order.getCardNo());}elseif(messageinstanceofObjectMessage) {ObjectMessage msg = (ObjectMessage) message;Order order = (Order) msg.getObject();System.out.println(order.getCardNo());}}catch(Exception e) {e.printStackTrace();}}}}消费者批量消费
ConsumerBatchDemon123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384packagecom.zj.astrotrain.demo;importjava.util.List;importcom.alibaba.fastjson.JSON;importcom.alibaba.rocketmq.client.exception.MQClientException;importcom.zj.astrotrain.client.ATMessage;importcom.zj.astrotrain.client.ConcurrentlyMessageListener;importcom.zj.astrotrain.client.consumer.DefaultATPushConsumer;importcom.zj.astrotrain.client.message.ObjectMessage;importcom.zj.astrotrain.client.message.StringMessage;/*** 消费者批量消费示例* <pre>需要在 ClassPath 路径下准备 astrotrain-consumer.properties 具体配置信息参考 src/main/resources下的配置</pre>***/publicclassConsumerBatchDemon {privateDefaultATPushConsumer atPushConsumer;publicConsumerBatchDemon() {}publicvoidsetUp() {this.atPushConsumer =newDefaultATPushConsumer();try{//订阅必须在start之前this.atPushConsumer.subscribe("demo",newDemonConcurrentlyMessageListener());}catch(MQClientException e) {e.printStackTrace();}}publicvoidstart() {if(this.atPushConsumer !=null) {try{this.atPushConsumer.start();System.in.read();//按任意键退出}catch(Exception e) {e.printStackTrace();}}}publicvoidshutdown() {if(this.atPushConsumer !=null){this.atPushConsumer.shutdown();}}publicstaticvoidmain(String[] args) {ConsumerBatchDemon demon =newConsumerBatchDemon();demon.setUp();demon.start();demon.shutdown();}/*** 消息监听***/publicclassDemonConcurrentlyMessageListenerimplementsConcurrentlyMessageListener{@OverridepublicvoidonMessage(List<ATMessage> msgs) {for(ATMessage message : msgs) {try{if(messageinstanceofStringMessage){StringMessage msg = (StringMessage) message;Order order = JSON.parseObject(msg.getMsg(), Order.class);System.out.println(order.getCardNo());}elseif(messageinstanceofObjectMessage) {ObjectMessage msg = (ObjectMessage) message;Order order = (Order) msg.getObject();System.out.println(order.getCardNo());}}catch(Exception e) {e.printStackTrace();}}}}}
注意事项
- 订阅时不要加上tag,以*注册所有tag,然后再做筛选,订阅时附上tag会导致先注册的相同topic不能正常消费
- 在开发环境里Topic和SubGroup都是自动创建的,生产上是需要手动创建的,所以上线之前一定要检查对应的主题和订阅组是否已创建
RocketMQ 笔记-转的更多相关文章
- [分布式学习]消息队列之rocketmq笔记
文档地址 RocketMQ架构 哔哩哔哩上的视频 mq有很多,近期买了<分布式消息中间件实践>这本书,学习关于mq的相关知识.mq大致有有4个功能: 异步处理.比如业务端需要给用户发送邮件 ...
- RocketMQ 笔记
Queue Topic和Queue是1对多的关系,一个Topic下可以包含多个Queue,主要用于负载均衡.发送消息时,用户只指定Topic,Producer会根据Topic的路由信息选择具体发到哪个 ...
- ROCKETMQ源码分析笔记1:tools
rocketmq源码解析笔记 大家好,先安利一下自己,本人男,35岁,已婚.目前就职于小资生活(北京),职位是开发总监. 姓名DaneBrown 好了.我保证本文绝不会太监!转载时请附上以上安利信息. ...
- RocketMQ 简单梳理 及 集群部署笔记【转】
一.RocketMQ 基础知识介绍Apache RocketMQ是阿里开源的一款高性能.高吞吐量.队列模型的消息中间件的分布式消息中间件. 上图是一个典型的消息中间件收发消息的模型,RocketMQ也 ...
- RocketMQ学习笔记(16)----RocketMQ搭建双主双从(异步复制)集群
1. 修改RocketMQ默认启动端口 由于只有两台机器,部署双主双从需要四个节点,所以只能修改rocketmq的默认启动端口,从官网下载rocketmq的source文件,解压后使用idea打开,全 ...
- RocketMQ学习笔记(15)----RocketMQ的消息模式
在前面学习ActiveMQ时,看到ActiveMQ可以是队列消息模式,也可以是订阅发布模式. 同样,在RocketMQ中,也存在两种消息模式,即是集群消费模式和广播消费模式. 1. 集群消费模式 跟A ...
- RocketMQ学习笔记(13)----RocketMQ的Consumer消息重试
1. 概念 Producer端重试: 生产者端的消息失败,也就是Producer往MQ上发消息没有发送成功,比如网络抖动导致生产者发送消息到MQ失败. 这种消息失败重试我们可以手动设置发送失败重试的次 ...
- RocketMQ学习笔记(14)----RocketMQ的去重策略
1. Exactly Only Once (1). 发送消息阶段,不允许发送重复的消息 (2). 消费消息阶段,不允许消费重复的消息. 只有以上两个条件都满足情况下,才能认为消息是“Exactly O ...
- RocketMQ学习笔记(4)----RocketMQ搭建双Master集群
前面已经学习了RockeMQ的四种集群方式,接下来就来搭建一个双Master(2m)的集群环境. 1. 双Master服务器环境 序号 ip 用户名 密码 角色 模式 (1) 47.105.145.1 ...
随机推荐
- 2017 Wuhan University Programming Contest (Online Round) C. Divide by Six 分析+模拟
/** 题目:C. Divide by Six 链接:https://oj.ejq.me/problem/24 题意:给定一个数,这个数位数达到1e5,可能存在前导0.问为了使这个数是6的倍数,且没有 ...
- Linux vi 文件编辑
1.通过vi filename 进入编辑状态 2.退出 vi 编辑器 退出命令 说明 q 如果文件未被修改,会直接退回到Shell:否则提示保存文件. q! 强行退出,不保存修改内容. wq w 命令 ...
- VBA 字符串操作
Trim(string) 去掉string左右两端空白 Ltrim(string) 去掉string左端空白 Rtrim(string) 去掉string右端空白 Len(string) 计算stri ...
- day13迭代器与生成器
三个作业: # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码 login_dic = {'alex':False} def ...
- 庖丁解牛:USB 驱动开发技术彻底解密
我们知道如果开发工程师不懂RS232 肯定会让人笑话可以想象面向未来USB 接口无处不在因此掌握USB 的原理固件编程及其驱动开发技术势必成为当务之急USB 即插即用的优点和灵活性运用于各种电子产品现 ...
- 【转】10 个MySQL数据库备份教程推荐
10 个MySQL数据库备份教程推荐 MySQL是动态网站开发中最著名的开源数据库系统.如果你在网站中使用了MySQL,那么你应该定期备份你的数据以防止它丢失. 本文将介绍自动或手动备份MySQL数据 ...
- mysql小知识点汇总
附录:(更新于2013-11-21) sql必知必会学习笔记:http://www.cnblogs.com/IPrograming/category/509859.html mysql 基本命令学习: ...
- mysql导出csv文件
SELECT * FROM (select 'id','url','大分类','分类','贴吧名称','关注用户数','帖子数量','简介','帖子名称','楼主ID','发表时间','采集时间',' ...
- angularjs 复选框 单选框
关于复选框,在做项目的时候,有一下几点心得 单选框 1.判断哪个单选框选中的情况 html代码 判断该复选框是否选中 $scope.agree.isChecked 判断这个值,如果等于1,代表 ...
- javascript基础(整理自廖雪峰)
不要使用==比较,始终坚持使用===比较false == 0; //返回true. 这种情况, 它会自动转换数据类型再比较false === 0; //返回false. 建议用这种方式 NaN === ...