51 信用卡的技术架构是基于 Spring Cloud 所打造的微服务体系,随着业务的飞速发展,不断增多的微服务以及指标给监控平台带来了极大的挑战。监控团队在开源 vs 自研,灵活 vs 稳定等问题上须要不断作出权衡,以应对飞速发展的需求。本次将会分享咱们在微服务下的白盒监控思考,以及如何将时下社区流行的 Spring Cloud,K8S,Prometheus 等开源技术在企业落地。
此次主要讲的是关于微服务的监控,微服务看起来很美话,但实践起来却有不少坑,但愿此次的分享能给你们一些收获或者思考。算法
传统的监控通常会将监控分层,好比咱们经常使用的分层方式是将监控分红基础设施、系统、应用、业务和用户端这几层,分完层后将每层的监控作到位。
而在传统的监控里,zabbix 是最经常使用的开源软件,zabbix 的优势主要是成熟可靠,社区很是强大,几乎你的需求,社区都有一套对应的解决方案,但 zabbix 的缺点也很明显,就是太难用,不少监控配置加起来成本很高,甚至不少运维用了好久的 zabbix,还没学会怎么配置 HTTP 监控,这在应用较少的时候,还不是很明显的问题,可是到了微服务时代,这个问题就暴露得很是明显了,并且 zabbix 以机器为维度的监控也没法适用微服务时代的理念。数据库
微服务监控比起传统应用的监控,最明显的改变就是视角的改变,咱们把监控从分层 + 机器的视角转换成以服务为中心的视角,在微服务的视角下,咱们的监控能够分为指标监控、链路监控和日志监控,在开源社区,这些监控也都有对应的解决方案,好比指标监控有 prometheus、influxdb,链路监控有 zipkin、pinpoint,日志则有 elk。
在 51 信用卡发展起步的时候,咱们也一样使用这些开源方案来解决咱们的监控问题,但当咱们业务快速发展的时候,咱们开始不断碰到监控上的挑战,其中有部分是互联网金融特有的,另外一部分是微服务所带给咱们的。缓存
微服务监控有什么特色?用一句话归纳就是服务特别多,服务间的调用也变得很是复杂。咱们实际上是微服务的受害者,其实业内不少人作的架构只是服务化,并不够「微」,而咱们作的比较完全,咱们线上不少服务都只有一个 API,但这样形成线上指标很是多,告警也很是多,读和写的压力都很是大。性能优化
互联网金融是一个跟钱息息相关的行业,因此互联网金融对监控也有本身的要求。首先是对故障的容忍程度很低,监控的有效性须要被反复确认,其次是对监控的覆盖度,黑盒监控在互联网金融里很难行得通,白盒监控变得愈来愈重要,开发们迫切须要对本身的应用有全面的了解。而后是对告警的及时以及快速诊断有更高的需求,告警以及诊断信息在 10 分钟内发出与 5 分钟内发出有很大的差异,举个例子,若是有个活动有个漏洞被黑产行业抓住,若是能早一分钟肯定问题关闭后门,就能给公司挽回巨大的损失。架构
51 信用卡在早期也一样使用 Prometheus,其实 Prometheus 是个很棒的产品,白盒监控的理念也很先进,自带告警以及 PromQL,稍微学习以后便能上手,做为 CNCF 的项目与 K8S 等开源产品结合得也很好。
在随着服务的增加,咱们开始不断地踩坑,首先突出的问题就是 Prometheus 没有现成的分布式方案,性能遇到单机瓶颈以后只能手动给业务划分集群而且之间的数据不能共享,而后拉模式在兼容多数据源上也显得力不从心,好比咱们有场景须要指定精确的时间,还有好比咱们有些数据是从日志来的或是从 Kafka 来的,这些都没有现成的方案。并发
微服务的指标增加其实比想像得要快不少,由于微服务架构下,咱们老是迫切想要把应用的每一个细节都搞清楚,好比主机指标、虚拟机指标、容器指标、应用性能指标、应用间调用指标、日志指标以及自定义的业务指标等等,甚至在这些指标下,咱们还会给指标打上更多的标签,好比是哪一个进程,哪一个机房,咱们大体算过一笔帐,一个服务即便开发什么都不作,他经过基础框架就自带了 5000 个指标。框架
咱们内部也讨论过为何指标会这么多,能不能把一些指标去掉,但很快咱们就否决了去指标的想法,咱们以为业界的趋势是白盒监控会变得愈来愈重要,APM 的概念会变得愈来愈重要,devops 会和白盒监控不断发生化学反应,变成一种潮流。运维
而在 51 信用卡,咱们是怎么解决的呢,其实很简单,用三个字概况就是「平台化」,平台化的好处不少,最直观的好处就是提供了一个统一的平台去处理监控问题,并给开发带来了统一的使用体验。机器学习
咱们首先要解决的问题是如何构建对上层统一的存储,一开始咱们基于 Prometheus 的生态作了一些架构改进,将底层换成分布式的列式存储 Cassandra,并开发了推送服务和拉取服务来兼容原先的数据模型,在上层,咱们开发了兼容 PromQL 的界面提供给开发使用。
但很快,咱们就碰到了新的问题。分布式
首先是 labels 的匹配效率问题,当指标名相同的时候,因为 label 是自由组合的,在匹配部分 label 的时候,咱们须要先将 labels 的元数据所有读出来,而后进行过滤,这样的效率会显得很低,咱们的作法是在 label 元数据上面加上倒排索引,由于咱们是分布式方案,倒排索引自己也须要分布式,因此咱们直接使用 ES 来帮咱们构建元数据。
第二个问题是预聚合,好比咱们只想看 API 的总体访问量,但作这个查询的时候,咱们会在底层读到 4 份数据,而后再聚合再显示出来,这样无疑也是一种浪费。咱们的作法是引入预聚合机制,在纵向,咱们须要舍弃维度,在横向,咱们须要聚合时间轴。对于分布式而言,预聚合会显得比较麻烦,由于咱们须要考虑的东西比较多,好比须要在内存里完成,须要合理将数据分批分配到不一样机器,须要有一个窗口机制保证数据的及时有效又高性能。业内经常使用的作法是引入一个 Storm 这样的流式计算或者 Spark Streaming 这样的微批计算,而后将计算完的结果推入缓存或者内存供告警来使用。
第三个问题是 Metric 的长度,由于在列式存储的底层,咱们直接借鉴 Kairosdb 的存储格式,兼容 UTF8 的 Metric 而直接讲 Metric 转换成二进制存储在数据库里,若是指标不多,这个问题不大,但若是指标很是多,这会形成底层存储的存储浪费,并且影响索引的效率,这个问题的解决办法也很简单,直接引入一个 Bitmap 机制就能够解决。分享Java架构资源,因资料太多,请加高级架构资源裙:948368769 群里面会分享(有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等等)
第四个问题是维度重复,好比咱们有三个指标,这三个指标的维度都同样,但这三个指标彻底不一样,表明不一样的值,但存储在数据库的时候,它会占用三个 series 的空间,查找的时候也不够高效,由于每每三个指标会同时查询同时展现。这个解决办法是将数据库里本来的 value 定义成多类型支持,不仅是双精度浮点或是整型,增长 Map 的支持类型,并在数据库的上层作兼容。
当初咱们在解决这些问题的时候,咱们发现社区已经有一个比较好的解决方案了,就是 Druid,不是阿里那个数据库链接池 Druid,而是 druid.io。它比较好地知足了 Bitmap、预聚合、复合类型、倒排索引、冷热数据这些需求。
咱们将拉服务和收服务作了进一步的改进,能够自动将数据作转换,兼容原先数据模型的同时,将数据也投递一份到 Druid 里。
至此咱们基本完成了一个可以知足需求的存储架构改进。
最后限于时间关系,和你们分享两个很是有用又容易实践的告警智能诊断:
第一个是和日志监控的联动,当一个告警发生的时候,咱们以时间、服务为维度去匹配 ERROR 或是 Exception 日志,并以 simhash 之类的类似算法排序日志,就会很是快速地找到问题的直接缘由,不必定是 Root Cause,但告警的时候若是附上这个日志,对开发排查问题的效率会有很大的帮助。
第二个是和链路监控的联动,当一个告警发生的时候,咱们一样以时间、服务查询链路监控,并从日志监控里排名靠前的日志提取 trace id 后进行过滤,能很快发现故障的关联缘由,这一样不必定是 Root Cause(颇有多是),但一样对开发排查问题颇有帮助。
最后展望一下将来,咱们会继续在 3 个方向发力。
第一个是更好的底层存储,Cassandra 毕竟是一个通用的列式数据库,对时序数据来讲,有不少很差优化的地方,咱们指望可以自研一个时序数据库来知足咱们的业务需求。
第二个是智能化的监控和告警,运用合适的算法并加上机器学习或是深度学习,探索出无阈值的告警体系,并自动分析出告警之间的关联关系,给出根因。
第三个是 APM 和监控的更紧密结合,将链路监控、日志监控和指标监控直接合并,更深度地诊断系统,系统没有没法探查的秘密。