spring cloud sleuth提供了服务链路追踪,并兼容了zipkin,Zipkin是一个链路跟踪工具,能够用来监控微服务集群中调用链路的通畅状况。java
1.原本想新建一个有关zipkin-server的自定义zipkin服务器,发现最新的版本已经不支持了.web
build.gradle文件spring
buildscript { ext { springBootVersion = '2.0.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter') compile('org.springframework.boot:spring-boot-starter-web') compile('io.zipkin.java:zipkin-server:2.11.1') compile('io.zipkin.java:zipkin-autoconfigure-ui:2.11.1') testCompile('org.springframework.boot:spring-boot-starter-test') }
启动类:json
package com.example.serverzipkin; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import zipkin2.server.internal.EnableZipkinServer; //zipkin2是重点,防止找不到注解 @EnableZipkinServer @SpringBootApplication public class ServerZipkinApplication { public static void main(String[] args) { SpringApplication.run(ServerZipkinApplication.class, args); } }
来看源码发现zipkin中的@EnableZipkinServer注解已经被删掉了,放到zipkin2中了,若是你注解引入失败的话,先注释掉,而后在zipkin2中找到便可。服务器
此时启动,而后访问http://localhost:9291,发现报错,错误信息以下:app
2018-08-14 10:10:44.391 ERROR 1873 --- [ XNIO-1 task-11] io.undertow.request : UT005023: Exception handling request to /zipkin/traces_en.properties java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter containing tag keys [method, status, uri]. The meter you are attempting to register has keys [exception, method, status, uri]. at io.micrometer.prometheus.PrometheusMeterRegistry.lambda$collectorByName$9(PrometheusMeterRegistry.java:361) ~[micrometer-registry-prometheus-1.0.6.jar:1.0.6] at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1877) ~[na:1.8.0_162] at io.micrometer.prometheus.PrometheusMeterRegistry.collectorByName(PrometheusMeterRegistry.java:348) ~[micrometer-registry-prometheus-1.0.6.jar:1.0.6] at io.micrometer.prometheus.PrometheusMeterRegistry.newTimer(PrometheusMeterRegistry.java:160) ~[micrometer-registry-prometheus-1.0.6.jar:1.0.6] at io.micrometer.core.instrument.MeterRegistry.lambda$timer$2(MeterRegistry.java:257) ~[micrometer-core-1.0.6.jar:1.0.6] at io.micrometer.core.instrument.MeterRegistry.getOrCreateMeter(MeterRegistry.java:566) ~[micrometer-core-1.0.6.jar:1.0.6] at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:528) ~[micrometer-core-1.0.6.jar:1.0.6] at io.micrometer.core.instrument.MeterRegistry.timer(MeterRegistry.java:255) ~[micrometer-core-1.0.6.jar:1.0.6] at io.micrometer.core.instrument.Timer$Builder.register(Timer.java:447) ~[micrometer-core-1.0.6.jar:1.0.6] at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.stop(WebMvcMetricsFilter.java:234) ~[spring-boot-actuator-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.record(WebMvcMetricsFilter.java:225) ~[spring-boot-actuator-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:163) ~[spring-boot-actuator-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:123) ~[spring-boot-actuator-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108) ~[spring-boot-actuator-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE] at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:64) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104) [undertow-servlet-1.4.25.Final.jar:1.4.25.Final] at io.undertow.server.Connectors.executeRootHandler(Connectors.java:336) [undertow-core-1.4.25.Final.jar:1.4.25.Final] at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830) [undertow-core-1.4.25.Final.jar:1.4.25.Final] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_162] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_162] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_162]
加上management.metrics.web.server.auto-time-requests=false这个配置就行了eclipse
application.ymlmaven
server: port: 9411 spring: application: name: server-zipkin management: metrics: web: server: auto-time-requests: false
而后再次启动:ide
发现zipkin已经启动成功了。spring-boot
2.新建一个service-hi项目
build.gradle
buildscript { ext { springBootVersion = '2.0.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } ext { springCloudVersion = 'Finchley.SR1' } dependencies { compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.cloud:spring-cloud-starter-zipkin') testCompile('org.springframework.boot:spring-boot-starter-test') } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
application.yml
server: port: 9292 spring: application: name: service-hi zipkin: base-url: http://localhost:9411 sleuth: sampler: probability: 1.0 #采样比例为1.0,是全部的访问都须要
启动类
package com.example.servicehi; import brave.sampler.Sampler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.sleuth.sampler.ProbabilityBasedSampler; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @SpringBootApplication public class ServiceHiApplication { public static void main(String[] args) { SpringApplication.run(ServiceHiApplication.class, args); } @Autowired private RestTemplate restTemplate; @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } @RequestMapping("/hi") public String callHome(){ return restTemplate.getForObject("http://localhost:9293/info", String.class); } @RequestMapping("/hh") public String info(){ return "i'm service-hi"; } }
3.新建一个service-info项目
build.gradle
buildscript { ext { springBootVersion = '2.0.4.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } ext { springCloudVersion = 'Finchley.SR1' } dependencies { compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.cloud:spring-cloud-starter-zipkin') testCompile('org.springframework.boot:spring-boot-starter-test') } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
application.yml
server: port: 9293 spring: application: name: service-info zipkin: base-url: http://localhost:9411
启动类
package com.example.serviceinfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @SpringBootApplication public class ServiceInfoApplication { public static void main(String[] args) { SpringApplication.run(ServiceInfoApplication.class, args); } @RequestMapping("/hi") public String home(){ return "hi i'm information!"; } @RequestMapping("/info") public String info(){ return restTemplate.getForObject("http://localhost:9292/hh",String.class); } @Autowired private RestTemplate restTemplate; @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
此时访问http://localhost:9292/hi,其结果为:
此时访问http://localhost:9411/观察调用状况:
调用链以及调用时间以下:
以及
以及
点击service-hi