zipkin 下载

前往 zipkin 官网下载最新版的ZipKin Jar包

zipkin 内存存储版 启动

nohup java -jar zipkin-server-1.23.0.jar &

可以 使用命令 lsof -i:9411 在终端 查看是否启动成功

至浏览器 输入链接 打开 zipkin 网页

zipkin 配置 MySQL

  1. 需要本机启动MySQL 服务 service mysqld start
  2. 在 MySQL 中建表
CREATE SCHEMA `wjb_monitor` ;

CREATE TABLE IF NOT EXISTS zipkin_spans (
  `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` BIGINT NOT NULL,
  `id` BIGINT NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `parent_id` BIGINT,
  `debug` BIT(1),
  `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
  `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';

CREATE TABLE IF NOT EXISTS zipkin_annotations (
  `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
  `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
  `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
  `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
  `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
  `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
  `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
  `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';

CREATE TABLE IF NOT EXISTS zipkin_dependencies (
  `day` DATE NOT NULL,
  `parent` VARCHAR(255) NOT NULL,
  `child` VARCHAR(255) NOT NULL,
  `call_count` BIGINT
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);

zipkin MYSQL 存储版 启动

STORAGE_TYPE=mysql MYSQL_HOST=127.0.0.1 MYSQL_TCP_PORT=3306 MYSQL_DB=wjb_monitor MYSQL_USER=root MYSQL_PASS=o nohup java -jar zipkin-server-1.23.0.jar &

可以 使用命令 lsof -i:9411 在终端 查看是否启动成功

至浏览器 输入链接 打开 zipkin 网页

zipkin 开发过程

  1. 添加依赖项

         <dependency>
             <groupId>io.zipkin.brave</groupId>
             <artifactId>brave-core</artifactId>
             <version>3.11.1</version>
         </dependency>
    
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
             <version>1.7.21</version>
         </dependency>
    
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <version>19.0</version>
         </dependency>
    
         <dependency>
             <groupId>com.google.auto.value</groupId>
             <artifactId>auto-value</artifactId>
             <version>1.1</version>
         </dependency>
    
         <!-- yaml config -->
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
             <version>1.11</version>
         </dependency>
    
         <!-- for kafka collector -->
         <dependency>
             <groupId>org.apache.kafka</groupId>
             <artifactId>kafka-clients</artifactId>
             <version>0.10.0.0</version>
             <scope>provided</scope>
         </dependency>
    
  2. 在工程 resources/META-INF/dubbo 文件夹下,新建文件 com.alibaba.dubbo.rpc.Filter 主要用于 dubbo在调用中产生拦截 文件内容如下:

    TraceConsumerFilter=com.monitor.client.trace.filter.TraceConsumerFilter
    TraceProviderFilter=com.monitor.client.trace.filter.TraceProviderFilter
    
  3. 第二步 文件中所对应的三个核心类 分别是 TraceFilter、TraceConsumerFilter、TraceProviderFilter,其作用是在调用中产生拦截。 在这三个核心类中,都会读取 resources/trace.yml 文件。 文件中 主要配置 此工程在 zipkin 中的服务器信息,名称,作者,以及调用链的URL 根信息。

  4. ZipKin 的数据模型

    • Trace:标识整个请求链,即一些列Span的组合。其自身的ID将贯穿整个调用链,其中的每个Span都必须携带这个traceId,因此traceId将在整个调用链中传递;
    • Span: 标识一次分布式调用,其自身包含了id,parentId(指向上级Span的id), traceIds,服务名称等重要属性,其应尽量保持精简;
    • annotation:包括一个值,时间戳,主机名(留痕迹)。
      • traceId:就是一个全局的跟踪ID,是跟踪的入口点,根据需求来决定在哪生成traceId。比如一个http请求,首先入口是web应用,一般看完整的调用链这里自然是traceId生成的起点,结束点在web请求返回点。
      • spanId:这是下一层的请求跟踪ID,这个也根据自己的需求,比如认为一次rpc,一次sql执行等都可以是一个span。一个traceId包含一个以上的spanId。
      • parentId:上一次请求跟踪ID,用来将前后的请求串联起来。
      • cs:客户端发起请求的时间,比如dubbo调用端开始执行远程调用之前。
      • cr:客户端收到处理完请求的时间。
      • ss:服务端处理完逻辑的时间。
      • sr:服务端收到调用端请求的时间。
    • 客户端调用时间=cr-cs
    • 服务端处理时间=sr-ss
  1. 工程其余的类目都是围绕着这三个核心类去操作的。 在进行 Http 请求的时候,通过TraceAgent类进行生成一个调用控制器,由于考虑到会扩展到多种日志收集器,所以用代理做封装,其核心功能就是将数据通过http传送到zipkin,由此在每次调用开始时生成一个调用关系模型,存放进 TraceContext 中,在 TraceConsumerFilterinvke 方法中 判断 TraceContext.getTraceId() == null 来判断 是否为 根调用。

zipkin 集成进工程

  1. pom.xml 文件中添加如下依赖:

     <dependency>
       <groupId>wangjubao.monitoring</groupId>
       <artifactId>monitor-client</artifactId>
       <version>1.3-SNAPSHOT</version>
     </dependency>
    
  2. spring xml 配置文件(dubbo 配置)

    1. 添加以下代码:

           <import resource="classpath*:spring/spring_monitor_client.xml"/>
           <dubbo:application name="test_consumer" />
           <dubbo:registry address="zookeeper://106.15.46.228:2181"  protocol="zookeeper"/>
      
    2. 删除以下代码:(在以上文件中集中配置)

          <dubbo:provider timeout="10000" retries="3" …… />
      <dubbo:consumer …… />
          <dubbo:monitor protocol="registry"/>
      
    3. 在 resources 文件夹下, 新建 trace.yml 文件

      ### 以下为Provider Consumer Web 层 工程都需要配置的基础信息
      
      # 此项目是否需要进行调用链记录
      enable: true
      
      # 调用链服务器地址(一般与监控地址相同,端口为 9411, 正式工程 配置地址为:121.40.32.163:9411
      server: 'localhost:9411'
      
      # 此 APP 工程名 - 请保持与 Dubbo 服务名相同,以方便监控
      name: 'myapp'
      
      # 此APP 负责人 - 请填写这个服务的负责人
      owner: 'kevin'
      
      ### 以下为 Web 层 工程需要配置的独立基础信息
      # 调用链定义需要的跟踪的请求节点
      points:
      
         - key: user.login #节点名
         pattern: ^/api/users/.* #节点路径
         desc: 用户登陆 #节点描述
      
         - key: order.create
         pattern: ^/.* #此 web 工程下所有请求全部跟踪
         desc: 用户下单
      
  3. web 工程中还需在 web.xml 中配置一下如下filter,用于拦截生成调用链

       <filter>
         <filter-name>traceFilter</filter-name>
         <filter-class>com.monitor.client.trace.filter.TraceFilter</filter-class>
       </filter>
    
       <filter-mapping>
            <filter-name>traceFilter</filter-name>
         <url-pattern>/*</url-pattern>
       </filter-mapping>
    

    summary: 配置文件中 关于dubbo 的配置 除了 服务消费者和提供者Bean的配置 以及 工程监控导入配置的代码,仅保留以下两行代码

     ```xml
         <!-- Dubbo通用配置以及监控配置 -->
         <import resource="classpath*:spring/spring_monitor_client.xml"/>
         <!-- 提供方应用信息,用于计算依赖关系 -->
         <dubbo:application name="test_provider_pro" />
         <dubbo:registry address="zookeeper://106.15.46.228:2181"  protocol="zookeeper"/>
     ```
    

查看 zipkin

在 浏览器 输入 http://localhost:9411 如果产生调用,即可查看到调用链的信息。

调用链流程解读

  1. 如上所述,监控的调用链模块分为三个核心类 TraceFilter、TraceConsumerFilter、TraceProviderFilter。
  2. TractFilter 可以在Web应用层初始化整个调用链,包括traceId,rootSpanId等重要信息,对于ID,我们根据自己的规则去生成。
  3. 由于需要在整个请求链中共享traceId及父级spanId,因此将其放入ThreadLocal上下文。既然已经初始化了rootSpan,接下来我们还需要将这里的traceId和spanId传递给后端的dubbo服务,这可以通过在dubbo提供的Filter(TraceConsumerFilter、TraceProviderFilter)中的attachment中设置。
  4. 这样在provider端就能获取到当前traceId和spanId,由于在provider端仍然还有可能调用其他dubbo服务,因此provider端接收到consumer传递的traceId和spanId后,还需要将其设置在ThreadLocal中,以便后续的dubbo服务调用中也需要传递traceId和spanId。
  5. 这样,当在前端发起请求后,则会在跟踪服务器生成对应的跟踪记录

异常监控接入流程

  1. pom.xml 中引入 网聚宝 监控客户端,如果引用过了,请注意重新build下。
     <dependency>
       <groupId>wangjubao.monitoring</groupId>
       <artifactId>monitor-client</artifactId>
       <version>1.3-SNAPSHOT</version>
     </dependency>
    
  2. log4j.xml 中加入如下 配置

     <!-- 阿里云监控日志 -->
     <appender name="loghub" class="com.aliyun.openservices.log.log4j.LoghubAppender">
         <!-- 注意:以下 ${} 引用变量的值 请找架构组相关人员提供 -->
         <param name="projectName" value="${projectName}" />
         <param name="logstore" value="${logstore}" />
         <param name="endpoint" value="${endpoint}" />
         <param name="accessKeyId" value="${accessKeyId}"/>
         <param name="accessKey" value="${accessKey}"/>
         <param name="topic" value="${your dubbo application name}"/>
         <param name="packageTimeoutInMS" value="3000"/>
         <param name="logsCountPerPackage" value="4096"/>
         <param name="logsBytesPerPackage" value="5242880"/>
         <param name="memPoolSizeInByte" value="1048576000"/>
         <param name="ioThreadsCount" value="1"/>
         <param name="timeFormat" value="yyyy-MM-dd HH:mm:ss"/>
         <param name="timeZone" value="GMT+8"/>   
     </appender>
    
     <logger name="loghub" additivity="false">
         <level value="INFO" />
         <appender-ref ref="loghub" />
     </logger>
    
     <root>
         <level value="WARN" />
         <appender-ref ref="loghub" />
     </root>
    
  3. 在 服务启动的 main 函数中第一行调用如下方法
     ExceptionHandler.startupExcetpionHandler();
    

发布提交代码监控接入流程

  1. code.aliyun.com 对应的 Git 项目中,将 网聚宝公司账户 加入此项目(如使用公司账户创建项目的,忽略此条)
  2. code.aliyun.com 对应的 Git 项目中,打开侧边栏 Settings - WebHooks ,添加以下 URL(IP 地址请架构组相关人员提供),点击 ADD WEB HOOK
     http://<!--IP Address-->/monitor-server-1.0-SNAPSHOT/monitor/devops/postGitWebHook
    
    WebHooks 设置

数据库监控接入流程

  1. pom.xml 中引入 网聚宝 监控客户端,如果引用过了,请注意重新build下。
     <dependency>
       <groupId>wangjubao.monitoring</groupId>
       <artifactId>monitor-client</artifactId>
       <version>1.3-SNAPSHOT</version>
     </dependency>
    
  2. mybatis-config.xml 中添加

     <configuration>
    
         <plugins>
             ...
             <plugin interceptor="com.monitor.client.database.SqlCostInterceptor" />
         </plugins>
     </configuration>
    
  3. log4j.xml 中加入如下 配置 (ps. 如果在异常接入中已添加,请忽略)

     <!-- 阿里云监控日志 -->
     <appender name="loghub" class="com.aliyun.openservices.log.log4j.LoghubAppender">
         <!-- 注意:以下 ${} 引用变量的值 请找架构组相关人员提供 -->
         <param name="projectName" value="${projectName}" />
         <param name="logstore" value="${logstore}" />
         <param name="endpoint" value="${endpoint}" />
         <param name="accessKeyId" value="${accessKeyId}"/>
         <param name="accessKey" value="${accessKey}"/>
         <param name="topic" value="${your dubbo application name}"/>
         <param name="packageTimeoutInMS" value="3000"/>
         <param name="logsCountPerPackage" value="4096"/>
         <param name="logsBytesPerPackage" value="5242880"/>
         <param name="memPoolSizeInByte" value="1048576000"/>
         <param name="ioThreadsCount" value="1"/>
         <param name="timeFormat" value="yyyy-MM-dd HH:mm:ss"/>
         <param name="timeZone" value="GMT+8"/>   
     </appender>
    
     <logger name="loghub" additivity="false">
         <level value="INFO" />
         <appender-ref ref="loghub" />
     </logger>
    
     <root>
         <level value="WARN" />
         <appender-ref ref="loghub" />
     </root>
    
  4. [如已经配置发布提交代码监控,请忽略4 、 5 两条配置]code.aliyun.com 对应的 Git 项目中,将 网聚宝公司账户 加入此项目(如使用公司账户创建项目的,忽略此条)
  5. code.aliyun.com 对应的 Git 项目中,打开侧边栏 Settings - WebHooks ,添加以下 URL(IP 地址请架构组相关人员提供),点击 ADD WEB HOOK
         http://<!--IP Address-->/monitor-server-1.0-SNAPSHOT/monitor/devops/postGitWebHook
    
    WebHooks 设置