系统设计之----分布式跟踪系统

时间:2021-08-16 22:31:59
    • 一、设计依据
    • 二、设计思路
      • 1、核心数据模型字段
      • 2、参数透传说明
      • 3、日志格式(举例子)
      • 4、链路性能指标(处理时间)
    • 三、先决条件
      • 1、Web Servlet Filter 调用链开始
      • 2、Dubbo作为RPC 调用链跟踪
      • 3、DB调用跟踪
      • 4、Cache调用跟踪
      • 5、MQ调用跟踪
    • 四、系统对接步骤
      • 1、引入相关JAR包
      • 2、定义logger
      • 3、引入拦截调用链
    • 五、遗留问题
      • 1、异步传递
      • 2、并发访问
      • 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、日志格式(举例子)

iboxpay_tracer_log|ad7d8e36-f032-4e63-9eb7-b49ef39a2c29|0|WEB|cash_box|http://172.30.0.81:8080/TestRedis/session|1449621713215|1449621716120|


iboxpay_tracer_log|ad7d8e36-f032-4e63-9eb7-b49ef39a2c29|0.1|DUBBO_C|test-redis|null|1449621715234|1449621716119|

 

iboxpay_tracer_log|ad7d8e36-f032-4e63-9eb7-b49ef39a2c29|0.1|DUBBO_S|test_Tracer|null|1449650158205|1449650158206|

即按下述格式:iboxpay_tracer_log|tracerNo|serialNo|tracerType|name|url|startTime|endTime|params

解释如下:iboxpay_tracer_log|唯一跟踪ID|当前节点序号|跟踪类型|名称|URL|开始时间|结束时间|相关附带参数

其中iboxpay_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.iboxpay</ 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.iboxpay.base</ groupId >
         < artifactId >iboxpay-base-common</ artifactId >
         < version >0.0.1-SNAPSHOT</ version >
     </ dependency >
     < dependency >
         < groupId >com.iboxpay.base</ groupId >
         < artifactId >iboxpay-base-dao</ artifactId >
         < version >0.0.1-SNAPSHOT</ version >
     </ dependency >
      < dependency >
         < groupId >com.iboxpay.base</ groupId >
         < artifactId >iboxpay-base-web</ artifactId >
         < version >0.0.1-SNAPSHOT</ version >
     </ dependency >

其中,iboxpay-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.iboxpay.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.iboxpay.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.iboxpay.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.iboxpay.base.dao.mybatis.interceptor.TracerInterceptor" >
     </ plugin >
   </ plugins >
   <!-- <mappers>
     <mapper resource="mapper/*Mapper.xml"/>
   </mappers> -->
</ configuration >

五、遗留问题

1、异步传递

异步请求转发调用跟踪;

2、并发访问

并发访问跟踪节点对象等;

3、其他