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