#研发中间件介绍#NotifyServer

郑昀 基于朱传志的设计文档 最后更新于2014/11/11

关键词:异步消息、订阅者集群、可伸缩、Push模式、Pull模式


本文档适用人员:研发

电商系统为什么需要 NotifyServer?

如子柳所说,电商系统『需要两种中间件系统,一种是实时调用的中间件(淘宝的HSF,高性能服务框架)、一种是异步消息通知的中间件(淘宝的Notify)』。那么用传统的 ActiveMQ/RabbitMQ 来实现 异步消息发布和订阅 不行吗?

2013年之前我们确实用的是 ActiveMQ,当然主要是订阅者 Pull 模式,选 MySQL 做消息持久化存储,SA 还为此反复测试了各种高可用方案,如下图所示,ActiveMQ 5.8,mq主从+mysql互为主从+MMM。

图1 mq 高可用

它有三个问题。

第一,它对上游发布者要求可能不是那么高,但要求下游实现消息订阅时要健壮,比如订阅者把消息读走了后它挂了也得不丢弃消息继续处理,比如非常重要的消息不能只有一个单点订阅者,必须有订阅者集群,但又不能重复处理消息。我在《#研发中间件介绍#JobCenter》中说过,对每一位开发者维护者提出高要求,这不是我们的解题思路。我在《职场培训第五期:职场的真相》中给出了解题思路:『要摒弃单纯依靠员工之间互相提醒、依靠个人认真细致来规避相同错误的固有思路,铁打营盘流水兵,靠人终归是靠不住的,最好靠遵循规则的机器』。是的,异步消息的可靠推送(Push),应该是消息中间件的职责。

第二,ActiveMQ 的高可用方案在可伸缩上不那么灵活,不适合电商业务。譬如说,我一开始用一组 [(mq1+mysql1(master角色)),(mq2+mysql2)] 来支撑所有业务的异步消息,但突然七夕节一个销售验证高峰即将到来,需要尽量平滑地把某些消息队列转移出去,用另一组支撑;或者我看某个消息队列的消息量比较大,想追加一个 mysql 节点单独存储它的消息。总之就是线上尽量平滑地扩容 mq server和 database,这事儿还得咱们自己从头搞才顺手。

最后一个问题是所有开源系统的典型问题,伴随着开源系统以及各种 Driver 的版本升级,我们会一路踏入它埋下的每一个大大小小的坑。当然,不是说我们自己写的中间件就没有 Bug,但  ActiveMQ 确实让人摊手,如下面的 RCA 案例所示。

  • RCA:ActiveMQ 的生产者流量控制导致订单中心大量线程挂起;
  • RCA:PHP连MQ超时导致主库连接被打满,引发众多应用数据不一致——原因在于 PHP::Stomp 包的默认重试次数和默认超时时间;
  • RCA:调小 ActiveMQ之持久化 MySQL 的 wait_timeout 导致发送 MQ 消息频频失败。

最终我们还是选择自己来面对如下场景,采用 Push 模式(NotifyServer 主动向下游 Push 消息):

图2 一个异步消息需要很多订阅者集群分头处理

淘宝是怎么考虑这些问题的?

  • 可靠性:
    • 消息的投递分为两个阶段
      • 发布者向Broker发送消息
      • Broker向订阅者投递消息
    • 因此,消息有可能在三个地方丢失
      • 发布者到Broker之间
      • Broker本身
      • 从Broker到订阅者
  • 稳定性
    • 监视
      • Broker内存使用
      • 消息收发功能
      • 消息堆积情况
      • 存储的插入速度
      • 各个任务队列长度
      • 其他各项即时统计数据等
    • 控制
      • 自动移除失效存储节点 
      • 优雅降级的控制 
      • 添加新存储节点 
      • 添加新Broker
  • 限制
    • 有可能产生重复消息
    • 对订阅者的要求
      • 幂等性 f(f(x)) = f(x)
      • 重复调用多次产生的业务结果与调用一次产生的业务结果相同

它内部两个消息中间件产品的区别为:

图3 消息中间件对比

以上资料出自于《消息中间件-Notify的概念和原理.pdf》。

窝窝如何实现 NotifyServer 的?

2013年2月,经过几轮的讨论,技术选型初步确定,研发2部传志开始构建 NotifyServer。

