参考网址
blog.csdn.net/weixin_3800…
感谢大佬分享
生产者和消费者是消息队列的两个重要角色。
生产者向消息队列写入数据, 消费者从消息队列里读取数据。
一个topic,会对应1个或者多个消费者组。(基本上:每个消费者组就是一个应用)
每个消费者组内,都会有多个具体的消费者,它们通过集群模式或者广播模式来消费数据。
本篇讲解两种类型的消费者,一个是 DefaultMQPushConsumer,由系统控制读取操作,收到消息后自动调用传人的处理方法(及:回调函数)来处理
另一个是 DefaultMQPullConsumer,读取操作中的大部分功能由使用者自主控制 。
Clustering(集群模式)和Broadcasting(广播模式)
RocketMQ支持两种消息模式: Clustering(集群模式)和Broadcasting(广播模式)
<1>Clustering模式(集群模式)
同一个ConsumerGroup(GroupName相同)里的每个 Consumer 只消费所订阅topic的一部分内容,
同一个 ConsumerGroup 里所有的 Consumer 消费的内容加起来才是所订阅Topic的内容的整体,
从而达到负载均衡的目的。
每加入一个消费者,系统都会重新去调整负载均衡。
<2>Broadcasting模式(广播模式)
同一个ConsumerGroup里的每个Consumer都能消费到所订阅Topic中的全部消息,
也就是一个消息会被多次消费,被每个Consumer都消费。
即:消费者组中的每一个消费者,都会处理该订阅的topic中的所有的消息msg
广播,字面意思,广播发出来的声音,每一个人都能听到。
push 和 pull的理解
Push的方式是 Server端 接收到消息后,主动把消息推送给 Client端,主动权在Server端,实时性高。
用 Push方式主动推送有很多弊 端:首先是加大 Server 端的 工作量,进而影响 Server 的性能;
其次,Client 的处理能力各不相同, Client 的状态不受 Server 控制,
Pull方式是 Client端循环地从 Server端拉取消息,主动权在 Client手里,
自己拉取到一定量消息后,处理妥当了再接着取。
Pull 方式的问题是循环拉取 消息的间隔不好设定,间隔太短就处在一个 “忙等”的状态,浪费资源;
Pull 的时间间隔太长 Server 端有消息到来时 有可能没有被及时处理。
1/DefaultMQPushConsumer类型
使用 DefaultMQPushConsumer类型的消费者,主要是设置好各种参数和传人处理消息的函数(即:回调函数)。
系统收到消息后(即:生产者写入数据了)自动调用处理函数(回调函数)来处理消息,自动保存 Offset,
而且加入新的 DefaultMQPushConsumer后会自动做负载均衡。
DefaultMQPushConsumer需要设置3个参数 :
一是这个 Consumer 的 GroupName,
二是 NameServer 的地址和端 口号,
三是 Topic 的名称 ,下面将分 别进行详细介绍 。
(1) Consumer的 GroupName用于把多个 Consumer组织到一起, 提高并发处理能力, GroupName需要和消息模式 (MessageModel)配合使用。
(2)NameServer 的地址和端口号,可以填写多个,用分号隔开,达到消除单点故障的目的,
比如 “ip1:port;ip2:port;ip3 :port” 。
(3)Topic名称用来标识消息类型, 需要提前创建。如果不需要消费某 个 Topic 下的所有消息,可以通过指定消息的 Tag 进行消息过滤,比如: Consumer.subscribe (”TopicTest”,’tag1 || tag2 || tag3”), 表示这个 Consumer要 消费“ TopicTest”下带有 tag1 或 tag2 或 tag3 的消息。在填写 Tag 参数的位置,用 null 或者“ *“ 表示要消费这个 Topic 的所有消息 。
2/DefaultMQPullConsumer
处理 逻辑是逐个 读 取某 Topic 下所有 Message Queue 的内容, 读完一遍后退出, 主要处理额外的三件事情:
( 1 )获取 Message Queue 并遍历
一 个 Topic 包括多个 Message Queue(消息队列),如果这个Consumer需要获取Topic下所有的消息(阿广播模式),就 要遍历多有的 Message Queue。 如果有特殊情况,也可以选 择某些特定的 Message Queue 来读取消息 。
( 2 )维护 Offsetstore
从一个 Message Queue 里拉取消息的时候,要传人 Offset参数( long类型 的值),随着不断读取消息 , Offset会不断增长 。 这个时候由用户负责把 Offset 存储下来,根据具体情况可以存到内存里、写到磁盘或者数据库里等 。
( 3 )根据不同的消息状态做不同的处理
拉取消息的请求发出后,会返回: FOUND、 NO_MATCHED_MSG、 NO_NEW_MSG、 OFFSET_ILLEGAL 四种状态,需要根据每个状态做不同的处理 。比较重要的两个状态是 FOUNT 和 NO NEW MSG ,分别表示获取到消息和没 有新的消息 。
Consumer 的启动、关闭流程
对于 PullConsumer来说,使用者主动权很高,可以根据实际需要暂停、停止、启动消费过程 。
需要注意的是 Offset 的保存,要在程序的异常处理部分增加把 Offset 写人磁盘方 面的处理,记准了每个 Message Queue 的 Offset,才能保证消息消 费 的准确性 。
DefaultMQPushConsumer 的退出, 要调用shutdown()函数,以便释放资源、保存Offset等。这个调用要加到 Consumer 所在应用的退出逻辑中 。
启动DefaultMQPushConsumer时, NameServer地址填错,程序仍然可以正常启动,但是不会收到消息 。
解决启动时NameServer填写错误报错:
可以在 Consumer.start()语句后调用: Consumer.fetchSubscribeMessageQueues(”TopicName”),这 时如果配 置信息写得不准确,或者当 前服务不可 用,这个语句会报MQClientException异常。