正文
第二部分:Origin -可以轻松的完成百兆以内的文件解析和展示,按时间查找,全局高亮搜索等功能
通过对原始数据解析,我们可以拖拽时间滑片,直接定位到某个时间段查看骑手的日志明细,也可以选择某个关注的Tag,或者直接通过关键字搜索高亮查找,Origin模块让我们可以灵活的查找问题的蛛丝马迹,给定位问题的root cause提供了保障。 这样就够了吗?
第三部分:Statistics - 统计模块是基于特定的Tag数据,数据挖掘分析和展示。 当前实现了对电量,网络,流量,卡顿,请求,生命周期,内存,定位的数据分析。比如下面的内存分析,我们可以通过最长间隔,知道骑手有哪些时间段app是关闭着的,内存的峰值和低谷,平均内存各是多少,内存波动比较大的时间段是哪几个,波动大代表着资源开销可能异常,是需要仔细排查的点。
可以Loc Tag查看骑手的定位轨迹,分析是否有定位漂移或者定位失败情况
还可以通过PunchLoc Tag查看定位上传的失败占比,分析失败的原因是否和当时的网络状态有关
通过THttpReq可以查看网络请求的Host和Path占比情况,方便优化请求流量
Trojan和Dogger-Service组成了Dogger这个有机的整体,日志和解析配合,可以让我们在排查单个case的时候,对用户的行为了如指掌,丰富的埋点数据可以为我们的排查提供数据支撑。 目前Dogger服务中的日志写入sdk Trojan已经开源,欢迎交流学习
当我们有了实时的全局大盘和异常监控,还有单个用户的全周期日志数据,就够了吗?
大盘的曲线正常,异常的毛刺消除只能代表业务大盘稳定,但是业务功能真实的质量还不能一概而论,这时我们需要对数据漏斗的终点---离线数据池进行大数据挖掘分析来做最后的监控兜底。
下面介绍一下最后一层监控EDW
EDW:
离线报表监控作为全局大盘的另一种视角,E-Monitor属于实时大盘监控,只能观察实时曲线趋势和昨天做对比,判断粗粒度的业务是否异常,但是离线数据可以挖掘分析完整一天的数据,细粒度的判断每一个订单的健康程度,聚合定位失败的原因占比,获取复杂条件筛选出的各种比例,让我们从上帝视角观察整个业务线,评估线上业务健康度,分析趋势,表征产出,是移动端监控体系中不可或缺的利器。
公司大数据平台部自研的edw为我们提供了优质的离线大数据服务,它融合了即时查询、数据抽取、数据计算、数据推送、元数据管理、数据监控等多种数据服务的平台型产品。
当前我们在流量,定位质量,骑手多设备使用,离线送达,推送质量,订单异常等关键业务场景都有完备的离线报表。比如上图的流量报表,可以知晓线上流量消耗Top 100的骑手device_id 和流量数据,而排行第一的骑手response数据远大于request数据,通过Dogger拉日志后发现,骑手有多次下载app的行为。第二幅图则是线上主流程的偏向业务的流转时长监控,因为数据敏感所以打码了。这些报表可以说明线上业务的真实健康度,这一点能够让我们对全局的把控更有自信。基于离线数据的聚合分析,可以发现优化点,为改善方案提供依据。
实战
这里记录一下最近发生的一次网络层问题的排查过程,让大家直观感受这几层监控的作用。
第一步:我们的gafana的监控发现Android骑手的订单相关请求平均成功率降低到了98.69%,而正常请求成功率应该在99%以上
上面说到grafana属于可用性全局监控,如果这边的数据异常,将会影响全盘,所以我们不敢怠慢,立马着手排查。
首先我们怀疑是DNS解析问题,我们通过EDW拉取了出现问题骑手的id,然后配置了Dogger的骑手日志拉取,经过分析发现,DNS失败的场景多发生在断网等弱网环境,属于正常情况,而且我们发现日志上出问题的请求的requestID在后端的trace系统上都查不到,查看了skynet网络监控拦截器的代码
apmNetInterceptor插在最后一个,数据没有传上去,说明请求在发送前就已经抛了错,所以我们开始排查请求发送前的逻辑。第二步:通过EDW抽取出现问题骑手,对他们的请求失败原因聚合,得到了ioException异常占比最大
第三步:由于请求前的日志数据过少,所以我们升级了okhttp到3.11,使用EventListener来获取请求生命周期埋点,针对上报问题的骑手发了内测版本,希望获得出问题请求的链路明细。
完整的链路大致如下:
再次捞出有问题骑手的日志,发现有些时候网络状态是良好的,但是在 responseHeaderStart之后会直接抛错或者是 timeout:
于是我们撸了多遍okhttp的源码,觉得应该是连接池复用的问题,复用了已经失效的连接. 我们又加入 IOException 的 stacktrace日志.发现一个奇怪的问题:
线上的请求走的竟然是http/2的协议,仔细阅读Okhttp 握手相关的代码发现,Okhttp 在 https的情况下会判断服务端是否支持 http/2,如果支持则会走 http/2的协议,相关代码参见RealConnection.java的establishProtocol方法。
private void establishProtocol(ConnectionSpecSelector connectionSpecSelector,
int pingIntervalMillis, Call call,