-
- 一、设计依据
- 二、设计思路
- 1、核心数据模型字段
- 2、参数透传说明
- 3、日志格式(举例子)
- 4、链路性能指标(处理时间)
- 三、先决条件
- 1、Web Servlet Filter 调用链开始
- 2、Dubbo作为RPC 调用链跟踪
- 3、DB调用跟踪
- 4、Cache调用跟踪
- 5、MQ调用跟踪
- 四、系统对接步骤
- 1、引入相关JAR包
- 2、定义logger
- 3、引入拦截调用链
- 五、遗留问题
分布式跟踪系统设计
想知道系统哪个地方处理慢么?想优化系统,但不知哪块慢?每个调用耗时多少?xxx,还有N多疑问。好吧,我们先从最简单的跟踪做起。
一、设计依据
谷歌,DAPPER论文。中文翻译链接http://bigbully.github.io/Dapper-translation/ 下面是开头部分。
(当代的互联网的服务,通常都是用复杂的、大规模分布式集群来实现的。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具。
Dapper--Google生产环境下的分布式跟踪系统,应运而生。那么我们就来介绍一个大规模集群的跟踪系统,它是如何满足一个低损耗、应用透明的、大范围部署这三个需求的。当然Dapper设计之初,参考了一些其他分布式系统的理念,尤其是Magpie和X-Trace,但是我们之所以能成功应用在生产环境上,还需要一些画龙点睛之笔,例如采样率的使用以及把代码植入限制在一小部分公共库的改造上。)
二、设计思路
系统是演进的。先满足最小化跟踪。先满足核心调用链跟踪。并只做一件事,如实记录发生时间。
1、核心数据模型字段
tracerNo:全栈跟踪唯一ID(UUID)
serialNo:当前节点跟踪序号(比如上述图的0.1.1等)
上述两个参数为透传系统参数,后续嵌入跟踪系统,需要设置此参数以便处理。
2、参数透传说明
透传需要传递最后一个节点的上述两个字段参数,保证后续serialNo的正确性,连续性。
3、日志格式(举例子)
alipay_tracer_log|ad7d8e36-f032-4e63-9eb7-b49ef39a2c29|0|WEB|ali_box|http://172.30.0.81:8080/TestRedis/session|1449621713215|1449621716120|
alipay_tracer_log|ad7d8e36-f032-4e63-9eb7-b49ef39a2c29|0.1|DUBBO_C|test-redis|null|1449621715234|1449621716119|
alipay_tracer_log|ad7d8e36-f032-4e63-9eb7-b49ef39a2c29|0.1|DUBBO_S|test_Tracer|null|1449650158205|1449650158206|
即按下述格式:alipay_tracer_log|tracerNo|serialNo|tracerType|name|url|startTime|endTime|params
解释如下:alipay_tracer_log|唯一跟踪ID|当前节点序号|跟踪类型|名称|URL|开始时间|结束时间|相关附带参数
其中alipay_tracer_log 为大数据平台标识头。params 为添加进去的附带参数。
4、链路性能指标(处理时间)
整条调用链跟踪下来,计算总耗时:
1、300毫秒以下正常
2、300—500毫秒(语句调优)
3、500—1000毫秒(模块重构)
4、1000—3000毫秒(系统重构)
5、3000毫秒以上(考虑重写)
三、先决条件
JAVA语言系统。后续扩展其他语言系统。
1、Web Servlet Filter 调用链开始
基础库已实现。
2、Dubbo作为RPC 调用链跟踪
基础库已实现。
3、DB调用跟踪
(主流两种ORM框架实现,Hibernate,Mybatis;其他暂未)
4、Cache调用跟踪
(待实现)
5、MQ调用跟踪
(待实现)
四、系统对接步骤
1、引入相关JAR包
a>大数据平台日志接入JAR包。详见(大数据平台日志接入指南)
1 2 3 4 5 6 7 8 9 10 | < dependency > < groupId>com. alipay</groupId > < artifactId >logback-flume-appender</ artifactId > < version >1.0.0</ version > </ dependency > < dependency > < groupId >org.apache.flume</ groupId > < artifactId >flume-ng-sdk</ artifactId > < version >1.6.0</ version > </ dependency > |
b>基础库相关JAR包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | < dependency > < groupId>com. alipay.base</groupId > < artifactId> alipay-base-common</artifactId > < version >0.0.1-SNAPSHOT</ version > </ dependency > < dependency > < groupId>com. alipay.base</groupId > < artifactId> alipay-base-dao</artifactId > < version >0.0.1-SNAPSHOT</ version > </ dependency > < dependency > < groupId>com. alipay.base</groupId > < artifactId> alipay-base-web</artifactId > < version >0.0.1-SNAPSHOT</ version > </ dependency > |
其中,alipay-base-common 为必须依赖包,其他两个根据跟踪类型,选择性加入。
2、定义logger
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | < appender name = "log_to_flume_tracer" class = "com.gilt.logback.flume.FlumeLogstashV1Appender" > < flumeAgents > 172.16.4.145:5070 </ flumeAgents > < flumeProperties > connect-timeout=4000; request-timeout=8000 </ flumeProperties > < reporterMaxThreadPoolSize >6</ reporterMaxThreadPoolSize > <!--线程池数量 --> < reporterMaxQueueSize >100</ reporterMaxQueueSize > < batchSize >100</ batchSize > <!-- 最大发送数量 --> < reportingWindow >10</ reportingWindow > <!-- 发送时间间隔 --> < additionalAvroHeaders > <!--可选,可以不设置 --> logType=log-type </ additionalAvroHeaders > < application >smapleapp</ application > < layout class = "ch.qos.logback.classic.PatternLayout" > < pattern >%msg%n</ pattern > </ layout > </ appender > < logger name ="com. alipay.base.tracer.Node" level = "INFO" additivity = "false" > < appender-ref ref = "log-to-flume-tracer" /> </ logger > |
3、引入拦截调用链
1、引入filter,web.xml文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | < filter > < filter-name >tracerFilter</ filter-name > < filter-class>com. alipay.base.web.filter.TracerFilter</filter-class > < init-param > < param-name >appName</ param-name > < param-value >cash_box</ param-value > </ init-param > < init-param > < param-name >staticResourceSuffix</ param-name > < param-value >js,css,png,jpg,jpeg,gif</ param-value > </ init-param > </ filter > < filter-mapping > < filter-name >tracerFilter</ filter-name > < url-pattern >/*</ url-pattern > </ filter-mapping > |
2、引入dubbo,filter;一般在application-dubbo-client.xml或是application-dubbo-server.xml;找到定义的地方即可。
1 2 3 4 | <!--<dubbo:reference filter="tracerClientFilter" />--> <!-- 消费方调用过程拦截 --> < dubbo:consumer filter = "tracerClientFilter" /> <!-- 消费方调用过程缺省拦截器,将拦截所有reference --> <!--<dubbo:service filter="tracerServerFilter" />--> <!-- 提供方调用过程拦截 --> < dubbo:provider filter = "tracerServerFilter" /> <!-- 提供方调用过程缺省拦截器,将拦截所有service --> |
3、引入ORM,Interceptor
a>Hibernate引入下述配置(一般在hibernate-config.xml)
1 2 3 4 5 6 7 8 | < bean id = "tracerInterceptor" class ="com. alipay.base.dao.hibernate.interceptor.TracerInterceptor"/> < bean id = "sessionFactory" class = "org.springframework.orm.hibernate4.LocalSessionFactoryBean" > < property name = "dataSource" > < ref local = "dataSource_jdbc" /> </ property > < property name = "entityInterceptor" ref = "tracerInterceptor" /> .............. </ bean > |
b>Mybatis引入下述配置(一般在mybatis-config.xml)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | < configuration > < settings > <!-- changes from the defaults --> < setting name = "lazyLoadingEnabled" value = "false" /> <!-- JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER --> < setting name = "jdbcTypeForNull" value = "NULL" /> < setting name = "defaultStatementTimeout" value = "30" /> </ settings > < plugins > < plugin interceptor ="com. alipay.base.dao.mybatis.interceptor.TracerInterceptor"> </ plugin > </ plugins > <!-- <mappers> <mapper resource="mapper/*Mapper.xml"/> </mappers> --> </ configuration > |
五、遗留问题
1、异步传递
异步请求转发调用跟踪;
2、并发访问
并发访问跟踪节点对象等;
3、其他