版权声明:本文为博主原创文章,遵循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. bootstrap 多级联动下拉框

    <!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...

  2. vlc for mac设置中文的方法

    VLC for mac是一款mac系统下的多媒体播放器,支持播放MPEG-1.MPEG-2.MPEG-4.DivX.MP3和OGG,以及DVD.VCD.等各种流媒体协议在内的多种协议格式,并且能够对电 ...

  3. HashSet Integer输出有序,String输出无序

    1. 背景自己在测试HashSet时,发现其输出Integer是有序的.2. 测试public static void hashSetObjectTest(){ Set<Integer> ...

  4. CentOS7.4下安装部署HAProxy高可用群集

    目录第一部分 实验环境第二部分 搭建配置web服务器第三部分 安装配置haproxy服务器第四部分 测试验证第五部分 haproxy配置相关详细解释 第一部分 实验环境1.一台harpoxy调度服务器 ...

  5. java基础之 内部类 & 嵌套类

    参考文档: 内部类的应用场景 http://blog.csdn.net/hivon/article/details/606312 http://wwty.iteye.com/blog/338628 定 ...

  6. 阿里云ecs centos yarn 安装

    安装流程:https://yarn.bootcss.com/docs/install/#centos-stable

  7. 【python基础学习】基础重点难点知识汇总

    python中decorator装饰器 语法示例: @decorator 什么是装饰器: 问题: 定义一个函数后 在运行时动态增加功能 又不想改动函数本身的代码 示例: # 希望对下列函数调用增加lo ...

  8. javascript常用方法 - String

    // 1.长字符串 // 1.1 let longString1 = "This is a very long string which needs " + "to wr ...

  9. phpstorm2019.1 实现保存(ctrl+s)同时格式化代码

    1.选择Edit(编辑)->Macros(宏)->Start Macro Recording(开始录制宏),如下图: 2.直接按想要录制的快捷键,先按Ctrl+ALT+L,然后键盘按Ctr ...

  10. php异常处理小总结

    2019年8月23日10:56:31 php很多开发不习惯使用异常处理,因为web开发,重在于快速开发,易用性,高性能,不强调程序健壮性 php的异常使用其实不是太完善,易用性也差点,当然这个对比其他 ...