pull类型消息中间件-消息消费者(二)
消费者的实例化
关于consumer的默认实现,metaq有两种:
- DefaultMQPullConsumer:由业务方主动拉取消息
- DefaultMQPushConsumer:通过业务方注册回调方法,由metaq主动推送消息
共同点:
都是消费者,也都提供了start,shutdown方法(吐个槽,这种公用的接口应该MQConsumer接口中,而不是MQPullConsumer与MQPushConsumer各搞一个)
不同点:
具体消费模式不同,PullConsumer提供了各种获取消息的方法,MQPushConsumer提供了各种订阅注册的方法来回调处理
同一类型的消费者通过consumerGroup来区分。
类结构:
Consumer 消息消费者,负责消费消息,一般是后台系统负责异步消费。一般一个应用创建一个Consumer,由应用来维护此对象,可以设置为全局对象或者单例。
consumer的start()方法主要完成以下几件事:
- checkConfig();检查consumer的groupName、Listener等是否设置。consumer的配置需在start()方法前完成。
- copySubscription();复制consumer所有的订阅。
- registerConsumer().注册consumer
- sendHeartbeatToAllBrokerWithLock()。给broker发送心跳
- rebalanceImmediately()订阅消息负载均衡。
底层还是调动netty中com.alibaba.rocketmq.remoting.netty.NettyRemotingClient#invokeAsync
或者com.alibaba.rocketmq.remoting.netty.NettyRemotingClient#invokeSync
无论是consumer还是producer中的send还是pull方法本质上都是调用netty中的invokeSync/invokeAsync进行通信。区别只是在于InvokeCallback回调对象的实现。
消费架构
consumer多余partition
partition多余consumer
消费者可靠性保证
消费者是一条接着一条地消费消息,只有在成功消费一条消息后才会接着消费下一条。如果在消费某条消息失败(如异常),则会尝试重试消费这条消 息(默认最大5次),超过最大次数后仍然无法消费,则将消息存储在消费者的本地磁盘,由后台线程继续做重试。而主线程继续往后走,消费后续的消息。因此, 只有在MessageListener确认成功消费一条消息后,meta的消费者才会继续消费另一条消息。由此来保证消息的可靠消费。消费者的另一个可靠性的关键点是offset的存储,也就是拉取数据的偏移量。默认存储在zoopkeeper上,zookeeper通过集群来保证数据的安全性。Offset会定期保存,并且在每次重新负载均衡前都会强制保存一次,因此可能会存在极端情况下的消息的重复消费。
消息过滤
消息过滤主要使用Message 的Tag字段做的。
- 在服务端,每一条消息对应的Tag被转换成一个8byte的hashcode, 在Broker 端对比Queue中每一个存储单元的的hashcode和 订阅的Tag的hashcode进行对比,不符合,则跳过,继续比对下一个,符合则传输给Consumer。在队列中进行hashcode对比
- Consumer 收到过滤后的消息后,再次将传递过来的Message中的Tag字符串和订阅的Tag字符串进行对比,不是hashcode。这样做可以避免Hash冲突
消息重复性
订阅消息阶段,由于涉及集群订阅,多个订阅方需要使用负载均衡方式订阅,在因负载均衡出现的短暂不一致的情况下可能会重复。
订阅者意外宕机,消费进度未及时存储也会产生息重复。
解决方法:
- Consumer收到消息后,通过Tair,DB去重。
- 使用Pull的方式拉取消息,但是Pull的时候,怎么协调分配队列需要应用控制。
消费时序

- RebalanceService根据NameServer提供的路由信息,执行负载均衡策略。每个consumer都会被尽量平均的分配相应的队列。
- 每一个consumer,RebalanceService都会针对每一个队列派发初始的pullRequest到PullMessageService维护的pullRequest阻塞队列里。
- pullMessageService每次都从pullRequestList里take一个拉消息的请求,并建立与broker的连接,每次默认从Broker获取32条消息。
- 每次pull消息成功后,会异步的调用callback回调函数,callback函数需要做的就是:第一,重新实例化一个新的的pullRequest,将其offset设置为之前已经消费的32条消息之后的offset值,将这个pullRequest重新put到pullRequest队列里。这样就形成了针对一个队列消费的闭环。第二,将之前已经能够获取到的32条消息及其他信息封装成一ConsumeRequest,并submit到ConsumeMessageService维护的ConsumeRequestQueue里。
- ConsumeMessageService 监听到ConsumeRequestQueue里有新的请求时,将会每次起一个线程执行ConsumeRequest里的run函数,这个函数主要是针对每一个消息调用之前Consumer注册的MessageListener函数。
- 顺序消费服务ConsumeMessageConcurrentlyService构建的时候,构建线程池来接收消费请求ConsumeRequest,同时构建一个单线程的本地线程,定时重新消费ConsumeRequest, 用来执行定时周期性锁队列任务
- 周期性锁队列lockMQPeriodically,获取正在消费队列列表ProcessQueueTable所有MesssageQueue,构建根据broker归类成MessageQueue集合Map>;遍历Map>的brokername, 获取broker的master机器地址,将brokerName的Set发送到broker请求锁定这些队列。在broker端锁定队列,其实就是在broker的queue中标记一下消费端,表示这个queue被某个client锁定。 Broker会返回成功锁定队列的集合,根据成功锁定的MessageQueue,设置对应的正在处理队列ProccessQueue的locked属性为true没有锁定设置为false
pull类型消息中间件-消息消费者(二)的更多相关文章
- pull类型消息中间件-消息发布者(一)
消息集群架构 对于发送方来说的关键几要素 topic 消息的主题,由用户定义.类似于知乎的话题,Producer发送消息的时候需要指定发送到某一个topic下面,Consumer从某一个topic下面 ...
- pull类型消息中间件-消息服务端(三)
部署架构 消息存储 存储结构 MetaQ的存储结构是一种物理队列+逻辑队列的结构.如下图所示: Producer生产消息,根据消息的topic选择topic对应某一个分区,然后发送到这个分区对应的Br ...
- push类型消息中间件-消息发布者(二)
1.消息发布者声明 我们以spring的方式来声明一个消息发布者: <bean id="operateLogsMessageManager" class="com. ...
- push类型消息中间件-消息订阅者(一)
1.订阅者的声明方式 我们以spring组件化的方式,声明一个消息订阅者,对于消息订阅者关心的主要有: topic: 一级消息类型(又名消息主题).如TRADE 消息类型:二级消息类型,区别同一Top ...
- push类型消息中间件-消息服务端(三)
1.连接管理 网络架构原来是使用是自己开发的网络框架Gecko,Gecko默认为每个网络连接分配64KB的内存,支持1000个网络连接,就需要大概64MB的内存.后来采用Netty重构了网络服务层. ...
- 消息中间件——RabbitMQ(二)各大主流消息中间件综合对比介绍!
前言 消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.当今市面上有很多主流的消息中间件,如老牌的Act ...
- 译MassTransit 创建消息消费者
创建消息消费者一个消息消费者是一个 可以消费一个或多个消息类型的类,指定IConsumer<T>接口,T为消息类型 public class UpdateCustomerConsumer ...
- SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介、创建消息生产者、创建消息消费者、自定义消息通道、分组与持久化、设置 RoutingKey)
1.概念:SpringCloudStream 2.具体内容 2.1.SpringCloudStream 简介 SpringCloudStream 就是使用了基于消息系统的微服务处理架构.对于消息系统而 ...
- spring参数类型异常输出(二), SpringMvc参数类型转换错误输出(二)
spring参数类型异常输出(二), SpringMvc参数类型转换错误输出(二) >>>>>>>>>>>>>>&g ...
随机推荐
- windows下安装Django
因为Django本身是由Python编写,所以先要安装Python.下载地址(可以根据读者当前版本自行下载):http://www.python.org/download/releases/3.3.4 ...
- html标签详解,html标签属性大全(完美版),包括css属性详解
这个是平时放在笔记里,需要什么了,查下当字典用,想不起来了就查下,个人在用有道云,查询框一输就找到了.下篇会把我整理手机的html5发了.引用在某处常看到的话.楼主耗时费心整理··请拿走······· ...
- Python版C语言词法分析器
#!/usr/bin/python # -*- coding: utf-8 -*- import sys from Tkinter import * from tkFont import * from ...
- 【转】PYTHON open/文件操作
[注]虽是转载,但会在原文上有些修改! open/文件操作f=open('/tmp/hello','w')#open(路径+文件名,读写模式)#读写模式:r只读,r+读写,w新建(会覆盖原有文件),a ...
- Mocha的单元测试实战
Mocha Mocha是一个测试框架,为JS应用添加测试.使用见:mochajs. Mocha结合Nodejs实战 ontstair.js 这里我们使用自定义模块:ontstair.js,代码如下. ...
- 【CSS学习笔记】CSS选择器
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...
- OO的五大原则:SRP、OCP、LSP、DIP、ISP
OO的五大原则是指SRP.OCP.LSP.DIP.ISP. SRP -- (Single Responsibility Principle 单一职责原则) OCP--开闭原则(Closed for M ...
- 百度的hao123.com篡改浏览器首页,解决办法
快捷方式右键找到chrome.exe, 把chorme.exe修改成别的名字例如 chromeFuckHao123.exe 就OK了. hao123是用病毒的形式查找chrome.exe然后进程注入的 ...
- java 包 修饰符 权限详解
作用域 当前类 同package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly(default) √ √ × ...
- 解决mac-osx10.11下无法安装wxPython2.8-osx-unicode-2.8.12.1的问题
在mac-osx10.11版本下,安装RIDE前提需要装wxPython2.8-osx-unicode-2.8.12.1库,但在安装wxPython过程中,会提示安装失败,以下提供一种解决方案 这里我 ...