总体介绍
Metaq是一款分布式、队列模型的消息中间件。分为topic和queue两种模式,push和pull两种消费方式,支持严格的消息顺序,亿级别的堆积能力,支持消息回溯和多个维度的消息查询。开源版本叫rocketMQ。
MetaQ运维团队向用户承诺消息不丢,但是不保证不重复,另外发送消息如出现短暂超时现象属于正常,可能是网络问题或者服务器短暂压力大,应用做重试即可。(at least once,业务需要考虑做幂等处理)
稳定
服务可用性99.95%; 经过淘宝多次双十一的考验
可靠
消息多个物理节点保存; 单点故障,自动迁移
弹性
集群按需扩容; topic透明迁移; 软件透明升级
功能介绍
- 消息管理控制台
使用此平台,用户轻易的创建发送消息的topic, 发送者,订阅者,以及自动化生成发送或消费示例代码
消息回溯消费
如果想重新消费最近一段时间的消息,通过控制台,即可轻松做到(目前看是不支持这个功能的,只支持丢弃历史消息)
完善的监控体系
ONS展示用户各topic消息堆积情况,提供报警机制(基于消费者id配置告警)
消息轨迹跟踪
消息投递成功,或者失败,提供消息跟踪日志,方便应用查找问题
全球消息路由(将一个区域的topic消息同步到另外一个区域,主要用于国际化环境)
注:metaq各区域环境原先是物理隔离的,互不影响。
例:需要在新加坡消费杭州产生的metaq消息,就需要进行如下配置,这样新加坡的消费者就可以正常消费了。
基础知识
判断机器连接的metaq环境,登录到你的服务器,
curl http://jmenv.tbsite.net:8080/env
topic和consumerId是否需要申请
日常和预发不用申请,线上需要申请
ProducerGroup是否需要申请
不需要,ProducerGroup用户可以自己随意定义
ConsumerId和consumerGroup的区别
没有区别,叫法不同而已
原理、使用
发布消息
日常环境不需要申请即可发送,Topic与Producer Group请保证唯一即可,但是如果需要在控制台里管理,则需要在控制台里申请对应的资源。生产环境必须要到MetaQ Console申请才能发送。
对于非常重要的消息,例如订单消息,业务方需要有重发补偿的机制,例如MetaQ服务短暂不可用,此时发往MetaQ的消息将失败,等到MetaQ服务恢复后,业务方可以将之前发送失败的消息重新补偿发送
不推荐应用发送超过16K的消息,如果消息确实比较大,发送消息客户端有个配置,默认超过4K的消息开始压缩,消息到达订阅方之前会自动解压。
MetaQ通信层没有对大的请求做优化,采用的是典型的RPC方式,不适合大的请求传递,可能会导致网络层的Buffer异常。
MetaQ的服务器存储是一个典型的LRU CACHE系统,过大的消息会占用较多Cache,对于其他应用Cache命中率产生影响
MetaQ的磁盘资源通常比较紧张
MetaQ暂不解决大消息存储问题
发送消息时,如果将来需要查询消息,或者定位消息是否被接收,需要设置Message Key属性,例如设置为订单Id,商品Id等
发送消息时,如果订阅方有过滤需求,请在消息Tag属性上设置相关值,Tag的名称不需要申请,可自由设置,一条消息只允许设置一个Tag。
发送事务消息,出于运维角度考虑,淘宝用户请使用Notify。
订阅消息
日常、预发等非生产环境,订阅消息不需要申请。订阅生产环境的消息,必须要到MetaQ Console申请才能订阅,系统自动审批。
MetaQ支持服务器消息过滤,如果订阅某个Topic,但只关心其中一部分消息,可以使用表达式方式过滤。这样可以避免无用的消息传输到客户端,而且降低了应用与MetaQ服务器的负载。过滤表达式中的Message Tag是由发送方自由指定
非顺序消息消费,耗时时间不做限制,但是应用应该尽可能保证耗时短,这样才能达到高性能,另外消费消息Hang住,会导致消息所在队列的消费动作暂停,直到Hang住的消息消费完。对其他队列不受影响
顺序消息消费,耗时时间有限制,要保证每条消息在30s内消费完,超过30s会有潜在的乱序问题。(原因是分布式锁超时问题,但概率极低)
消费方式
集群消费,一条消息只会被同一个group里一个消费端消费。不同group之间相互不影响。
广播消费,一条消息会被同一个group里每一个消费端消费。
消息重复性
MetaQ不能保证消息不重复,"Exactly Only Once"这个特性不支持,原因如下:
发送消息阶段,会存在分布式环境下典型的超时问题,即发送消息阶段不能保证消息不重复。
订阅消息阶段,由于涉及集群订阅,多个订阅者需要Rebalance方式订阅,在Rebalance短暂不一致情况下,会产生消息重复
订阅者意外宕机,消费进度未及时存储,也会产生消息重复
消息重复性问题如何解决?
应用方收到消息后,可通过Tair、DB等去重
应用方可通过主动拉的方式,可保证拉消息绝对不重复,但是分布式协调分配队列问题需要应用来控制
消息重试
非顺序消息消费失败重试,消费失败的消息发回服务器,应用可以指定这条失败消息下次到达Consumer的时间。消费失败重试次数有限制,通常线上为每个订阅组每条失败消息重试5次(每次消息都会定时重试,定时时间随着重试次数递增,此过程应用可干预)。超过重试次数,消息进入死信队列,并向用户报警。
消息重试对于服务器代价较高,如果某个应用消息量非常大,且失败率非常高,需要大量重试,则不建议使用MetaQ
顺序消息消费失败重试,某个队列正在消费的消息消费失败,会将当前队列挂起(挂起时间应用可通过API设置),其他队列仍然正常消费。
死信队列
消息一旦进入死信队列,则不再向应用投递,MetaQ监控系统会向应用报警 (报警功能开发中)
由于消息一旦进入死信队列,则不能再被订阅,建议应用在最后一次重试消费时,将失败消息保存到DB
消息堆积
MetaQ每台服务器提供大约亿级的消息堆积能力(多个业务方共用),超过堆积阀值,订阅消息吞吐量会下降。
消息实时性
MetaQ采用了长轮询方式从Broker拉消息(pull),实时性同Push方式一致,消息的延迟时间大约几毫秒左右。
消息在MetaQ服务器保存24小时,超过24小时没有消费,有可能被删除
架构
逻辑部署架构(网图)
物理部署架构(网图)
实际具体分析
大致消费原理(网图)
一个topic有12台机器,每台机器有8个队列,总共12*8=96个队列。(图中brokerName显示14是中间缺了两台机器)
消费者有14台机器,平均每台消费96*14=6.8个队列
总共有108条消费信息,其中消费队列信息是96条(和broker中的队列数量一致),还有12条是重试消息(每个broker都会有一个重试队列,存放消费失败的消息)。