Spring Cloud版本:Hoxton.SR5java
Spring Cloud Sleuth爲Spring Cloud提供了分佈式跟蹤的解決方案,它大量借用了Google Dapper、Twitter Zipkin和Apache HTrace的設計。web
Sleuth借用了Dapper的術語:spring
span(跨度):基本工做單元。span用一個64位的id惟一標識。除ID外,span還包含了其餘數據,例如描述、時間戳事件、鍵值對的註解(標籤),spanID、span父ID等。span被啓動和中止時,記錄了時間信息。初始化span被稱爲「root span」,該span的id和trace的ID相等。shell
trace(跟蹤):一組共享「root span」的span組成的樹狀結構稱爲trace。trace也用一個64位的ID惟一標識,trace中的全部span都共享該trace的ID。json
annotation(標註):annotaion用來記錄事件的存在,其中,核心annotaion用來定義請求的開始和結束。bootstrap
CS(Client Server客戶端發送):客戶端發起一個請求,該annotaion描述了span的開始後端
SR(Server Received服務器端接收):服務器端得到請求並準備處理它。若是用SR減去CS時間戳,就能獲得網絡延遲服務器
SS(Server Sent服務器端發送):該annotation代表若是完成請求處理(當響應發揮客戶端時)。若是用SS減去SR時間戳,就能獲得服務器端處理請求所需的時間網絡
CR(Client Received客戶端接收):span結束的標識。客戶端成功接收到服務器端的響應。若是CR減去CS時間戳,就能獲得客戶端發送請求到服務器響應所需的時間
app
在scl-eureka-client-consumer和scl-eureka-client-provider中添加以下依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
在配置文件application.yml中添加以下配置
logging: level: root: INFO org.springframework.web.servlet.DispatcherServlet: DEBUG org.springframework.cloud.sleuth: DEBUG
重啓兩個項目,訪問http://localhost:8090/consumer/info,可發現兩個項目的日誌內容中已包含span和trace的一些信息
ELK是一款很是流行的日誌分析系統。搭建過程請參考:https://blog.csdn.net/u012575432/article/details/107252814
在scl-eureka-client-consumer和scl-eureka-client-provider中添加以下依賴
<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>6.4</version> </dependency>
由於日誌須要輸出給logstash進行分析,所以須要在src/main/resources
目錄下新建文件logback-spring.xml
,內容以下:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <springProperty scope="context" name="springAppName" source="spring.application.name"/> <!-- Example for logging into the build folder of your project --> <property name="LOG_FILE" value="${BUILD_FOLDER:-log}/${springAppName}"/> <!-- You can override this to have a custom pattern --> <property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/> <!-- Appender to log to console --> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <!-- Minimum logging level to be presented in the console logs--> <level>DEBUG</level> </filter> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>utf8</charset> </encoder> </appender> <!-- Appender to log to file --> <appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern> <maxHistory>7</maxHistory> </rollingPolicy> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>utf8</charset> </encoder> </appender> <!-- Appender to log to file in a JSON format --> <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}.json</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern> <maxHistory>7</maxHistory> </rollingPolicy> <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"> <providers> <timestamp> <timeZone>UTC</timeZone> </timestamp> <pattern> <pattern> { "severity": "%level", "service": "${springAppName:-}", "trace": "%X{traceId:-}", "span": "%X{spanId:-}", "baggage": "%X{key:-}", "pid": "${PID:-}", "thread": "%thread", "class": "%logger{40}", "rest": "%message" } </pattern> </pattern> </providers> </encoder> </appender> <root level="INFO"> <appender-ref ref="console"/> <appender-ref ref="logstash"/> <!-- <appender-ref ref="flatfile"/> --> </root> </configuration>
由於logback-spring.xml
中使用了spring.application.name
屬性,因此須要將spring.application.name
移動到bootstrap.yml
下。
由於logback-spring.xml配置先於
application.yml
加載,因此若仍將spring.application.name
放在application.yml
裏,將沒法正確讀取屬性
編寫Logstash配置文件,命名爲logstash.conf,放在config
目錄下,而後重啓Logstash。內容以下
input { file { codec => json path => "/home/sc/eureka-client/log/*.json" # logback輸出的json格式日誌文件 } } filter { grok { match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}\s+---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" } } date { match => ["timestamp", "ISO8601"] } mutate { remove_field => ["timestamp"] } } output { elasticsearch { hosts => ["http://127.0.0.1:9000"] # ES地址 } }
重啓兩個項目,屢次訪問http://localhost:8090/consumer/info,產生日誌
而後訪問Kibana首頁http://localhost:5601,找到Elasticsearch下的Index Management,發現列表中已存在logstash開頭的index
而後找到Kibana下的Index Patterns,並按照以下步驟建立Index Pattern
建立完成後,點擊Kibana下的Discover,便可看見以下日誌。一個完整的http請求過程,展開可發現traceID都是一致的
ELK實現了業務日誌的跟蹤,Zipkin可實現服務鏈路日誌跟蹤
Spring官網已不推薦本身實現Zipkin Server端,建議使用原生的Zipkin Server
zipkin-server:https://search.maven.org/remote_content?g=io.zipkin&a=zipkin-server&v=LATEST&c=exec
zipkin-dependencies:https://search.maven.org/remote_content?g=io.zipkin.dependencies&a=zipkin-dependencies&v=LATEST
啓動zipkin服務端
nohup java -jar zipkin-server-2.21.5-exec.jar >> /home/sc/zipkin-server/zipkin.log 2>&1 &
在scl-eureka-client-consumer和scl-eureka-client-provider中添加以下依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
在application.yml裏添加zipkin相關配置
spring: zipkin: base-url: http://127.0.0.1:9411 sleuth: sampler: probability: 1.0
重啓兩個項目,屢次訪問http://localhost:8090/consumer/info,產生日誌,而後訪問http://localhost:9411,可看到請求日誌,點擊其中某一條便可看見調用過程。
使用以下命令啓動Zipkin服務端
nohup java -jar zipkin-server-2.21.5-exec.jar --RABBIT_ADDRESSES=127.0.0.1:5672 >> /home/sc/zipkin-server/zipkin.log 2>&1 &
在scl-eureka-client-consumer和scl-eureka-client-provider中添加以下依賴
<dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency>
<dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency>
修改application.yml配置文件,刪除spring.zipkin.base-url
,添加RabbitMQ相關配置
spring: zipkin: sender: type: rabbit sleuth: sampler: probability: 1.0 rabbitmq: host: 127.0.0.1 port: 5672
按上一步的測試方法進行測試。依然能夠正常顯示跟蹤日誌
Zipkin默認使用將數據存儲在內存中。若Zipkin Server重啓或崩潰都會致使數據丟失,不適合生產環境。zipkin Server支持多種後端存儲,MySQL、Elasticsearch、Cassandra等。本文使用Elasticsearch存儲跟蹤數據
使用以下命令啓動Zipkin服務端
* nohup java -jar zipkin-server-2.21.5-exec.jar --RABBIT_ADDRESSES=127.0.0.1:5672 --STORAGE_TYPE=elasticsearch --ES_HOSTS=http://127.0.0.1:9000 >> /home/sc/zipkin-server/zipkin.log 2>&1 &
使用curl http://localhost:9411/health
便可查看
使用以下命令啓動zipkin dependencies便可
STORAGE_TYPE=elasticsearch ES_HOSTS=http://127.0.0.1:9000 java -Xms64m -Xmx512m -jar zipkin-dependencies-2.4.2.jar
該jar包啓動後僅容許一次,分析當前依賴關係。若想定時分析,可配置定時任務
從新訪問http://localhost:9411,點擊依賴便可查看