听云廖雄杰:运筹帷幄—追溯应用性能问题根源
本文整理自GOPS2016全球运维大会主会场听云研发副总裁廖雄杰题为《运筹帷幄—追溯应用性能问题根源》的演讲。
今天带来的主题是《追溯应用性能问题的根源》,我们先来看一下,在平时的运维研发过程中,一个复杂应用交付链的环境下我们会在服务器端部署应用,最终用户端会通过不同的接入方式,比如用浏览器去访问,用手机打开一个APP去访问,那时如果你的浏览器渲染能力或者APP本身的一些切换能力不足的话,都会对应用的性能产生影响。那么在这么复杂的场景下面,我们怎样去快速地监控,在出现问题后如何快速地追溯问题呢。
我们先简单看下图,实际工作中的部署环境可能比这更复杂得多。用户遍布在手机端浏览器端
服务器本身后端也是有很多的服务器组成,同时我们可能也会用近两年比较热门的微服务化架构,服务和服务之间本身也会存在很多复杂的调用。在这么复杂的架构下面,出现性能问题时如何去快速地发现和进行追溯,这是一个值得关注的问题。在我们的日常运维过程中,经常也会碰到这一问题,刚才萧老师也说到运维经常用“背锅侠”这个词语,这个词听起来心里还挺不是滋味的,但实际上这也是运维人员的现状。用户遇到问题的时候打电话来投诉,一般情况下首先找的也是运维,这没有办法,因为出现问题我们总是需要一个入口把这个问题去说出来。
那么在不同的架构下如何追溯?先从App端到Server端说起看下性能问题如何追溯。我们知道APP端距离服务器端很远,运维人员通常出现问题的时候很难去接触到用户那一端。当用户端出现问题时就比较麻烦了,而实现追溯问题的方式就是我们可以在App那一端通过嵌码的方式在开发阶段拦截它的请求和响应,因为APP经常是在网络请求,以及跟网络、服务器端进行API交互的时候出现问题。这个时候通过拦截请求和响应,把服务器端的响应时间注入到自定义HTTP头里面,这样监控时就可以与Server端进行透明交互。我们拿到这些监控数据,就可以快速地定义一些问题。
从App端的监控数据里面看到了首包时间在某个点出现了高峰,首包时间我们通常是会觉得服务器端在响应时出现了问题,出现了一些复杂的调用。这在用户端呈现出的就是响应慢,甚至出现了卡顿,这个时候我们通过一些打点的方式把APP客户端的数据和服务器端的数据关联起来进行分析。这是我们看到一次App端慢响应的时候。
从图中看到一个3秒多的请求,我们通过一些打点的方式将服务器端的数据关联起来。看一下后端在干什么事情,发现由于后端有一个请求,其响应时间有两秒多。再深入地去看一下服务器端,然后点Next看一下详细的情况,发现这个方法用掉了整个服务器调用时间的90%。
而从这些信息看并不能实际地分析出来它到底是什么问题,但是我们可以在下图看出来,这一次请求调用有55次,总响应时间有2秒多钟
开发人员根据这一现状很快地分析出来,根因是Filterlterator的方法出现了问题,这样开发人员可以快速定位追溯这个问题。
同样这样的监控方式也可以应用到其他端。APP端相对来说比较复杂一点,我们要把监控的数据通过打点的方式嵌入进去有点难度,但是对于Browser浏览器端相对比App要简单一些。说到Browser端我们首先想到通过JS,很多网站都有通过JS的注入做一些事情,比如说做广告的分析,做点击量用户行为的分析。同样这样的一个手段也可以做性能分析,包括可以从浏览器端到服务器整个后端,对整个数据库整个过程去做追踪。下面分享一下怎样从Browser端到Server端怎样追踪性能问题。
追踪实现的方式都是大同小异,只是在不同的技术手,里面采取的方式会不太一样。在Browser端是有两个方式,一个是对主页面,主页面是直接的JSP请求,这个请求没有办法篡改,这时能做的就是在服务器端拦截服务器端JSP/PHP编译过程。拦截的话,每一次请求就可以将服务器端的响应时间拦截下来,采集出来通过直接注入到JSP的页面里面,代码也好或者是其他的过程也好只要拦截过程就可以注入进去。
还有像经常会有一步请求,Ajax的请求很多时候就不通过这样的方式了,对Ajax采取另外一个方式,在浏览器里面Ajax的请求是大部分通过XmlHttpRequest的对象去实现的,这个对象可以对它进行拦截,任何方法都是可以替换的,这样把它发出请求的方法拦截下来,把我们要的直接向刚才App端一样,把响应时间通过自定义Request和Resp头传输。
这个追踪数据传输过去以后,我们就可以看到运维最关心的图,就是不同的数据连接、跳转、追踪的事情。这里面跟刚才差不多,我们看到的是Blooth的响应时间,也看到服务器的响应时间,我们是可以把它的服务器端的响应时间进行关联。关联起来如果有问题的话,实际上是可以很快地分析出来到底是浏览器前端的问题,还是服务器端后端的问题,包括一些网络端的问题,通过不同的指标都可以很快速地分辨出来。
刚才介绍的都是两个终端的情况,对运维来说更加关注的是服务器端不同的服务之间发生问题时,怎样去进行追踪。当某一端服务发生问题影响到前端。我们可以快速地发现到底是哪个服务出现了问题,这也是我们需要去监控的时候需要下比较多功夫的地方。我们说要把服务改成微服务架构,一个很重要的问题是监控如何去做,这其实是微服务架构下与开发同等重要的问题。具体的做法与前面提到的差不多,如果是HTTP,就是去拦截HTTP Req/Resp,通过自定义HTTP头实现跟踪,而且通过HTTP头传输是最安全的,对应用基本是透明的,也不会对应用造成干扰。
如果API的框架是其他的框架,这要根据每个不同的框架底层具体权利看,Dobbo是可以通过Attachment对象传输前后端追踪数据,这个对象也是Dubbo进行上下调用的时候,可以随着远程的IDC请求传到后端的,每一次请求可以将这个对象关联起来。这个对象作为附加对象与调用的其他参数不会发生混淆,这样我们把前后端的数据从前端传到后端,后端传到前端都是有可能的。Thrift也是其他的方式,如果是其他的框架要研究一下底层是怎样传输的。不管怎样,核心的点是我们做监控时这个自定义的数据是绝对不能够影响业务的核心协议数据的,这样尽量通过找HTTP头,Attachment这一附加对象来实现,这样对应用比较安全一点。
采集到这一追踪数据,就可以从一个服务追踪到另外一个服务,这样的话就成为了一种可能。像这个案例里面
它前后端是通过消息的组件来进行传输。这样的话就可以从它前端Service到后端Service,前端出现了状况看后端发生了什么问题。这里面发现是在后端的Gateway面是有一个调用的时间比较长,这样就可以达到快速追踪的目的。有了追踪的数据,也可以将应有服务,不同的应用服务之间的拓扑结构调出来。
这样可以很快地发现调用过程中哪个环节是有问题的。