中国应用性能管理行业盛宴——2016中国应用性能管理大会(简称APMCon 2016)于8月18日至19日在北京新云南皇冠假日酒店隆重召开。APMCon由听云、极客邦和InfoQ联合主办的作为国内APM领域最具影响力的技术大会,首次举办的APMCon以“驱动应用架构优化与创新”为主题,致力于推动APM在国内的成长与发展。
美团点评技术工程部技术专家 尤勇于服务器端应用监控实践专场发表了题为《开源APM软件CAT解密》的演讲,现场解读了CAT的发展历程,以及CAT在服务端、移动端、前端监控的实战情况,解读CAT核心报表技术以及一些宝贵的关于CAT的使用经验。
以下为演讲实录:
尤勇:大家下午好!这一场是服务端监控的专场,第一场是由我来给大家分享我们在点评美团里面依靠CAT系统是怎么做的,每一场结束后大家可以进行提问,如果大家提的问题还不够的话,对面还有一个讲师交流,大家可以去进行更深层次的交流。今天由我开始给大家带来第一场分享。
我做一个简单的调查,了解过CAT系统的人有吗?看来大部分人都不是很了解,那我这个PPT里面会有一些产品和设计相关的内容。首先自我介绍一下,我叫尤勇,2010年加入美团点评,一直在基础架构团队做相关的一些工作,现在主要负责CAT监控、移动接入层、slb等项目。今天主要分享的一个是CAT介绍,一个是CAT设计,还有在整个过程中我们的一些实践。
一、CAT介绍
CAT我大概给它做了一个总结,美团点评里面有两个词形容它,一个是移动端监控,一个是应用层监控。因为这是一个服务端专场,所以移动端就略过。CAT是一个提供实时监控告警,移动端以及后端应用性能分析诊断的工具。、
说到监控,或者用今天更大的词APM来讲有这几个层次,我在这里用我的一些定义,给大家做一些划分。
•第一层是移动端监控,比如所有的API,还有返回码、城市、地区、运营商、版本等很多数据,这些数据解决了哪些问题?比如我今天发了一个版本,怎么知道这个版本发出去怎么样,比如在某个地区劫持了,或者某一个省份成功率非常低、响应特别慢,我怎么知道它的问题?定义于移动端的衍生还有一个前端监控,就是我们传统意义上微博站点的监控。前端监控的占比比较小,因为现在整个互联网已经偏移动化了,像点评美团这样的公司,90%的流量都在移动上面。
•第二层是业务监控,比如支付、订单、验券等等,我们可以理解为最核心的业务指标。
•第三层是应用层监控,包含url、service、每次缓存调用、数据调用等,在整个应用层的数据比业务层要多很多。
•第四层是系统层监控,包括物理机、虚拟机、数据库以及CPU、Memory、网卡流量等等。
•第五层是基础设施监控,这一层更加偏向于网络,包括网络、交换机以及F5监控等。
在整个监控层里面有移动端监控、前端监控、业务监控、应用层监控、系统层监控、基础设施监控,前面三层基本所有的数据在CAT里面承载,下面这两层一般情况下有zabbix或者小米系统都可以做。这是我对监控层大概的理解,至少在点评美团是这么来做分工的。
要做到真正的实时监控,并且能做到快速的故障定位,有几点很关键:
1、客户端日志不落地。
2、服务端实时处理。
3、客户端全量数据采集。
这就意味着整个服务端里运行的所有的请求,整个系统从消息的产生到服务端把报表产生出来,整个监控系统不仅要解决快速的发现问题,还需要很强的报表功能知道这个故障到底是哪个系统引起的。
在这个基础上我讲一下CAT以前基于这一点我们做的原始消息格式是什么样的,我们称之为CAT的原始消息。
比如上面图中,左边一列全部是时间,时间就是从程序开始到结束出现的那些序列,这里面有URL,我们可以知道我们程序在这一点执行了那些关键路径以及这个请求过程执行的所有事情,你可以理解这就是一个日志的流水。我们把所有事情串起来,就知道我一共做了多少事情,每一件事情都是有时间序列串起来的。与之对应的,我可以知道每一段发生的时间在哪里,每个请求的时间有多长,比较慢的是哪个,这样就知道这一段优化的方法是哪个。
大家也知道在服务调用链中有A调B,B调C这样的情况。这里面有开关,一点就可以知道远端服务是怎么执行的,所以在整个调用链路里面是可以知道A调B,B调C这样的链路的,整个链路是可以串下去的。
我们系统里面所有的来源都是原始格式,我们现在的生产环境,一天大概是800亿、900亿数量级,也就意味着人根本不可能看这样的数据,已经超出了人类所能看的范畴。这也就回应了早上有些嘉宾讲到整个APM的数据是非常多的,是远超于任何一个业务系统的数据量的,因为它是记录到全站里面所有系统的访问路径的。这可能还是点评这个级别的公司,如果上升到百度、腾讯、阿里,如果在业务上有一定数量级,这样的监控可能有两到三个数量级,因为你处理一个业务请求,后面要调的服务有可能是十几次、二十几次。所以整个应用监控里面原始数据非常庞大,那在这个基础上我们必须要做一些业务部门能看得懂的报表,所以我们做了应用监控报表,比如有Transaction报表,有Event、Problem、Hearbeat等等这些报表,这里我大概介绍三个左右,让大家了解一下。
1、Transaction报表,就是一段代码运行时间、次数。比如我们一个应用程序响应很慢,最后所有的优化点都来自于优化那一段响应时间,这个响应时间就叫一段代码的响应时间。首先每一个接入的项目有一个项目名,其次这么多项目会部署到很多台机器上,整个Transaction有两层分类,一是Type分类,一是Line分类,通过这两层可以知道一个URL,可以知道这一段时间内所有访问的接口是8毫秒,访问量是几十万。
如果看到这些数据能解决什么问题?怎么通过这个报表找到性能的点在哪里?一般看响应时间慢的应该就是你要优化的地方,访问量比较多的也是一个可能优化的地方。整个所有需要优化的应用程序就在一个两个,优化那些响应时间特别慢的和那些访问量特别多的。通过这个你就可以发现整个应用程序性能里面无论是跟URL、数据库缓存有性能点的通过这些都可以知道,一些代码片段都可以通过定义埋点的方式知道。这时候肯定会有同学问比如URL的埋点怎么做?比较推荐的做法特别是我们在点评美团实践的结论是URL集成一个freedom就可以了。我们现阶段正好在点评这套系统里面做,每个框架基本上花半天到一天基本上就可以做完了,大概是这样的,埋点的成本特别在企业内部做埋点成本相对比较低。
2、Problem报表,比如我们一天有800亿数量级,你不可能叫业务开发人员来看这些数据,所以我们根据这个800亿的数据针对每一个项目做了一些特征的提取,这些特征就是那些有问题的特征。比如,第一个特征我们定义为exception,第二是long-url,第三是long-sql,第四是long-service,第五是long-cache,第六是long-call,第七是Transaction fail。相对而言这个系统是提供了一个傻瓜式的报表告诉你,你就应该优化这个地方。所以我们很多技术体系的报表,包括给老板看的一些指标都会从这上面看到,如果让业务开发自己去分析,或者自己通过压测分析结果,业务量是很大的。所以我们做了Problem报表,把有问题的东西给你找出来,告诉你这些东西就是你应该优化的地方,换句话说如果你这些应用没有任何异常,那你这个应用我相信基本不会有什么问题,或者这些应用出问题的概率相对比较少。
3、Cross报表,现在我们整个公司都在SOA做服务化。举个例子,以前我们做一个服务,它有时候因为一个job批量调用把它调垮了,我们针对整个调用环节做了一个Cross,整个统计是支持到项目、IP、每个方法。比如,我在客户端里面可以知道A项目调了哪些服务的哪些方法,调每个服务访问量是多少,响应量是多少。服务端跟客户端基本一样,我可以知道每个服务端被多少人调了,调了多少次,方法有哪些。
我今天在产品部分准备的相对少一点。如果你们对产品部分还有一些疑问,建议大家到网上搜一些PPT,那里面会有更加详细的内容。
二、CAT设计
接下来我们讲一下CAT设计,分三个部分:一是整体设计,二是客户端设计,三是服务端设计。
在做任何系统的时候都有一些核心的SOA,在这个指标的前提下才能选择整个方案是什么。我们监控系统的指标如下:
•第一、我们要做到对应用无影响 。
•第二、实时性 。因为我们是一个实时系统,在整个生产环境出故障,一是要靠监控发现问题,二是靠监控定位问题,所以整个系统的实时性就意味着你处理故障的响应时间。
•第三、吞吐量 。吞吐量是一个系统,特别是APM系统,面对这么庞大的数据量时肯定要面临的一个问题,目前我们在生产环境下整个系统吞吐量是几百万每秒,所以系统吞吐量非常大。
•第四、开销低 。我们做了一些压力测试的数据可以给大家做一些参考,我们CAT有一个交流群,上面也会有一些测试方面的工作,但是我发现压力测试并不是所有人都能做得非常好,有时候压缩数据跟我们自己公司内部压缩数据差别很大。
•第五、可靠性 。我们认为我们整个系统没必要设计为百分之百的可靠。
•第六、服务端处理100%的到达消息 。我们认为服务端也不是必须百分之百的消息到达,它是允许一定数据丢失的。
把第五点和第六点设计成不是百分之百可靠并不是意味着你整个系统就朝着这个方向去做,像我们在监控系统里每天处理八九百亿,最后算下来丢掉的消息可能会有几十万上百万,可能最后可靠性在四个九以上,所以在做很多系统设计的时候,整个系统有没有必要做到100%跟做到99.99%,这个方案差别是非常大的。
整体设计方面,我们有很多的业务方应用A、应用B、应用C,在整个生产环境中有一万多个节点,他用了我们的SDK,通过长连接的方式把数据发到我们的消费机里面,整个消费机的水平可以扩展,随着机器规模的增加可以随便扩展。我们有两部分的数据,一部分是Logview,这个数据是放在HDFS上面。一部分是Repor,这些实际上是放在MySQL里面。这个结构非常清楚,最后在做整个部署的时候,消费机和控制台部署在一起。
这个时候大家会想到,好像结构非常简单,实际上在做整个基础架构里面,我体会最深的一点就是,什么样的架构是一个非常好的架构?实际上只有一个词叫简单。简单的东西就是好东西,不是说用了一个非常复杂的项目,你要知道如果一旦用了那些复杂的东西,可能意味着生产系统的维护成本非常高,这就是为什么整个CAT系统在开源后很多小公司在用,因为它用了之后只要一台机器,如果发展到很大规模,一样用这套架构可以玩得转。所以在这里我感受非常深刻:一个东西要解决很多问题的时候要用那些很流行的词,没用那些东西就感觉OUT了一样,实际上不是那样,我们要把复杂的东西做到简单,用简单的东西提升它的稳定性,提升它的层次,里面的代码质量可以写的很复杂,但是架构一定要简单。
接下来我们讲一下客户端设计:
我用一个Http线程举例,我在整个线程组里用了一个ThreadContext,在线程开始的时候,我可以在业务主线程上创建一个监控的起点,比如做了一次远程调用,就把远程调用的监控信息放到树里面,最后整个请求结束就返回给用户,这时候消息构建就结束了,结束之后做的第一件事情,就是把当前这个请求的对象放到内存队列里去。实际上在这里面有一个深刻的体会,就是写SDK,特别是框架级别的SDK,它的要求确实很高。这个得益于整个CAT第一版的设计师,我印象中整个CAT的客户端从上线到今天应该就出现过一次bug。我也曾经历过很多框架,比如配置框架等等都出现过若干次的bug,在这里面写出来的东西会时刻关注每一行代码的性能,最后才能完成像前面说的加了整个CAT的SDK,正常情况下整个监控的影响只有2%左右。客户端比较重要的点有以下几个方面:
1、内存开销 ,怎么严格限制SDK消耗的内存。以前我们遇到过一个极端的例子,我可以理解为如果一家公司面临业务方比较多,任何极端的例子都可能会有。我们有一个业务请求做餐饮加商铺的销售额,他一般会通过for循环所有商铺,结果就造成内存爆了,后来发现有几万家分店,会循环几万次,每个循环里面都会有数据库连接。所以说写框架的代码不能想象业务方会怎么用你的代码,任何情况下都可能会出问题。
2、CPU开销 ,CPU开销也是一样,构建消息要足够轻量,开销减低在2%。
3、客户端没有做压缩 ,如果要做压缩可能会消化客户端的性能,服务端可能也需要做解压。为什么没有做压缩?就在于内网带宽消耗比较大一点。
4、基于netty实现消息传输 。
服务端设计也是这样,我们有很多应用,把所有的监控请求全部发过来,我们这边会有一堆接收器,把它接收过来。接受过来后,第一件事情就是把所有监控请求放到队列里去,在这个队列上会做二次分发,把这些消息发到二级队列里,通过二级队列我们进行不同机制的处理,可以理解为在这个队列里面我们再做一次扩展,整个是采用全异步的方式做的。全异步带来的好处是访问量很高,但第二个就是这个队列会满,所以这个也验证了前面说的,整个系统不保证是一个可靠的系统,队列可能会丢。这个方案为什么这么做,也是得益于我们前面做了一些基本的结论。
我们的本地存储实际上写到本地的文件,文件通过异步的方式发布到HDFS里面,统计报表是放到MySQL里面,这里面都不能用实时的,如果用实时会出问题。所以,我们用本地磁盘写了一次缓存,就是把所有文件按照索引结构写了一次文件,再通过文件形式过一段时间慢慢传输,所以整个服务端的基础架构就是这么简单。
整个CAT系统的搭建是可以支持非常小的规模的,只要一个MySQL就可以把整个系统玩转起来。如果你的系统做不到这样,那你整个系统的开发效率是非常高的。一个项目真正在做开发设计,后面有很长的时间需要做一些维护、监控、运维等工作,如果你的系统设计的非常庞大,那你的运维成本很高,很多成本都是长期的成本,所以我在这里非常建议大家,无论做什么样的系统,必须要把复杂的系统简单的去做,但是简单不一定意味着这个系统很弱。
我们认为在服务端里几个比较重要的地方,第一是监控建模,第二是报表建模,第三是CPU优化,第四是数据存储。
1 、监控建模 。如果不用建模,很多监控解决方案会用log,这也是很多的思路。log意味着整个结构是一个很松散的结构,你从log里面提取一些东西,然后又可以无限的去打一些信息,最后通过后面配规则实现这个log,现在很多市面上都是这么做的。但是log里面有一个问题,我认为它最大的问题在于结构过于松散,这意味着后端处理这个log的成本是非常高的。
在CAT系统里面首先需要对监控领域做建模,可以解决什么问题?一是解决一段代码的执行时间,二是一段代码执行次数,三是定期执行某些代码,四是监控一些指标,比如这些指标是销售额、订单量、验券等等这些。对应的名字一是Transaction,二是Event,三是Heartbeat,四是Metric。但是这些模型能不能解决所有的问题?很明确的告诉你是不能的,比如消息的监控,比如我要知道消费端延迟,生产端的延迟,或者我要知道这个消息在哪一段的存储延迟等会有很多场景,你不要以为一个监控系统或者一个APM系统就是万能的,不是这样的,特别是在针对一些很极端的我理解就是更加偏向于后台的应用,比如特别是基础架构的应用,或者是运维的应用,但是这一层通用领域可以解决什么问题?特别是大公司里面所有业务方的问题,你要把那些因为业务方做的所有的开发框架,做得所有的事情都是基于整个平台中间链路上的一些应用,你能把应用开发解决好基本上就能解决很多问题了,因为整个公司大部分问题都是为了让业务开发搞一些问题。
2 、报表建模 。现在很流行的监控有OpenTSDB,还有时间序列库,比如InfluxDB等,他们也是在做一些监控,但他们做监控往往都是基于一个指标。这样到后面你会发现越做越复杂,开始指标非常少的时候非常管用,等突然间变大了之后问题会很多。APM里面有一个词叫做你分析到最后的报表越精细,最后给业务查问题,查性能,包括找故障的源头才会更加深。
我们整个CAT系统里面用了大量的服务端建模的思路。包括目标模型定义,目标模型的定义是什么?就是我最后给业务呈现的报表是针对于一个特定领域的;访问、转换和合并;模型持久化;XML,JSON,Binary;代码生成。
模型遍历 ,如果一个模型有六七层的结构,当你去遍历的时候,如果没有很合适的方法,一般我们可能就会用For循环。在这里介绍一个比较好的模式就是Java的访问者模式(visitor pattern),这样会极大的帮你解决遍历整个模型的程度。平时我们在做设计模式时用的比较多的肯定不是这个,但在做建模的时候它确实是非常好用的。
模型合并 。就像我前面讲的,我们在做一个模型的时候有六七层结构,我要把两个模型变成一个模型,因为你处理的消息可能在很多地方,最后要把很多数据合并展示给用户,很多监控系统会把集中式的地方放在存储里面,用存储解决合并的问题,比如传统意义上业务系统的数据库。我在这里的一个例子就是在做模型合并的时候,不能要求在最后的存储上帮你做合并。我们做模型合并是这样的,前提是一个项目所有的监控机在两台机器上,每个模型都有六层七层的结构,你把六层七层这样的模型合并成第三个模型,如果你没有好的方式来做这样的事情,基本上这样的代码写一两天都很难写的完全对。我们可以很方便的用一些工具支持到模型的合并,最后你就关注到两个节点的合并。
接下来讲一点cpu的优化,所有的应用程序后端吞吐量都是比较大的,我们能够优化的都是应用程序自身的一些东西。实际上优化大概分两类:第一,减少重复的cpu的运算,第二,减少重复对象的创建。
数据存储实际上一直是集中式的存储,但我们没有用集中式的存储。我们的系统是2010年就开始做了,那个时候整个存储比较火的可能就是HBS,当时HBS整个稳定性真的是不敢恭维,或者说如果没有很多能力去投入到这个场景,去做维护还是比较困难的,可能你去维护HBS大的集群,三四个人都不够。那时候我们的存储大概做了四五个版本,最后可以支持的特性是顺序写、随机读以及批量压缩。这个结构我不细讲了,大概就是用了一些多层索引的方式和分片压缩的方式来解决一些问题。
三、最佳实践
最后我们再花一点点时间来讲一下我们在实践里做的一些东西。
一、MVP版本 ,Demo版本用了1个月,MVP版本用了3个月。为什么强调MVP版本?因为做这个项目你是要能让你的老板支持你的决定。大概在2011年左右,我们整个生产环境估计也有一千台机器了,一旦出现问题就到运维那边看日志,看日志的痛苦大家都应该理解,这时候发现一台机器雪崩,可能会导致很多不知道的问题。所以我们就做了MVP版本解决这个问题,当时我们大概做了两个功能。这里我想说的是MVP版本不要做太多内容,但是在做一个产品的时候必须从MVP版本做起,要做一些最典型的功能让你大家支持你。
二、一些不和谐的声音 ,一是业务的挑战,比如可靠性、性能怎么样等等。对于外界的任何产品都要持有保留的态度,要经过自己的验证之后才能知道它适合不适合你,对于业务的挑战实际上相对还好,用一些数据来证明自己就可以。还有就是领导的挑战,不是所有的领导都懂技术,那个时候领导告诉我们要做开关,当业务出问题的时候可以把它关掉,我们就把那个功能做上去了,后来发现很多业务出问题都是由于把这个开关关掉了。所以我们在做任何产品的时候都要坚持一些工程师的思路,领导要的东西往往跟你出的技术方面的东西是不符合的。
三、数据质量 ,我一直认为我们在做整个监控系统就像数据线一样,数据质量决定你最后的监控质量。所以我在前面说你如果不建模,你的数据质量是相对比较弱的。所以,我认为我们在做整个数据质量的时候,可以跟数据库框架,缓存框架、rpc框架、web框架等做一些集成。
四、单机开发环境 ,这也是我们认为对整个项目开发效率提升最重要的一点。单机开发环境实际上就是说你在一台机器里可以把你所有的项目都启起来,这边也有一些小公司出来的,往往做到这点真的很难。如果你在一个单机环境下把所有东西启起来,你就会想方设法地知道这个服务挂了我怎么办。如果你能做到这一点,你整个项目对其他一些系统的容错是相当好的,而且是非常能提升开发效率的。
五、最难的事情 ,最难的事情就是项目上线推动。整个项目大概有两三个人一起做,当时是这样的,一旦说整个产品相对来说做的非常完善,确实是业务方需要的功能,后面会形成良性循环,后面推广就会变得比较容易。但是特别是做底层基础架构的,产品质量是你的生命线,需要支持公司两千多人,所以还是需要很多时间来做这件事情。
六、开放生态 ,APM领域里面公司越大,需求越多。它里面会有很多报表上的需求,比如我们整个点评美团一样,产品有很多报表,整个技术体系里面也有很多报表,技术体系报表里面有些又跟部门相关,需求非常多,所以这个时候很多业务方都会问我们要数据接口等等。最后我们决定把整个CAT系统里面所有的数据都作为API暴露出去,这些需求我们不做,因为我们做那个根本是做不了的。整个系统的开放我觉得也是特别重要的,否则你最后会面临无数多报表的需求管理,会做得非常累。
整个CAT项目从2011年开始做,到现在整个生产环境大概有三千应用,服务器大概是13000到14000的样子,整个项目是从历时看起来是一个五年多的项目,但是你会发现即使做了五年多的一个项目,现在还有很多的需求,这就是我们一直聊过的一点你做得东西越多需求会越多。
最后我做一下总结,第一,要从小开始做起,先做小做精,再做大做全 ;第二,我们要做持续的集成,持续的发布 ;第三,要进行单机开发跟调试 ;第四,Everything Fails;第五,关注客户,快速响应 ;第六,也是特别重要的一点,站在巨人的肩膀上 ,我们做很多系统不是我们想造出一个东西出来,你要知道市面上已经有哪些好的东西可以借鉴。你做任何系统的时候,你都要关注外面很多已经做成熟的非常好的东西,已经有很多经验可以借鉴,这样可以帮你少走很多弯路。
整个CAT系统在github.com上面,地址是:http://github.com/dianping/cat,大家有兴趣可以到上面找一些资料。目前我们有上百家公司在用在搭建,也有一些现在比较大的互联网公司,比如像点评、携程、猎聘等。
我今天的演讲到这边就结束了,如果大家有兴趣可以关注一下,整个项目就介绍到这边。下面有一个提问环节,大家如果有问题可以问一下。
Q&A
Q1:我想问一下您这边CAT的服务端性能怎么样?
尤勇:我们服务端有20台物理机,物理机的配置应该是32和64G的。服务端好像单机到十几万每秒,每个请求大概是2K左右,我看的最多是15万。我之前给你看那个模型,那个模型里面数据是一个小时的数据,支持分钟级的力度,会在分钟级力度里面帮你做合并。
Q2:95线和99线是怎么说?
尤勇:比如我有一千万个请求,这个时候有一个算法,首先做分桶,比如0-10就分十个桶,如果一旦到500以上就分500个桶,这样给业务算出来95线,比如到1秒了,你告诉出来95线是1秒跟110秒是没有关系的,因为95线跟99线不需要特别精确,而且整个互联网里面响应时间一般是几秒,所以不需要,你就分桶,这样可以减少非常多的内存。CAT是不处理任何物理相关值的。