天天看点

Zipkin存储Sleuth信息实现调用链追踪的几种方法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/alva_xu/article/details/84648249

</div>
                                                <!--一个博主专栏付费入口-->
                      <!--一个博主专栏付费入口结束-->
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-833878f763.css">
                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-833878f763.css">
            <div class="htmledit_views" id="content_views">
                                        <h2>一、基本概念</h2>
           

大家知道,对于分布式应用系统,特别是微服务应用,服务之间的调用链跟踪是极其重要的。在Springcloud的微服务框架中提供了Springcloud Sleuth结合Zipkin的调用链跟踪方案,其理论基础主要来自于 Google 的一篇论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》

Spring Cloud Sleuth为服务之间调用提供链路追踪。通过Sleuth可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。从而让我们可以很方便的理清各微服务间的调用关系。

Sleuth还可以帮助我们进行:

  • 耗时分析: 通过Sleuth可以很方便的了解到每个采样请求的耗时,从而分析出哪些服务调用比较耗时;
  • 可视化错误: 对于程序未捕捉的异常,可以通过集成Zipkin服务界面上看到;
  • 链路优化: 对于调用比较频繁的服务,可以针对这些服务实施一些优化措施。

而zipkin可以收集Sleuth的采样数据,利用zipkin的存储来存储信息,利用zipkin ui来展示数据。根据其官方文档https://zipkin.io/pages/architecture.html?from=singlemessage&isappinstalled=0,其架构如下,

Zipkin存储Sleuth信息实现调用链追踪的几种方法

其中四个组件的作用如下

Zipkin Collector

Once the trace data arrives at the Zipkin collector daemon, it is validated, stored, and indexed for lookups by the Zipkin collector.

Storage

Zipkin was initially built to store data on Cassandra since Cassandra is scalable, has a flexible schema, and is heavily used within Twitter. However, we made this component pluggable. In addition to Cassandra, we natively support ElasticSearch and MySQL. Other back-ends might be offered as third party extensions.

Zipkin Query Service

Once the data is stored and indexed, we need a way to extract it. The query daemon provides a simple JSON API for finding and retrieving traces. The primary consumer of this API is the Web UI.

Web UI

We created a GUI that presents a nice interface for viewing traces. The web UI provides a method for viewing traces based on service, time, and annotations. Note: there is no built-in authentication in the UI!

