轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://blog.csdn.net/forezp/article/details/76795269
本文出自方志朋的博客
為什么需要Spring Cloud Sleuth
微服務(wù)架構(gòu)是一個(gè)分布式架構(gòu),它按業(yè)務(wù)劃分服務(wù)單元,一個(gè)分布式系統(tǒng)往往有很多個(gè)服務(wù)單元。由于服務(wù)單元數(shù)量眾多,業(yè)務(wù)的復(fù)雜性,如果出現(xiàn)了錯(cuò)誤和異常,很難去定位。主要體現(xiàn)在,一個(gè)請(qǐng)求可能需要調(diào)用很多個(gè)服務(wù),而內(nèi)部服務(wù)的調(diào)用復(fù)雜性,決定了問(wèn)題難以定位。所以微服務(wù)架構(gòu)中,必須實(shí)現(xiàn)分布式鏈路追蹤,去跟進(jìn)一個(gè)請(qǐng)求到底有哪些服務(wù)參與,參與的順序又是怎樣的,從而達(dá)到每個(gè)請(qǐng)求的步驟清晰可見(jiàn),出了問(wèn)題,很快定位。
舉個(gè)例子,在微服務(wù)系統(tǒng)中,一個(gè)來(lái)自用戶的請(qǐng)求,請(qǐng)求先達(dá)到前端A(如前端界面),然后通過(guò)遠(yuǎn)程調(diào)用,達(dá)到系統(tǒng)的中間件B、C(如負(fù)載均衡、網(wǎng)關(guān)等),最后達(dá)到后端服務(wù)D、E,后端經(jīng)過(guò)一系列的業(yè)務(wù)邏輯計(jì)算最后將數(shù)據(jù)返回給用戶。對(duì)于這樣一個(gè)請(qǐng)求,經(jīng)歷了這么多個(gè)服務(wù),怎么樣將它的請(qǐng)求過(guò)程的數(shù)據(jù)記錄下來(lái)呢?這就需要用到服務(wù)鏈路追蹤。
Google開(kāi)源的 Dapper鏈路追蹤組件,并在2010年發(fā)表了論文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,這篇文章是業(yè)內(nèi)實(shí)現(xiàn)鏈路追蹤的標(biāo)桿和理論基礎(chǔ),具有非常大的參考價(jià)值。
目前,鏈路追蹤組件有Google的Dapper,Twitter 的Zipkin,以及阿里的Eagleeye (鷹眼)等,它們都是非常優(yōu)秀的鏈路追蹤開(kāi)源組件。
本文主要講述如何在Spring Cloud Sleuth中集成Zipkin。在Spring Cloud Sleuth中集成Zipkin非常的簡(jiǎn)單,只需要引入相應(yīng)的依賴和做相關(guān)的配置即可。
基本術(shù)語(yǔ)
Spring Cloud Sleuth采用的是Google的開(kāi)源項(xiàng)目Dapper的專(zhuān)業(yè)術(shù)語(yǔ)。
- Span:基本工作單元,發(fā)送一個(gè)遠(yuǎn)程調(diào)度任務(wù) 就會(huì)產(chǎn)生一個(gè)Span,Span是一個(gè)64位ID唯一標(biāo)識(shí)的,Trace是用另一個(gè)64位ID唯一標(biāo)識(shí)的,Span還有其他數(shù)據(jù)信息,比如摘要、時(shí)間戳事件、Span的ID、以及進(jìn)度ID。
- Trace:一系列Span組成的一個(gè)樹(shù)狀結(jié)構(gòu)。請(qǐng)求一個(gè)微服務(wù)系統(tǒng)的API接口,這個(gè)API接口,需要調(diào)用多個(gè)微服務(wù),調(diào)用每個(gè)微服務(wù)都會(huì)產(chǎn)生一個(gè)新的Span,所有由這個(gè)請(qǐng)求產(chǎn)生的Span組成了這個(gè)Trace。
- Annotation:用來(lái)及時(shí)記錄一個(gè)事件的,一些核心注解用來(lái)定義一個(gè)請(qǐng)求的開(kāi)始和結(jié)束 。這些注解包括以下:
- cs - Client Sent -客戶端發(fā)送一個(gè)請(qǐng)求,這個(gè)注解描述了這個(gè)Span的開(kāi)始
- sr - Server Received -服務(wù)端獲得請(qǐng)求并準(zhǔn)備開(kāi)始處理它,如果將其sr減去cs時(shí)間戳便可得到網(wǎng)絡(luò)傳輸?shù)臅r(shí)間。
- ss - Server Sent (服務(wù)端發(fā)送響應(yīng))–該注解表明請(qǐng)求處理的完成(當(dāng)請(qǐng)求返回客戶端),如果ss的時(shí)間戳減去sr時(shí)間戳,就可以得到服務(wù)器請(qǐng)求的時(shí)間。
- cr - Client Received (客戶端接收響應(yīng))-此時(shí)Span的結(jié)束,如果cr的時(shí)間戳減去cs時(shí)間戳便可以得到整個(gè)請(qǐng)求所消耗的時(shí)間。
案例實(shí)戰(zhàn)
本文案例一共四個(gè)工程采用多Module形式。需要新建一個(gè)主Maven工程,主要指定了Spring Boot的版本為1.5.3,Spring Cloud版本為Dalston.RELEASE。包含了eureka-server工程,作為服務(wù)注冊(cè)中心,eureka-server的創(chuàng)建過(guò)程這里不重復(fù);zipkin-server作為鏈路追蹤服務(wù)中心,負(fù)責(zé)存儲(chǔ)鏈路數(shù)據(jù);gateway-service作為服務(wù)網(wǎng)關(guān)工程,負(fù)責(zé)請(qǐng)求的轉(zhuǎn)發(fā),同時(shí)它也作為鏈路追蹤客戶端,負(fù)責(zé)產(chǎn)生數(shù)據(jù),并上傳給zipkin-service;user-service為一個(gè)應(yīng)用服務(wù),對(duì)外暴露API接口,同時(shí)它也作為鏈路追蹤客戶端,負(fù)責(zé)產(chǎn)生數(shù)據(jù)。
構(gòu)建zipkin-server工程
新建一個(gè)Module工程,取名為zipkin-server,其pom文件繼承了主Maven工程的pom文件;作為Eureka Client,引入Eureka的起步依賴spring-cloud-starter-eureka,引入zipkin-server依賴,以及zipkin-autoconfigure-ui依賴,后兩個(gè)依賴提供了Zipkin的功能和Zipkin界面展示的功能。代碼如下:
<parent>
<groupId>com.forezp</groupId>
<artifactId>sleuth</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
</dependencies>
在程序的啟動(dòng)類(lèi)ZipkinServiceApplication加上@EnableZipkinServer開(kāi)啟ZipkinServer的功能,加上@EnableEurekaClient注解,啟動(dòng)Eureka Client。代碼如下:
@SpringBootApplication
@EnableEurekaClient
@EnableZipkinServer
public class ZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinServerApplication.class, args);
}
}
在配置文件application.yml文件,指定程序名為zipkin-server,端口為9411,服務(wù)注冊(cè)地址為http://localhost:8761/eureka/。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 9411
spring:
application:
name: zipkin-server
構(gòu)建user-service
在主Maven工程下建一個(gè)Module工程,取名為user-service,作為應(yīng)用服務(wù),對(duì)外暴露API接口。pom文件繼承了主Maven工程的pom文件,并引入了Eureka的起步依賴spring-cloud-starter-eureka,Web起步依賴spring-boot-starter-web,Zipkin的起步依賴spring-cloud-starter-zipkin,代碼如下:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
在配置文件applicatiom.yml,指定了程序名為user-service,端口為8762,服務(wù)注冊(cè)地址為http://localhost:8761/eureka/,Zipkin Server地址為http://localhost:9411。spring.sleuth.sampler.percentage為1.0,即100%的概率將鏈路的數(shù)據(jù)上傳給Zipkin Server,在默認(rèn)的情況下,該值為0.1,代碼如下:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8762
spring:
application:
name: user-service
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
percentage: 1.0
在UserController類(lèi)建一個(gè)“/user/hi”的API接口,對(duì)外提供服務(wù),代碼如下:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/hi")
public String hi(){
return "I'm forezp";
}
}
最后作為Eureka Client,需要在程序的啟動(dòng)類(lèi)UserServiceApplication加上@EnableEurekaClient注解。
構(gòu)建gateway-service
新建一個(gè)名為gateway-service工程,這個(gè)工程作為服務(wù)網(wǎng)關(guān),將請(qǐng)求轉(zhuǎn)發(fā)到user-service,作為Zipkin客戶端,需要將鏈路數(shù)據(jù)上傳給Zipkin Server,同時(shí)它也作為Eureka Client。它在pom文件除了需要繼承主Maven工程的 pom,還需引入的依賴如下:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
在application.yml文件,配置程序名為gateway-service,端口為5000,服務(wù)注冊(cè)地址為http://localhost:8761/eureka/,Zipkin Server地址為http://localhost:9411,以“/user-api/**”開(kāi)頭的Uri請(qǐng)求,轉(zhuǎn)發(fā)到服務(wù)名為 user-service的服務(wù)。配置代碼如下:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 5000
spring:
application:
name: gateway-service
sleuth:
sampler:
percentage: 1.0
zipkin:
base-url: http://localhost:9411
zuul:
routes:
api-a:
path: /user-api/**
serviceId: user-service
在程序的啟動(dòng)類(lèi)GatewayServiceApplication,加上@EnableEurekaClient注解開(kāi)啟Eureka Client,加上@EnableZuulProxy注解,開(kāi)啟Zuul代理功能。代碼如下:
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
}
項(xiàng)目演示
完整的項(xiàng)目搭建完畢,依次啟動(dòng)eureka-server、zipkin-server、user-service、gateway-service。在瀏覽器上訪問(wèn)http://localhost:5000/user-api/user/hi,瀏覽器顯示:
I'm forezp
訪問(wèn)http://localhost:9411,即訪問(wèn)Zipkin的展示界面,界面顯示如圖1所示:

這個(gè)界面主要用來(lái)查找服務(wù)的調(diào)用情況,可以根據(jù)服務(wù)名、開(kāi)始時(shí)間、結(jié)束時(shí)間、請(qǐng)求消耗的時(shí)間等條件來(lái)查找。點(diǎn)擊“Find Trackes”按鈕,界面如圖所示。從圖可知服務(wù)的調(diào)用情況,比如服務(wù)調(diào)用時(shí)間、服務(wù)的消耗時(shí)間,服務(wù)調(diào)用的鏈路情況。

點(diǎn)擊Dependences按鈕,可以查看服務(wù)的依賴關(guān)系,在本案例中,gateway-service將請(qǐng)求轉(zhuǎn)發(fā)到了user-service,它們的依賴關(guān)系如圖:

怎么在鏈路數(shù)據(jù)中添加自定義數(shù)據(jù)
現(xiàn)在需要實(shí)現(xiàn)這樣一個(gè)功能,需要在鏈路數(shù)據(jù)中加上操作人。這需要在gateway-service上實(shí)現(xiàn)。建一個(gè)ZuulFilter過(guò)濾器,它的類(lèi)型為“post”,order為900,開(kāi)啟攔截。在攔截邏輯方法里,通過(guò)Tracer的addTag方法加上自定義的數(shù)據(jù),比如本案例中加入了鏈路的操作人。另外也可以在這個(gè)過(guò)濾器中獲取當(dāng)前鏈路的traceId信息,traceId作為鏈路數(shù)據(jù)的唯一標(biāo)識(shí),可以存儲(chǔ)在log日志中,方便后續(xù)查找。
@Component
public class LoggerFilter extends ZuulFilter {
@Autowired
Tracer tracer;
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return 900;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
tracer.addTag("operator","forezp");
System.out.print(tracer.getCurrentSpan().traceIdString());
return null;
}
}
使用spring-cloud-starter-stream-rabbit進(jìn)行鏈路通訊
在上述的案例中,最終gateway-service收集的數(shù)據(jù),是通過(guò)Http上傳給zip-server的,在Spring Cloud Sleuth中支持消息組件來(lái)通訊的,在這一小節(jié)使用RabbitMQ來(lái)通訊。首先來(lái)改造zipkin-server,在pom文件將zipkin-server的依賴去掉,加上spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit,代碼如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
在application.yml配置上RabbitMQ的配置,包括host、端口、用戶名、密碼,如下:
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
在程序的啟動(dòng)類(lèi)ZipkinServerApplication上@EnableZipkinStreamServer注解,開(kāi)啟ZipkinStreamServer。代碼如下:
@SpringBootApplication
@EnableEurekaClient
@EnableZipkinStreamServer
public class ZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinServerApplication.class, args);
}
}
現(xiàn)在來(lái)改造下Zipkin Client(包括gateway-service、user-service),在pom文件中將spring-cloud-starter-zipkin以來(lái)改為spring-cloud-sleuth-zipkin-stream和spring-cloud-starter-stream-rabbit,代碼如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
同時(shí)在applicayion.yml文件加上RabbitMQ的配置,同zipkin-server工程。
這樣,就將鏈路的上傳數(shù)據(jù)從Http改了為用消息代組件RabbitMQ。
將鏈路數(shù)據(jù)存儲(chǔ)在Mysql數(shù)據(jù)庫(kù)
在上述的例子中,Zipkin Server是將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,一旦程序重啟,之前的鏈路數(shù)據(jù)全部丟失,那么怎么將鏈路數(shù)據(jù)存儲(chǔ)起來(lái)呢?Zipkin支持Mysql、Elasticsearch、Cassandra存儲(chǔ)。這一小節(jié)講述用Mysql存儲(chǔ),下一節(jié)講述用Elasticsearch存儲(chǔ)。
首先,在zipkin-server工程加上Mysql的連接依賴mysql-connector-java,JDBC的起步依賴spring-boot-starter-jdbc,代碼如下:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
在配置文件application.yml加上數(shù)據(jù)源的配置,包括數(shù)據(jù)庫(kù)的Url、用戶名、密碼、連接驅(qū)動(dòng),另外需要配置zipkin.storage.type為mysql,代碼如下:
spring:
datasource:
url: jdbc:mysql://localhost:3306/spring-cloud-zipkin?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
zipkin:
storage:
type: mysql
另外需要在Mysql數(shù)據(jù)庫(kù)中初始化數(shù)據(jù)庫(kù)腳本,數(shù)據(jù)庫(kù)腳本地址:https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql/src/main/resources/mysql.sql
CREATE TABLE IF NOT EXISTS zipkin_spans (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL,
`id` BIGINT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`parent_id` BIGINT,
`debug` BIT(1),
`start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
`duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';
CREATE TABLE IF NOT EXISTS zipkin_annotations (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
`span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
`a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
`a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
`a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
`a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';
CREATE TABLE IF NOT EXISTS zipkin_dependencies (
`day` DATE NOT NULL,
`parent` VARCHAR(255) NOT NULL,
`child` VARCHAR(255) NOT NULL,
`call_count` BIGINT,
`error_count` BIGINT
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);
將鏈路數(shù)據(jù)存儲(chǔ)在ElasticSearch
使用Mysql存儲(chǔ)鏈路數(shù)據(jù),在并發(fā)高的情況下,顯然不合理,這時(shí)可以選擇使用ElasticSearch存儲(chǔ)。讀者需要自行安裝ElasticSearch、Kibana(下一小節(jié)使用),下載地址為https://www.elastic.co/products/elasticsearch。安裝完成后并啟動(dòng)它們,其中ElasticSearch的默認(rèn)端口為9200,Kibana的端口為5601。
安裝的過(guò)程可以參考我的這篇文章:http://blog.csdn.net/forezp/article/details/71189836
本小節(jié)的案例在上上小節(jié)的案例的基礎(chǔ)上進(jìn)行改造。首先在pom文件,加上zipkin的依賴和zipkin-autoconfigure-storage-elasticsearch-http的依賴,代碼如下:
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin</artifactId>
<version>1.28.0</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
<version>1.28.0</version>
</dependency>
在application.yml文件加上Zipkin的配置,配置了zipkin的存儲(chǔ)類(lèi)型為elasticsearch,使用的StorageComponent為elasticsearch。然后需要配置elasticsearch,包括hosts,可以配置多個(gè),用“,”隔開(kāi);index為zipkin等,具體配置如下:
zipkin:
storage:
type: elasticsearch
StorageComponent: elasticsearch
elasticsearch:
cluster: elasticsearch
max-requests: 30
index: zipkin
index-shards: 3
index-replicas: 1
hosts: localhost:9200
在kibana上展示
上一小節(jié)講述了如何將鏈路數(shù)據(jù)存儲(chǔ)在ElasticSearch,ElasticSearch可以和Kibana結(jié)合,將鏈路數(shù)據(jù)展示在 Kibana上。安裝完Kibana,并啟動(dòng),它默認(rèn)會(huì)向本地的9200端口的ElasticSearch讀取數(shù)據(jù),它默認(rèn)的端口為5601。訪問(wèn)http://localhost:5601,顯示的界面如下:

在上述的界面點(diǎn)擊"Management"按鈕,然后點(diǎn)擊“Add New”,添加一個(gè)index,在上節(jié)我們?cè)贓lasticSearch中寫(xiě)入鏈路數(shù)據(jù)的index配置為“zipkin”,那么在界面填寫(xiě)為“zipkin-*”,點(diǎn)擊“Create”按鈕。

創(chuàng)建完index之后,點(diǎn)擊Discover,就可以在界面上展示鏈路數(shù)據(jù)了。

源碼下載
最原始的工程:
https://github.com/forezp/SpringCloudLearning/tree/master/chapter-sleuth
采用RabbitMq通訊的工程:
https://github.com/forezp/SpringCloudLearning/tree/master/chapter-sleuth-stream
采用Mysql存儲(chǔ)的工程:
https://github.com/forezp/SpringCloudLearning/tree/master/chapter-sleuth-stream-mysql
采用ES存儲(chǔ)的工程:
https://github.com/forezp/SpringCloudLearning/tree/master/chapter-sleuth-stream-elasticsearch
參考資料
http://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html