他设计了如下概念:

图4 notifyserver 的几个角色概念

技术模型可以描述为:

  • 模块关系
    • 各个模块(队列、生产者、交换中心、DB、消息体缓存、队列缓存、日志缓存、分配中心、消费者)存在一定的对应关系,通过这些对应关系能够更好路由和分流消息,动态扩展系统,改善系统瓶颈。
    • 这些对应关系都存储在控制中心关系数据库中,通过控制台界面来进行配置,各模块在启动和定时到控制中心来更新这些关系,用于消息的分配。
    • 这些关系都遵守一定规则,添加更改不会影响系统的稳定性,如:一个队列必须对应两个以上的交换中心来处理消息,如果DB中还有消息没有消费完毕不允许直接删除,等等。
  • 模块监控
    • 控制台定期测试各个模块的健康状况。
    • 各个模块会定期向控制中心发送一些监控数据,报告自己的运行状态。
    • 控制台收集监控数据,以图表、拓扑图等形式向管理人员展示或报警。
  • 消息跟踪
    • 每一条消息在进入系统后都会被分配一个唯一标识。
    • 各模块在处理消息时都会产生特定的日志信息,日志信息实时的传送到日志系统。
    • 唯一标识+日志+各模块信息和关系可以容易的跟踪每一条消息的执行情况。

那么最简单的消息消费泳道图如下所示:

图5 消息消费

分配中心主导的慢速/重试Push,它会尽量从缓存(Redis)中拿消息体,尽量减少对 DB 的访问,尤其是消息体特别大的时候,效果会比较明显,如下图所示。

图6 重试的泳道图

对于可伸缩、高可用,他是这么考虑的:

  • 吞吐量:
    • 交换中心、分配中心都采用平行结构。
    • 队列使用持久化方式缓存,使用缓存减少对DB的操作。
    • 交换中心与分配中心分离,性能互不影响。
    • 动态改变网络拓扑结构,分流系统瓶颈。
    • 动态控制吞吐量参数,调整系统性能。
  • 扩展性
    • 交换中心、分配中心、DB、缓存可以动态添加或删除。
    • 队列路由路径可以动态改变。
  • 可用性
    • 交换中心、分配中心采用平行方式提高可用性。
    • DB采用 master-master 方式提高可用性。
    • 缓存采用多点读写方式提过可用性。
  • 一致性
    • 消息状态持久化在DB,未分配或消费失败的会再次被提取。
    • 分配中心采用快慢两种方式接收消息处理消息。
  • 等幂性
    • 缓存保存正在处理的消息,防止重复分配。

与 JobCenter 一样,NotifyServer 也纳入在我们的 idcenter 体系下,这样可以共用一套帐号体系(LDAP),共用一个统一的权限分配:

图7 notifyserver 的入口

图8 notifyserver 的主界面

图9 notifyserver 系统队列(主要是配置信息)界面

图10 notifyserver 监控队列(主要是运行时状况)界面

2013年中旬,经过积分业务的试用后,传志的 NotifyServer 开始在内部推广,各种异步消息发布和订阅一点一点地搬进来,ActiveMQ 方案下线。

-over-

时间: 2024-10-11 23:28:33

#研发中间件介绍#NotifyServer的相关文章

#研发中间件介绍#定时任务调度与管理JobCenter

郑昀 最后更新于2014/11/11 关键词:定时任务.调度.监控报警.Job.crontab.Java 本文档适用人员:研发员工 没有JobCenter时我们要面对的: 电商业务链条很长,业务逻辑也较为复杂,需要成百上千种定时任务.窝窝的大多数定时任务其实调用的是本地或远端 Java/PHP/Python Web Service.如果没有一个统一的调度和报警,在集群环境下,我们会: 不知道哪一个定时任务执行失败或超时,不见得能第一时间知道——直到最终用户投诉反馈过来: 要求每一个定时任务输出统

#研发中间件介绍#异步消息可靠推送Notify

