链路监控的核心是建立多个日志的连接,今天我们从服务端与客户端两个方面,一起构建链路监控系统。
<1>
服务端链路日志
1.入口层记录nginx日志
● 客户端调用接口名称以及其相关信息(request time,bodySent等等)。
● 入口idc标记。
● 用户唯一标记(uid)。
● 会话sessionID,这个ID是用来标记一个请求链路的唯一标记。
● 用户相关头信息(ua,ip等)
2.web层记录向后端请求的日志
● 客户端请求的接口的接口名。
● 下游接口的接口名。
● 会话sessionID。
● 其他用户相关信息。
3.两个维度连接三个服务的日志
一个维度是是通过接口名和接口RT,另一个维度是sessionID维度。
我们首先需要给这三层服务分别起一个日志标记,比如七层的日志我们可以起名叫l7,web服务那层叫www,下游服务层叫webinf。
由于我们在三份日志中都记录客户端的接口名,所以我们需要在三层日志中都使用相同的key,比如这个key叫做transUrl。同时我们还需要另外一个同时都有的key,这个key是用来标记每层接口的耗时情况,我们这里命名为tranRT。
4.接口和RT维度查看整体耗时情况
我们可以通过term aggregation请求,通过对transUrl的聚合,查看每一层的RT,可以一目了然的看到各层的耗时时间。在kibana中如下图这样:
由于每一层的耗时时间都包含上一层的耗时时间(七层包含web层耗时,web层耗时包含下游耗时),当下游服务出现问题时一定会对上游系统的耗时造成影响,所以我们可以通过各层的耗时来直接定位是哪一层的问题。
另外当下游数据服务出现问题时,由于我们在webinf日志中记录了两层的数据,所以我们可以直接通过选中webinf日志中下游接口名,而过滤出对他调用的上游接口是什么(因为webinf日志中也记录了transUrl字段),以及此时web层(www日志)中的一些问题,比如如下这样:
以上是服务端记录的链路日志。那么客户端中我们需要记录什么日志呢?
<2>
客户端链路日志
在客户端中我们可能要记录一些更详细的性能日志,这种性能日志主要记录具体阶段的时间,比如要包含下面这些信息:
● 本地等待时间
● dns查询时间
● tcp建立连接时间
● ssl握手时间
● 发送上行数据时间
● 等待服务器响应时间
● 读取header时间
● 读取body时间
我们也可以通过上面记录服务相关链路日志的逻辑记录客户端各个阶段的时间,同时对其进行聚合,得到如下这样的图:
我们可以通过这个图快速的判断客户端响应时间中各个阶段的耗时情况,这样不管是排查问题还是进行服务端性能优化都可以清晰的展现出来。
除此之外再补充一些问题,比如我们现在需要对服务端各个阶段的前后两日的耗时对比,比如如下图这样:
像这样的图我们可以通过kibana中的timelion来做。
<3>
timelion的用法
下面我简单的介绍一下timelion的用法。
timelion底层依赖pipeline aggregations。它的语法有点类似函数式编程的语法,可以通过“.”的方式调用不同的函数来对数据集进行迭代处理。我们通过几个例子讲解一下:
1.查询
最简单的一个查询,我可以查询出来一个索引的日志量随时间变化的趋势。我们可以使用查询语句:
.es(index='logstash-mweibo_trace-2019.07.07')
同时我们也可以添加查询条件,比如我们想看某一类的数据,比如我们想看transModule字段为www的日志变化情况。我们可以使用查询语句:
.es(index='logstash-mweibo_trace-2019.07.07' q='transModule:www')
同时timelion还支持我们对某一个数值条件的日志进行metric计算。比如我们想看这一天中tranRT字段的平均值变化情况。我们可以使用查询语句:
.es(index='logstash-mweibo_trace-*' q='transModule:www',metric='avg:transRT')
我们也可以把多个条件的时序图画在同一个图中,比如我们想分别查看transModule为l7,www,webinf的三种数据变化情况,每个查询使用“,”分隔:
.es(index='logstash-mweibo_trace-2019.07.07' q='transModule:www'),.es(index='logstash-mweibo_trace-2019.07.07' q='transModule:webInf'),.es(index='logstash-mweibo_trace-2019.07.07' q='transModule:l7')
如果我们看烦了直线图表,timelion也给我们提供了其他几种形式的图标,比如点图,柱状图。它们分别对应函数.points(), .bars()
.es(index='logstash-mweibo_trace-2019.07.07' q='transModule:webInf').points()
.es(index='logstash-mweibo_trace-2019.07.07' q='transModule:webInf').bars()
2.指定偏移量
指定偏移量可以方便我们对比不同时刻的数据,在timelion中使用offset函数进行偏移。比如我们想比较两日同一时间数据情况,可以运行如下语句:
.es(index='logstash-mweibo_trace-*' q='transModule:www' offset=-1d),.es(index='logstash-mweibo_trace-*' q='transModule:www')
这里注意一下,我们如果要比较两天的数据,首先需要有2日以上的数据,所以我们在选择数据集的时候使用的index='logstash-mweibo_trace-*'来进行模糊匹配。
以上是timelion比较基础的用法,我们下面来看一下比较高级的玩法。
3.****数据函数转换
timelion支持divide()相除函数,add()相加函数,subtract()相减函数,multiply()相乘函数。还有一些算法函数。比如滑动平均函数(.movingaverage()或.mvavg())。
我们可以使用滑动平均函数对函数曲线进行降噪,得到一条相对平滑的函数曲线。比如我们对平均transRT进行降噪处理,可以使用语句:
.es(index='logstash-mweibo_trace-*' q='transModule:www',metric='avg:transRT' ).mvavg(1``0)
其中mvavg(10)代表使用滑动窗口为10的滑动平均函数进行去燥。
timelion还为我们提供了一些展示函数。比如label()函数。我们可以给这条曲线加一个含义,使用如下查询语句:
.es(index='logstash-mweibo_trace-*' q='transModule:www',metric='avg:transRT' ).mvavg(10).label("平均RT")
我们也可以给我们的timelion加一个title,使用title()函数。
我们可以给这个图起一个题目,比如我们之前那个失败率的例子,我们可以使用title()函数给它起一个名字叫做web层失败率,查询语句如下:
.es(index='logstash-mweibo_trace-*' q='transModule:www AND wwwStatus:5*').divide(.es(index='log``stash-mweibo_trace-*' q='transModule:www')).label("5xx比例").title('web服务层失败率')
4.保存
点击save,会有两个选项,一个是save entire timelion sheet,一个是save current expressoion as Kibana dashboard pane。
一般点击第一个保存即可。点击第二个保存,可以在dashboard看到这个timelion视图。