其中最重要的collector的工作原理如下

  1. ───────┐ ┌───────────────────────┐ ┌─────────────┐ ┌──────────────────┐
  2. │ User Code │ │ Trace Instrumentation │ │ Http Client │ │ Zipkin Collector │
  3. └─────────────┘ └───────────────────────┘ └─────────────┘ └──────────────────┘
  4. │ │ │ │
  5. ┌─────────┐
  6. │ ──┤GET /foo ├─▶ │ ────┐ │ │
  7. └─────────┘ │ record tags
  8. │ │ ◀───┘ │ │
  9. ────┐
  10. │ │ │ add trace headers │ │
  11. ◀───┘
  12. │ │ ────┐ │ │
  13. │ record timestamp
  14. │ │ ◀───┘ │ │
  15. ┌─────────────────┐
  16. │ │ ──┤GET /foo ├─▶ │ │
  17. │X-B3-TraceId: aa │ ────┐
  18. │ │ │X-B3-SpanId: 6b │ │ │ │
  19. └─────────────────┘ │ invoke
  20. │ │ │ │ request │
  21. │ │ │ │ │
  22. ┌────────┐ ◀───┘
  23. │ │ ◀─────┤200 OK ├─────── │ │
  24. ────┐ └────────┘
  25. │ │ │ record duration │ │
  26. ┌────────┐ ◀───┘
  27. │ ◀──┤200 OK ├── │ │ │
  28. └────────┘ ┌────────────────────────────────┐
  29. │ │ ──┤ asynchronously report span ├────▶ │
  30. │ │
  31. │{ │
  32. │ "traceId": "aa", │
  33. │ "id": "6b", │
  34. │ "name": "get", │
  35. │ "timestamp": 1483945573944000,│
  36. │ "duration": 386000, │
  37. │ "annotations": [ │
  38. │--snip-- │
  39. └────────────────────────────────┘

本文通过示例来介绍Zipkin存储和展示Sleuth数据的几种方式

二、示例环境介绍

在搭建zipkin server前,我们先写了以下几个服务

Zipkin存储Sleuth信息实现调用链追踪的几种方法

1,SERVICE-HI

通过访问http://localhost:8081/hi?name=aaa和http://localhost:8082/hi?name=aaa

返回 hi aaa,i am from port:8081 和hi aaa,i am from port:8082

2,SERVICE-RIBBON

通过访问http://localhost:8010/ribbon?name=xuwh 来实现ribbon的load balance功能,依次调用SERVICE-HI 服务的8081和8082端口

3,SERVICE-FEIGN-HYSTRIX

通过访问http://localhost:8020/feign?name=xuwh来实现feign的load balance功能,依次调用SERVICE-HI 服务的8081和8082端口

4,SERVICE-ZUUL

通过访问http://localhost:8040/feign/feign?name=xuwh和http://localhost:8040/feign/feign?name=xuwh来实现Zuul的路由功能

服务之间的访问链路如下图

Zipkin存储Sleuth信息实现调用链追踪的几种方法

三、通过http调用直接在zipkin UI 上显示调用链的配置方法

该方法实际上就是Collector直接通过http的方式收集信息,Zipkin UI读取collector的信息,并展示,信息不落地到数据库。需要改造Zipkin Client(即被监控服务)的配置和Zipkin Server的配置。

Zipkin存储Sleuth信息实现调用链追踪的几种方法

1,Zipkin server服务

(1)zipkin-server服务源码

  1. package jar;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  5. import zipkin.server.EnableZipkinServer;
  6. @SpringBootApplication
  7. @EnableEurekaClient
  8. @EnableZipkinServer
  9. public class ZipkinServerApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(ZipkinServerApplication.class, args);
  12. }
  13. }

(2)配置application.yml

  1. server:
  2. port: 9411
  3. spring:
  4. application:
  5. name: zipkin-server
  6. eureka:
  7. client:
  8. service-url:
  9. defaultZone: http://localhost:8761/eureka/

(3)pom.xml 加依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.svw</groupId>
  6. <artifactId>zipkin-server</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <packaging>jar</packaging>
  9. <name>zipkin-server</name>
  10. <description>Demo project for Spring Boot</description>
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>1.5.6.RELEASE</version>
  15. <relativePath/> <!-- lookup parent from repository -->
  16. </parent>
  17. <properties>
  18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  20. <java.version>1.8</java.version>
  21. <spring-cloud.version>Dalston.SR3</spring-cloud.version>
  22. </properties>
  23. <dependencies>
  24. <dependency>
  25. <groupId>org.springframework.cloud</groupId>
  26. <artifactId>spring-cloud-starter-eureka</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>io.zipkin.java</groupId>
  30. <artifactId>zipkin-server</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>io.zipkin.java</groupId>
  34. <artifactId>zipkin-autoconfigure-ui</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-test</artifactId>
  39. <scope>test</scope>
  40. </dependency>
  41. </dependencies>
  42. <dependencyManagement>
  43. <dependencies>
  44. <dependency>
  45. <groupId>org.springframework.cloud</groupId>
  46. <artifactId>spring-cloud-dependencies</artifactId>
  47. <version>${spring-cloud.version}</version>
  48. <type>pom</type>
  49. <scope>import</scope>
  50. </dependency>
  51. </dependencies>
  52. </dependencyManagement>
  53. <build>
  54. <plugins>
  55. <plugin>
  56. <groupId>org.springframework.boot</groupId>
  57. <artifactId>spring-boot-maven-plugin</artifactId>
  58. </plugin>
  59. </plugins>
  60. </build>
  61. </project>

这里最重要的是引入zipkin-server依赖,以及zipkin-autoconfigure-ui依赖

  1. <dependency>
  2. <groupId>io.zipkin.java</groupId>
  3. <artifactId>zipkin-server</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>io.zipkin.java</groupId>
  7. <artifactId>zipkin-autoconfigure-ui</artifactId>
  8. </dependency>