郑昀 基于朱传志的设计文档 最后更新于2014/11/11 关键词: 异步消息 .订阅者集群.可伸缩.Push模式.Pull模式 本文档适用人员:研发 电商系统为什么需要 NotifyServer? 如子柳所说,电商系统『 需要两种中间件系统,一种是实时调用的中间件(淘宝的HSF,高性能服务框架).一种是异步消息通知的中间件(淘宝的Notify)』.那么用传统的 ActiveMQ/RabbitMQ 来实现 异步消息发布和订阅 不行吗? 2013年之前我们确实用的是 ActiveMQ,当然主要是订

#研发解决方案介绍#基于StatsD+Graphite的智能监控解决方案

郑昀 基于李丹和刘奎的文档 创建于2014/12/5 关键词:监控.dashboard.PHP.graphite.statsd.whisper.carbon.grafana.influxdb.Python 本文档适用人员:研发和运维员工 提纲: 监控平台要做到什么程度?为什么要自己做? 几个通用技术问题 绘图所依赖的数据如何收集?如何加工?如何存储? 图形如何绘制,各种指标如何叠加? 拓扑关系如何绘制? 技术选型哲学 最终选了statsd+graphite 数据的采集 数据存储的粒度 天机的技术

数据库相关中间件介绍

数据库相关中间件介绍 详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt412 这里主要介绍互联网行业内有关数据库的相关中间件.数据库相关平台主要解决以下三个方面的问题: 为海量前台数据提供高性能.大容量.高可用性的访问 为数据变更的消费提供准实时的保障 高效的异地数据同步 应用层通过分表分库中间件访问数据库,包括读操作(Select)和写操作(update, insert和delete等,DDL, DCL).写操作会在数据

#研发解决方案介绍#基于ES的搜索+筛选+排序解决方案

郑昀 基于胡耀华和王超的设计文档 最后更新于2014/12/3 关键词:ElasticSearch.Lucene.solr.搜索.facet.高可用.可伸缩.mongodb.SearchHub.商品中心 本文档适用人员:研发和运维 提纲: 曾经的基于MongoDB的筛选+排序解决方案 MongoDB方案的缺陷 看中了搜索引擎的facet特性 看中了ES的简洁 看中了ES的天生分布式设计 窝窝的ES方案 ES的几次事故和教训 ES自身存在的问题 首先要感谢王超和胡耀华两位研发经理以严谨治学的研究精

#研发解决方案介绍#Tracing(鹰眼)

郑昀 最后更新于2014/11/12 关键词:GoogleDapper.分布式跟踪.鹰眼.Tracing.HBase.HDFS. 本文档适用人员:研发 分布式系统为什么需要 Tracing? 先介绍一个概念:分布式跟踪,或分布式追踪. 电商平台由数以百计的分布式服务构成,每一个请求路由过来后,会经过多个业务系统并留下足迹,并产生对各种Cache或DB的访问,但是这些分散的数据对于问题排查,或是流程优化都帮助有限.对于这么一个跨进程/跨线程的场景,汇总收集并分析海量日志就显得尤为重要.要能做到追踪

#研发解决方案介绍#基于持久化配置中心的业务降级

郑昀 最后更新于2014/4/18 关键词:业务降级,配置中心,基本可用性, A.业务降级的背景知识: 淘宝就双十一课题曾经讲过: 『 所谓业务降级,就是牺牲非核心的业务功能,保证核心功能的稳定运行.简单来说,要实现优雅的业务降级,需要将功能实现拆分到相对独立的不同代码单元,分优先级进行隔离.在后台通过开关控制,降级部分非主流程的业务功能,减轻系统依赖和性能损耗,从而提升集群的整体吞吐率. 』 主动关闭系统功能的场景: 我们更新系统或数据库刷库时,可能会提出,某天凌晨几点到几点不能下单,几点到几

#研发解决方案介绍#Recsys-Evaluate(推荐评测)

郑昀 基于刘金鑫文档 最后更新于2014/12/1 关键词:recsys.推荐评测.Evaluation of Recommender System.piwik.flume.kafka.storm.redis.mysql 本文档适用人员:研发 推荐系统可不仅仅是围着推荐算法打转 先明确一下,我们属于工业领域.很多在学术论文里行之有效的新特奇算法,在工业界是行不通的.当年我们做语义聚合时,分词.聚类.相似性计算.实体词识别.情感分析等领域最终还都采用了工业界十几年前乃至于几十年前就流行的成熟算法.

中间件介绍

中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.Auth