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

            </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 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前,我们先写了以下几个服务

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的路由功能

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

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

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

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,启动各个服务,

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

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

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

还可以看到更多的信息

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

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

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

1,安装RabbitMQ

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

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>

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


  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管理界面,可以看到,有数据传输

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

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

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

本章节介绍数据存入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)代码不用改

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

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

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

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

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

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

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

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

2,改造Zipkin server

(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服务的虚机地址。

(3)代码不用改

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

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

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

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

总结

本文详细介绍了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

Zipkin存储Sleuth信息实现调用链追踪的几种方法的更多相关文章

  1. 多语言(Java、.NET、Node.js)混合架构下开源调用链追踪APM项目初步选型

    1. 背景 我们的技术栈包括了Java..NET.Node.js等,并且采用了分布式的技术架构,系统性能管理.问题排查成本越来越高. 2. 基本诉求 针对我们的情况,这里列出了选型的主要条件,作为最终 ...

  2. C/C++:Windows编程—调用DLL程序的2种方法(转载)

    文章为转载,原文出处https://blog.csdn.net/qq_29542611/article/details/86618902 前言先简单介绍下DLL.DLL:Dynamic Link Li ...

  3. 请阐述调用Activity有哪几种方法,并写出相关的Java代码

    请阐述调用Activity有哪几种方法,并写出相关的Java代码. 答案:可以采用两种方式调用Activity:显示调用和隐式调用.显示调用直接指定了Activity,代码如下: Intent int ...

  4. ASP.NET,C#后台调用前台javascript的五种方法

    C#后台调用前台javascript的五种方法 由于项目需要,用到其他项目组用VC开发的组件,在web后台代码无法访问这个组件,所以只好通过后台调用前台的javascript,从而操作这个组件.在网上 ...

  5. C# 调用WCF服务的两种方法

    项目简介 之前领导布置一个做单点登录的功能给我,实际上就是医院想做一个统一的平台来实现在这个统一的平台登录后不需要在His.Emr.Lis等系统一个个登录,直接可以登录到对应的系统,然后进行相应的操作 ...

  6. 学习之路十四:客户端调用WCF服务的几种方法小议

    最近项目中接触了一点WCF的知识,也就是怎么调用WCF服务,上网查了一些资料,很快就搞出来,可是不符合头的要求,主要有以下几个方面: ①WCF的地址会变动,地址虽变,但是里面的逻辑不变! ②不要引用W ...

  7. (转)JAVA 调用Web Service的三种方法

    1.使用HttpClient用到的jar文件:commons-httpclient-3.1.jar方法:预先定义好Soap请求数据,可以借助于XMLSpy Professional软件来做这一步生成. ...

  8. go 调用windows dll 的三种方法

    参考:https://blog.csdn.net/qq_39584315/article/details/81287669 大部分代码参考:https://studygolang.com/articl ...

  9. WCF 客户端调用服务操作的两种方法

    本节的主要内容:1.通过代理类的方式调用服务操作.2.通过通道的方式调用服务操作.3.代码下载 一.通过代理类的方式调用服务操作(两种方式添加代理类) 1.手动编写代理类,如下: 客户端契约: usi ...

随机推荐

  1. HTTPS加密协议过程

    1.客户端发起https请求 指用户在浏览器中输入一个https网址,然后链接到server的443端口 2.服务端的配置 在服务端向CA机构申请SSL数字证书.SSL证书就是一对公钥和私钥.公钥相当 ...

  2. UDP丢包原因总结

    丢包检查方法 给每个UDP包编号,对比收发端的接收到的包.对于UDP协议层上的包,例如RTP包,可以从RTP包中读出包的序列号进行判断. 抓包.发送端和接收端分别抓包.linux下可以使用tcpdum ...

  3. 动态查找之二叉树查找 c++实现

    算法思想 二叉搜索树(又称二叉查找树或二叉排序树)BST树 二叉查找树 二叉查找树,也称二叉搜索树,或二叉排序树.其定义也比较简单,要么是一颗空树,要么就是具有如下性质的二叉树: (1)若任意节点的左 ...

  4. CAS单点登录源码解析之【客户端】

    cas 3.5.3服务器搭建+spring boot集成+shiro模拟登录(不修改现有shiro认证架构).因为我们属于供应商,所以有些客户那里会需要接对方的CAS,所以没有使用shiro和cas的 ...

  5. 本地快速搭建MarkDown语法网站

    主要是在之前跟人学的快速搭建一个简单的网站,可以通过这样的方式把相关的文档美美的放在服务器上,然后给别人看也好,自己也能熟系熟系MarkDown的语法并学习,要是接口文档还是推荐通过swagger去实 ...

  6. Windows删除空文件夹问题带来的学习与思考

    https://blog.csdn.net/XavierDarkness/article/details/84785482 1.问题产生:   前段时间得到一份资源,号称有近500个G的学习资料,花了 ...

  7. DOS批处理中%~dp0表示什么意思

    https://www.jianshu.com/p/5a1a882ead95 https://www.cnblogs.com/cnpirate/p/5282324.html https://www.c ...

  8. Axure8.1.0.3388 授权码

    Licensee:www.jb51.net Key:5eKQiVe0zlGqMijERRp6ancI2jGAxhuejGWvk2oWClywQSB/Mrq72wYhj7D9gAKC

  9. IDEA快捷键无法使用

    IDEA快捷键无法使用 觉得有用的话,欢迎一起讨论相互学习~Follow Me 今天新换了一台主机,但是很奇怪的是自己的IDEA快捷键使用不了了,以为是主机还是硬件的问题,最终解决后,发现是软件之间的 ...

  10. Xcode中opengl的配置

    1. GLUT + GLTools + SDL2 Frameworks Search Paths :Framework + Library ( $(PROJECT_DIR)/build ) Searc ...