2,要跟踪链路的服务的改造(4个服务都要改)

(1)改配置

以SERVICE-ZUUL 为例

  1. server:
  2. port: 8040
  3. spring:
  4. application:
  5. name: service-zuul
  6. zipkin:
  7. base-url: http://localhost:9411
  8. sleuth:
  9. sampler:
  10. percentage: 1.0
  11. eureka:
  12. client:
  13. service-url:
  14. defaultZone: http://localhost:8761/eureka/
  15. zuul:
  16. routes:
  17. user-route1: # 该配置方式中,user-route只是给路由一个名称,可以任意起名。
  18. service-id: SERVICE-FEIGN-HYSTRIX
  19. path: /feign/** # service-id对应的路径
  20. user-route2: # 该配置方式中,user-route只是给路由一个名称,可以任意起名。
  21. service-id: SERVICE-RIBBON
  22. path: /ribbon/** # service-id对应的路径
  23. security:
  24. basic:
  25. enabled: true # 开启基于HTTP basic的认证
  26. user:
  27. name: xuwh # 配置登录的账号是user
  28. password: password123 # 配置登录的密码是password123

在application.yml中增加了这几行配置

  1. zipkin:
  2. base-url: http://localhost:9411
  3. sleuth:
  4. sampler:
  5. percentage: 1.0

(2)加依赖

在pom.xml中增加以下依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-zipkin</artifactId>
  4. </dependency>

3,启动各个服务,

Zipkin存储Sleuth信息实现调用链追踪的几种方法

4,并对各个服务进行web访问操作,在调试中发现,由于增加了系统采样,SERVICE-ZUUL在调用其他服务的时候,由于超时,而我们又没定义超时熔断服务,所以会调用不成功,console报错如下

  1. com.netflix.zuul.exception.ZuulException: Forwarding error
  2. at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:188) ~[spring-cloud-netflix-core-1.3.4.RELEASE.jar:1.3.4.RELEASE]
  3. at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:163) ~[spring-cloud-netflix-core-1.3.4.RELEASE.jar:1.3.4.RELEASE]
  4. at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:111) ~[spring-cloud-netflix-core-1.3.4.RELEASE.jar:1.3.4.RELEASE]
  5. at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) ~[zuul-core-1.3.0.jar:1.3.0]
  6. at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193) ~[zuul-core-1.3.0.jar:1.3.0]
  7. at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157) ~[zuul-core-1.3.0.jar:1.3.0]
  8. at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:118) ~[zuul-core-1.3.0.jar:1.3.0]
  9. at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:96) ~[zuul-core-1.3.0.jar:1.3.0]
  10. at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:116) ~[zuul-core-1.3.0.jar:1.3.0]
  11. at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:81) ~[zuul-core-1.3.0.jar:1.3.0]
  12. at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:157) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  13. at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequest(ZuulController.java:44) [spring-cloud-netflix-core-1.3.4.RELEASE.jar:1.3.4.RELEASE]
  14. at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  15. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  16. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  17. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  18. at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  19. at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.16.jar:8.5.16]
  20. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  21. at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.16.jar:8.5.16]
  22. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.16.jar:8.5.16]
  23. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  24. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.16.jar:8.5.16]
  25. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  26. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  27. at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
  28. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  29. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  30. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  31. at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) [spring-boot-actuator-1.5.6.RELEASE.jar:1.5.6.RELEASE]
  32. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  33. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  34. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  35. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  36. at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  37. at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  38. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  39. at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  40. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  41. at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  42. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  43. at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  44. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  45. at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  46. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  47. at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  48. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  49. at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:215) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  50. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  51. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  52. at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  53. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  54. at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  55. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  56. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  57. at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  58. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  59. at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  60. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  61. at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  62. at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  63. at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  64. at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  65. at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  66. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  67. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  68. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  69. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  70. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  71. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  72. at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  73. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  74. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  75. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  76. at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  77. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  78. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  79. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  80. at org.springframework.cloud.sleuth.instrument.web.TraceFilter.doFilter(TraceFilter.java:169) [spring-cloud-sleuth-core-1.2.4.RELEASE.jar:1.2.4.RELEASE]
  81. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  82. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  83. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  84. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  85. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  86. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  87. at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) [spring-boot-actuator-1.5.6.RELEASE.jar:1.5.6.RELEASE]
  88. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
  89. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
  90. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
  91. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.16.jar:8.5.16]
  92. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar:8.5.16]
  93. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar:8.5.16]
  94. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar:8.5.16]
  95. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
  96. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
  97. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
  98. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
  99. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
  100. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
  101. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
  102. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
  103. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
  104. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
  105. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
  106. at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
  107. Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: SERVICE-FEIGN-HYSTRIX timed-out and no fallback available.
  108. at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:819) ~[hystrix-core-1.5.12.jar:1.5.12]
  109. at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:804) ~[hystrix-core-1.5.12.jar:1.5.12]
  110. at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140) ~[rxjava-1.1.10.jar:1.1.10]
  111. at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
  112. at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
  113. at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1472) ~[hystrix-core-1.5.12.jar:1.5.12]
  114. at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1397) ~[hystrix-core-1.5.12.jar:1.5.12]
  115. at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
  116. at rx.observers.Subscribers$5.onError(Subscribers.java:230) ~[rxjava-1.1.10.jar:1.1.10]
  117. at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44) ~[rxjava-1.1.10.jar:1.1.10]
  118. at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28) ~[rxjava-1.1.10.jar:1.1.10]
  119. at rx.Observable.unsafeSubscribe(Observable.java:10211) ~[rxjava-1.1.10.jar:1.1.10]
  120. at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51) ~[rxjava-1.1.10.jar:1.1.10]
  121. at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.1.10.jar:1.1.10]
  122. at rx.Observable.unsafeSubscribe(Observable.java:10211) ~[rxjava-1.1.10.jar:1.1.10]
  123. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) ~[rxjava-1.1.10.jar:1.1.10]
  124. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  125. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.1.10.jar:1.1.10]
  126. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  127. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.1.10.jar:1.1.10]
  128. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  129. at rx.Observable.unsafeSubscribe(Observable.java:10211) ~[rxjava-1.1.10.jar:1.1.10]
  130. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) ~[rxjava-1.1.10.jar:1.1.10]
  131. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  132. at rx.Observable.unsafeSubscribe(Observable.java:10211) ~[rxjava-1.1.10.jar:1.1.10]
  133. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) ~[rxjava-1.1.10.jar:1.1.10]
  134. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  135. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.1.10.jar:1.1.10]
  136. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  137. at rx.Observable.unsafeSubscribe(Observable.java:10211) ~[rxjava-1.1.10.jar:1.1.10]
  138. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) ~[rxjava-1.1.10.jar:1.1.10]
  139. at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  140. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.1.10.jar:1.1.10]
  141. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.1.10.jar:1.1.10]
  142. at rx.Observable.unsafeSubscribe(Observable.java:10211) ~[rxjava-1.1.10.jar:1.1.10]
  143. at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:142) ~[rxjava-1.1.10.jar:1.1.10]
  144. at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
  145. at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
  146. at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1$1.run(AbstractCommand.java:1154) ~[hystrix-core-1.5.12.jar:1.5.12]
  147. at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:45) ~[hystrix-core-1.5.12.jar:1.5.12]
  148. at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41) ~[hystrix-core-1.5.12.jar:1.5.12]
  149. at org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixConcurrencyStrategy$HystrixTraceCallable.call(SleuthHystrixConcurrencyStrategy.java:188) ~[spring-cloud-sleuth-core-1.2.4.RELEASE.jar:1.2.4.RELEASE]
  150. at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:61) ~[hystrix-core-1.5.12.jar:1.5.12]
  151. at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.tick(AbstractCommand.java:1159) ~[hystrix-core-1.5.12.jar:1.5.12]
  152. at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:99) ~[hystrix-core-1.5.12.jar:1.5.12]
  153. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_131]
  154. at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[na:1.8.0_131]
  155. at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_131]
  156. at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[na:1.8.0_131]
  157. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
  158. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
  159. ... 1 common frames omitted
  160. Caused by: java.util.concurrent.TimeoutException: null
  161. at com.netflix.hystrix.AbstractCommand.handleTimeoutViaFallback(AbstractCommand.java:997) ~[hystrix-core-1.5.12.jar:1.5.12]
  162. at com.netflix.hystrix.AbstractCommand.access$500(AbstractCommand.java:60) ~[hystrix-core-1.5.12.jar:1.5.12]
  163. at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:610) ~[hystrix-core-1.5.12.jar:1.5.12]
  164. at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:601) ~[hystrix-core-1.5.12.jar:1.5.12]
  165. at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140) ~[rxjava-1.1.10.jar:1.1.10]
  166. ... 16 common frames omitted

故需要在SERVICE-ZUUL 的配置文件application.yml中增加hystrix的超时设置,

  1. hystrix:
  2. command:
  3. default:
  4. execution:
  5. isolation:
  6. thread:
  7. timeoutInMilliseconds: 60000

同样,对SERVICE-FEIGN-HYSTRIX的配置文件application.yml中也增加hystrix的超时设置

5,现在可以对各个服务进行web访问操作了,多次操作,把采样数据送给Zipkin server

6,输入http://localhost:9411/zipkin,打开Zipkin UI

Zipkin存储Sleuth信息实现调用链追踪的几种方法

点击左边红色圈的下拉框,可以列出我们跟踪的4个服务,调整Start time和End time ,再点击Find Traces 可以得到该服务的调用链数据,具体含义在此不做解释了,可以看到,每个服务调用的时长超过了一秒,印证了前面所说要加长服务超时设置。

Zipkin存储Sleuth信息实现调用链追踪的几种方法

点击右上角Dependencies 按钮,可以看到完整的调用链视图

Zipkin存储Sleuth信息实现调用链追踪的几种方法

还可以看到更多的信息

Zipkin存储Sleuth信息实现调用链追踪的几种方法

四、通过RabbitMQ传输数据在zipkin UI 上显示调用链的配置方法

该方法实际上就是Collector直接通过RabbitMQ的方式收集信息,Zipkin UI读取collector的信息,并展示,信息不落地到数据库。需要改造Zipkin Client(即被监控服务)的配置和Zipkin Server的配置。

Zipkin存储Sleuth信息实现调用链追踪的几种方法

以下介绍用rabbitMQ传输数据给zipkin server的方式

1,安装RabbitMQ

这个很简单,参考官方文档安装即可。本人在localhost 的win7上装了一个rabbitmq。并在后台以服务方式运行着。我们需要知道它的端口(默认为5672)、用户名和口令。通过浏览http://localhost:15672/ 浏览可以对RabbitMQ进行管理(默认口令guest/guest)

Zipkin存储Sleuth信息实现调用链追踪的几种方法
Zipkin存储Sleuth信息实现调用链追踪的几种方法
Zipkin存储Sleuth信息实现调用链追踪的几种方法

2,改造zipkin-server

(1)改依赖,在pom.xml中去掉zipkin-server依赖,加上spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit依赖

  1. <!-- <dependency> -->
  2. <!-- <groupId>io.zipkin.java</groupId> -->
  3. <!-- <artifactId>zipkin-server</artifactId> -->
  4. <!-- </dependency> -->
  5. <dependency>
  6. <groupId>io.zipkin.java</groupId>
  7. <artifactId>zipkin-autoconfigure-ui</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
  16. </dependency>

(2)改配置,在application.yml中加上RabbitMQ的配置

  1. spring:
  2. application:
  3. name: zipkin-server
  4. rabbitmq:
  5. host: localhost
  6. port: 5672
  7. username: guest
  8. password: guest

(3)改代码,在主程序ZipkinServerApplication上加@EnableZipkinStreamServer注解,开启ZipkinStreamServer

  1. //@EnableZipkinServer
  2. @EnableZipkinStreamServer

3,改造zipkin Client,对4个服务做以下的操作

(1)改依赖,在pom.xml中将spring-cloud-starter-zipkin改为spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit

  1. <!-- <dependency> -->
  2. <!-- <groupId>org.springframework.cloud</groupId> -->
  3. <!-- <artifactId>spring-cloud-starter-zipkin</artifactId> -->
  4. <!-- </dependency> -->
  5. <dependency>
  6. <groupId>org.springframework.cloud</groupId>
  7. <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.cloud</groupId>
  11. <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
  12. </dependency>
  1. spring:
  2. application:
  3. name: service-feign-hystrix
  4. zipkin:
  5. base-url: http://localhost:9411
  6. rabbitmq:
  7. host: localhost
  8. port: 5672
  9. username: guest
  10. password: guest

(3)代码不用改

4,重启各个服务,并进行访问操作

5,登录RabbitMQ管理界面,可以看到,有数据传输

Zipkin存储Sleuth信息实现调用链追踪的几种方法

6,打开Zipkin-UI ,同样可以看到有数据显示

Zipkin存储Sleuth信息实现调用链追踪的几种方法

五、将数据通过rabbitMQ写入Mysql再在zipkin UI 上显示调用链的配置方法

Zipkin支持Mysql、Elasticsearch、Cassandra等数据库存储,其实现方式很简单,就是把Zip server的存储方式改为相应的数据库存储方式,将原来rabbitMQ传到collector的数据存入相应的数据库,Zipkin UI 读取数据库的数据再展示,目的是让数据持久化。其架构图如图所示。

Zipkin存储Sleuth信息实现调用链追踪的几种方法

本章节介绍数据存入MYSQL的方法。

Zipkin client无需做任何更改,只需配好Mysql数据库和zipkin server即可

1,安装配置mysql,建数据库表,存储sleuth数据

具体如何安装配置mysql,在此不再赘述。我的数据库直接安装在本机。

在Mysql创建数据库`spring_cloud_zipkin`,连接数据库,创建相应对象以存储Sleuth信息。源码参见https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql/src/main/resources/mysql.sql

  1. CREATE TABLE IF NOT EXISTS zipkin_spans (
  2. `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  3. `trace_id` BIGINT NOT NULL,
  4. `id` BIGINT NOT NULL,
  5. `name` VARCHAR(255) NOT NULL,
  6. `parent_id` BIGINT,
  7. `debug` BIT(1),
  8. `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
  9. `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query'
  10. ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
  11. ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';
  12. ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';
  13. ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
  14. ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
  15. ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';
  16. CREATE TABLE IF NOT EXISTS zipkin_annotations (
  17. `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  18. `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
  19. `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
  20. `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
  21. `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
  22. `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
  23. `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
  24. `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
  25. `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
  26. `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
  27. `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
  28. ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
  29. ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
  30. ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
  31. ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
  32. ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
  33. ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces';
  34. ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
  35. ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';
  36. CREATE TABLE IF NOT EXISTS zipkin_dependencies (
  37. `day` DATE NOT NULL,
  38. `parent` VARCHAR(255) NOT NULL,
  39. `child` VARCHAR(255) NOT NULL,
  40. `call_count` BIGINT,
  41. `error_count` BIGINT
  42. ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
  43. ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);

结果如下

  1. C:\Users\91678>mysql -u root -p spring_cloud_zipkin
  2. Enter password: ******
  3. Welcome to the MySQL monitor. Commands end with ; or \g.
  4. Your MySQL connection id is 7
  5. Server version: 5.7.19 MySQL Community Server (GPL)
  6. Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  7. Oracle is a registered trademark of Oracle Corporation and/or its
  8. affiliates. Other names may be trademarks of their respective
  9. owners.
  10. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  11. mysql> show tables;
  12. +-------------------------------+
  13. | Tables_in_spring_cloud_zipkin |
  14. +-------------------------------+
  15. | zipkin_annotations |
  16. | zipkin_dependencies |
  17. | zipkin_spans |
  18. +-------------------------------+
  19. 3 rows in set (0.00 sec)
  20. mysql>

2,改造Zipkin server

(1)加依赖,在POM.XML增加mysql JDBC相关依赖

  1. <dependency>
  2. <groupId>mysql</groupId>
  3. <artifactId>mysql-connector-java</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-jdbc</artifactId>
  8. </dependency>

(2)改配置,增加了DataSource配置和zipkin的storage配置

  1. server:
  2. port: 9411
  3. spring:
  4. application:
  5. name: zipkin-server
  6. rabbitmq:
  7. host: localhost
  8. port: 5672
  9. username: guest
  10. password: guest
  11. datasource:
  12. url: jdbc:mysql://localhost:3306/spring_cloud_zipkin
  13. username: root
  14. password: abc123
  15. driver-class-name: com.mysql.jdbc.Driver
  16. zipkin:
  17. storage:
  18. type: mysql
  19. eureka:
  20. client:
  21. service-url:
  22. defaultZone: http://localhost:8761/eureka/

3,重启各个服务,并进行访问操作

4,登录RabbitMQ管理界面,可以看到,有数据传输

Zipkin存储Sleuth信息实现调用链追踪的几种方法

5,查看mysql数据库,可以看到有新的Sleuth信息被存储进去

Zipkin存储Sleuth信息实现调用链追踪的几种方法
Zipkin存储Sleuth信息实现调用链追踪的几种方法
Zipkin存储Sleuth信息实现调用链追踪的几种方法

六、将数据通过rabbitMQ写入ElasticSearch再在zipkin UI 上显示调用链的配置方法

如第五章所言,Zipkin支持Mysql、Elasticsearch、Cassandra等数据库存储。以下是将rabbitMQ传到collector的数据存入ElasticSearch数据库,Zipkin UI 读取数据库的数据再展示。架构图同第五章。

修改第五章的相应配置,步骤如下

1,安装配置ElasticSearch,存储sleuth数据。安装方法参见本人博客ELK 日志平台搭建实战

(1)加依赖,在POM.XML去处第五章的mysql相关依赖,增加ElasticSearch相关依赖

  1. <!-- <dependency> -->
  2. <!-- <groupId>mysql</groupId> -->
  3. <!-- <artifactId>mysql-connector-java</artifactId> -->
  4. <!-- </dependency> -->
  5. <!-- <dependency> -->
  6. <!-- <groupId>org.springframework.boot</groupId> -->
  7. <!-- <artifactId>spring-boot-starter-jdbc</artifactId> -->
  8. <!-- </dependency> -->
  9. <dependency>
  10. <groupId>io.zipkin.java</groupId>
  11. <artifactId>zipkin</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>io.zipkin.java</groupId>
  15. <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
  16. <version>1.28.0</version>
  17. </dependency>

(2)改配置,在application.yml去除mysql相关配置,加上Zipkin的配置,配置了zipkin的存储类型为elasticsearch,使用的StorageComponent为elasticsearch,然后需要配置elasticsearch,包括hosts,可以配置多个,用“,”隔开;index为zipkin等,具体配置如下:

  1. server:
  2. port: 9411
  3. spring:
  4. application:
  5. name: zipkin-server
  6. rabbitmq:
  7. host: localhost
  8. port: 5672
  9. username: guest
  10. password: guest
  11. zipkin:
  12. storage:
  13. type: elasticsearch
  14. StorageComponent: elasticsearch
  15. elasticsearch:
  16. cluster: elasticsearch
  17. max-requests: 30
  18. index: zipkin
  19. index-shards: 3
  20. index-replicas: 1
  21. hosts: 192.168.122.10:9200
  22. eureka:
  23. client:
  24. service-url:
  25. defaultZone: http://localhost:8761/eureka/

此处hosts192.168.122.10为我的ELK服务的虚机地址。

Zipkin存储Sleuth信息实现调用链追踪的几种方法

5,查看kibana,可以看到ElasticSearch数据库有新的以zipkin为index 的Sleuth信息被存储进去

Zipkin存储Sleuth信息实现调用链追踪的几种方法
Zipkin存储Sleuth信息实现调用链追踪的几种方法

总结

本文详细介绍了Spring cloud zipkin通过http和rabbitMQ收集sleuth信息到collector,存入到mysql和ElasticSearch,并通过Zipkin UI展示的方法。

本文代码在github 上可以下载: https://github.com/alvaxu/zipkinlearn

注:本文参考了方志鹏的博客Spring Cloud Sleuth进阶实战

原文地址:https://blog.csdn.net/alva_xu/article/details/84648249

继续阅读