CAT 是 吴其敏 主导设计的基于 Java 开发的实时应用监控平台。他之前在 eBay 工作超过 10 年,对于 eBay 的 CAL 系统有深入了解, CAL 是 CAT 系统当初的原型。
CAT 设计目标如下:
如果故障不是在系统边界,那么通过单元测试或 sentry 这种异常工具可以发现故障的原因并修复。
我们先介绍数据模型,然后根据 CAT 提供的 WEB UI 了解其功能。以下描述中,『应该』表示是我觉得应该,CAT 可能并没有这个功能。
CAT 监控系统将每次 URL、Service 的请求内部执行情况都封装为一个完整的消息树、消息树可能包括 Transaction、Event、Heartbeat、Metric 和 Trace 信息
业务完成埋点后,会产生 CAT 的原始监控信息,即 Logview。
Transaction 和 Event 都是两级分类。Transaction 可以嵌套,Event 就是单个节点,不可嵌套,Trasaction 和 Event 都可以关联 Key-Value,Transaction 有成功和失败状态和响应时间。它还有另一种展现形式,可以明显看出整个请求耗时在哪。
说到 CAT,就要提到 Google 的 Dapper (zipkin 是其开源实现)。Dapper 追踪 RPC 服务间的调用关系,每次 RPC 调用被称为一个 Span,用户的 URL 请求是根 Span A,假设根 Span 调用了 RPC B、C,则 B、C 为 A 的子 Span,这样,整个请求就被建模为由 A 为根的 Span 树,被称为一个 Trace。每个 span 有 trace_id,span_id,parent_id,所有 span 通过这三个 id 联系起来,一个终端的 URL 请求的所有 span 通过 trace_id 联系起来,dapper 因此获得了端到端的追踪能力。通过对 span 计时,一个 URL 请求在各个系统中所耗的时间都能知道,dapper 也因此被广泛用于性能调优。应用开发者可以在 Span 里记录 Annotation 和 BinaryAnnotation,Annotation 带时间戳,BinaryAnnotation 只是 Key-Value,通过 Annotation,可以实现很多意想不到的功能。例如,可以用来实现 CAT。
首先,从数据采集上看,Span 本身就是二级分类,带的 BinaryAnnotation 就是 Transaction 的 Key-value,而 Event 可以用 Annotation 来实现,Annotation 有时间戳,而二级分类和 Key-value,完全可以通过一定的编码放到 Annotation 的 value 里,而 Heartbeat/Metric,无非是 Statsd 里的 Gauges/Timer/Counter,只需要和具体的 Span 关联起来,就可以在前端相关地方展示,Trace 也是 Annotation。其次,就需要基于原始 Trace 做一些统计分析来生成报表,以及在前端展示。
但是,想象不一定都能实现。像 Google 这种超级公司,做出一个通用的 Dapper,有很多其他团队的人会去用好它,例如,日志可以带 trace_id,从而把一个请求的日志都关联起来,并做好很好的展示和报表。对于这种级别的公司来说,日志、数据库、缓存,业务,网络,应该都有比较好的工具去监控和管理,也就不需要 Dapper 去提供这些设计和功能,所以,Dapper 只会去提供调用时间的追踪,而不需要去提供如错误追踪,业务监控等功能。而如果要用 dapper 这种系统去满足监控需求,就需要较多的人力和时间去实现 CAT 现在已经实现的报表。
下面的 Dashboard,TransactionReport、EventReport、ProblemReport、HeartbeatReport、Cross Report 小节,内容基本来自根据尤勇在【QCon高可用架构群】中的分享内容整理而成的一篇文章,包括图片和文字,为了本文的完整性,把它摘录过来。其中文字稍微有所删减,旧版本的图表也换成新版本的图,并整合了一些其他资源,比如原文里没有讲应用大盘,另外还添加了少量我个人的理解。
综合整个系统的一些大盘。
业务大盘:核心业务都会定义自己的业务指标,这不需要太多,主要用于24小时值班监控,实时发现业务指标问题,图中一个是当前的实际值,一个是基准值,基准值是根据历史趋势计算的预测值。这个相当于每个业务有一个 Dashboard,上面有多个图表,图表里显示的指标是业务指标。把业务指标单独抽离并显示,足见其重要性。
报错大盘:所有应用的 topN 的报错大盘,下图是一个出现故障的图。应用的单位是一个可部署的项目。Transaction 应该有属性表明它是什么应用,这样就可以把一个应用的报错聚合起来。图中显示的是每分钟的报错排行,比 sentry 更适合于故障时查看什么应用出了问题。每个项应该可点击,进入报错的 Transaction,查询具体原因。
数据库大盘:
网络大盘:这里采集了核心接入层网络交换机的一些信息,将一些状态定制到监控大盘上,主要的采集指标包括:进入口流量、丢包、错包等。
缓存大盘:与数据库大盘类似
应用大盘:每个应用 OK 不 OK。从图中看,应该是业务情况,一个业务包含多个项目,显示的是每个项目 ok 不 ok。
什么东西才可以作为一个大盘:这里需要看公司整体运维的故障情况,TopN以及业务指标应该属于通用,数据库和网络大盘是点评在实际经验中经常容易出故障的地方,所以做成大盘这样比较直观的形式,用于发现问题。比如平时因为发布引起故障比较多,他们也做了一个发布大盘,实时监控线上的发布情况。
Logview 太多,所以有基于 Logview 的报表,这些报表反映了作者对监控的理解,是 CAT 的亮点。
这个是 TransactionReport 的一个视图,最顶层可以切换项目,一个项目定义为独立的可部署单元,报表以小时为单位(但是是实时的,最新的 Transaction 信息会在当前小时的报表中显示)。再下一行是机器列表,有一个 All 以及具体的机器,可以看所有机器,也可以看单个机器,如果某台机器出现问题,则可以很容易看到。
这里展示了一个Transaction的第一层分类的视图,可以知道这段时间里面一个分类运行的次数,平均响应时间,延迟,95线以及99.9线。95line表示95%的请求的响应时间比这个值要小。
TransactionReport 主要用来做性能优化。看到这个数据,应该想这样的调用量是否合理,这样的耗时有没有办法优化。点击最左边的 show,可以看到响应时间的实时图表。现在时间是 33 分 29 秒,所以图中平均响应时间只有到 32 分钟的数据。
和 TransactionReport 类似,可以根据项目,ip 进行导航,但是没有响应时间的概念。主要是帮业务做一些业务统计,如看每天用户的登录次数或者代码里三个分支的执行次数等。
ProblemReport 把一些有问题的 Transaction 聚合成一张报表,这些 Transaction 包括:
上述报表是 tuangou-web 项目一段时间内的各种问题,点击左边的 show 可以看到错误在各 IP 的分布饼图,以及按错误数按时间的分布。
点击右边 Looooooog 可以看到原始的出错 logview。这个 logview 包含这个请求的整个执行情况,包括 RPC 参数等,很像一个分布式 sentry。
业务开发需要 fix ProbelmReport 中一些比较严重的问题。如 SQL 慢响应很多(通过索引或缓存),服务慢响应(如何优化),调用下游错误(推动下游服务端解决),异常等。
这里主要是 CAT 客户端定期一分钟向服务端汇报当前运行时候的一些状态,几个比较常用的指标有:
这个报表里也可以展示应用自己打的指标。
这个报表主要是解决在 RPC 中的一些上下游调用链路的问题,统计粒度支持项目、具体某一 IP、具体的服务方法。
比如上图是当前项目 xx-web 调用了 4 个服务,调用每个服务的响应时间,访问量以及错误量。点击某个项目进去可以知道具体调用此服务的具体每台机器的情况。
点击 ALL 或者单台机器可以知道调用具体此服务某个方法的耗时情况。
这个报表还有很多其他作用,比如做为一个服务端,它可以知道当前多少客户端访问我,可以查询服务端一个方法被多少客户端调用,每个客户端调用的响应以及耗时。
分请求类型的一些指标的曲线。QPS,响应时间,错误量,命中率,响应时间,错误量等。请求类型包括 get,Mget,delete 等。
错误量,QPS,响应时间,长响应个数等。分请求类型。因此可以方便看到读写比
另外,还有一个页面,展示服务端的一些指标,如 LockAndWait、InnoDBInfo 等。
趋势图:
拓扑图:即服务依赖拓扑图。
一次请求(URL、Service)中的调用链路统计,包括远程调用、sql调用、缓存调用。可以看到一个请求中哪一类型的请求占主要作用。
URL 访问趋势:某个 URL 的请求数、成功率、成功延时。可以限定和比较日期,返回码,URL,地区,运营商。
URL 访问分布:某个 URL 的返回码,运营商,地区分布。
JS 错误日志。
从手机 APP 收集的信息。
API 访问趋势:其纬度包含命令字(应该是业务名),返回码,网络类型,版本,连接类型(长连接短连接),平台(android or ios),地区,运营商。如下图所示。
访问量分布:纬度和访问趋势一样,展示请求量在各个纬度上的分布。如在返回码上的分布。
APP 页面测速:如下图所示。
每天报表统计:如下图所示。
Crash 日志:如下图所示。
告警类型包含:业务告警、网络告警、系统告警、异常告警、心跳告警、第三方告警、前端告警、App 告警、Web 告警、Zabbix 告警、DB 告警、Transaction 告警,http ping 报警。当前报警无需登录可以看到:
而报警配置需要登录才能配置。和其他 CAT 配置放一起,推测报警配置应该是由运维维护。
我们可以从 CAT 的报警里学到以下几点:
首先,进行业务分析,产品线有很多指标,来确定产品是否能满足用户需求,由 DW 负责,然后进行业务监控。业务监控关注最重要的业务指标,目的在于出现线上故障时评价影响面,一般一个产品线的核心业务指标不超过 6 个。比如团购,关键指标是:订单创建数量,交易数量,验券数量。一些定义错误的业务指标,比如XXX接口失败,这其实是一个异常指标,当他大量出现时候,其实XXX正常指标肯定是下降。比如XXX响应时间,这是一个性能指标,不是业务指标,当访问量出问题(比如CDN挂了),响应时间还是正常。
CAT 里项目被组织成产品线。在业务大盘中显示的是一个产品线的业务指标。
对所有应用的 Transaction 的执行次数、响应时间、失败率, Event 的执行次数,异常个数进行报警。数据采集已经由 CAT 做,所以只需要配置下报警。
系统层面的告警。网络:网络流量、丢包率;系统:CPU、Memory 等;
数据库访问响应时间,错误率的报警
根据指定的网址发送HTTP请求,当返回码不为200时发送警告。这个主要是第三方对我们网址的 ping 监控。
业务大盘。业务大盘其实就是业务指标的图表。例如知乎的业务数据包括创建回答数、提问数、邀请回答数、圆桌数、评论数,发送私信数,各主要页面 PV,UV 等。开发肯定是想看这个数据的,评估故障影响也好,看自己的业务是否正常也罢。要把业务数据单独提出来加以强调,并且全面采集业务数据的指标,然后放到一个地方展示。Grafana 一个不方便的地方是使用频率太低,只有绘图功能,点进去还一大堆图,不够有归属感。
报错大盘。所有应用的 TopN。这个在出故障时,所有应用的状况都一目了然。如果点击能查看具体为什么错,那就是一个比一条条日志更好的查错系统。从 Overview 开始,到具体的异常上下文,都在 CAT 里展示。这个会增加 CAT 的使用频率。
数据库大盘/缓存大盘。从响应时间,请求量,出错数这三个客户端指标来评估某数据库是否正常。这个也是在出错时会有用,可以看下是不是某个库出问题了,DBA 操作时也会看着这个盘来评估影响。
网络大盘。从网络层面,采集交换机进入口流量、丢包、错包 等指标,看网络有没有超负载,或某链路是否断了等。网络工程师最爱。
应用大盘。直观的显示一个业务(包含很多项目)是否正常。把所有业务正常与否放到一个页面显示使得整个公司的业务是否正常一目了然。
Transaction report。显示 Transaction 的响应时间、失败率、QPS。一个项目的所有 Transaction 被放到一起显示。先显示 Transaction 的统计信息,可以直观的看到项目的整体情况,点击细节可查看类似 zipkin 那种瀑布图,使得它非常适合用于性能调优。比 zipkin 增加了成功和失败状态,使得它具有定位故障的功能。这里有可以只看某机器的 Transaction,从而可以看到该机器是否有问题。
Event report。可以认为是 Statsd 中计数器。只是增加了两级分类,以及成功失败状态。这里的主要亮点是展示形式。
Problem report。把程序里抛出的异常、URL 访问出错及慢、服务访问出错及慢、缓存访问出错及慢、数据库访问出错及慢这些情况对应的 Transaction 放到一起,做统计,做展示。用于查错,其优点是把所有错误都集中到一起了,并且应用的异常不仅像 Sentry 一样有一些本进程的上下文,还有该 URL 请求在其他机器,其他服务的上下文。
Cross report。RPC 调用中的上下游管理。
Database report。各项目对数据库的 select 等调用的错误量,QPS,响应时间,长响应个数等。可以看到读写比。数据库服务端的指标也可以拿过来一起展示。
Dependency report。项目依赖的指标趋势图,以及依赖拓扑图。拓扑图可以看到本项目依赖的其他项目的健康状况,有利于查错。
Matrix report。本项目一次请求(URL、Service)中,RPC、SQL、Cache 的占比情况。
State report。CAT 自身的一些数据。
System report。
离线报表。
此外,CAT 针对 Web 和 App 定制了一些页面,包含 URL 请求某 URL 的请求量、成功率、延时等趋势图,亮点在于这些图可以做对比图,如 App 的请求,就可以比较 URL 请求在网络类型,版本,平台(ios or Android),地区,运营商等的分布情况。还有每天报表统计。这个也是亮点。很多人都想有个关于自己应用的请求的一些情况的每日报表。
如何做应用监控?开发者想知道:一个请求挂了,到底挂哪了;一个请求慢了,到底慢在哪;为此,要追踪请求的整个过程。先对请求建模。
一个请求称为 Transaction(或者叫 span),有两级分类,开始时间,持续时间,成功失败状态,还有 Key-value 对。在请求发生过程中,外部访问(SQL、RPC、Cache)都是 Transaction。内部执行中,某个时间点可以发生 Event (如异常,缓存命中),Event 有时间戳,两级分类,Key-value 对。程序还有一些状态信息,如队列长度,线程个数等,被建模为 Heartbeat。还有两个需求,程序想统计次数和函数的执行时间,可以分别建模为 Event 和 Transaction。
其他: