Spring Cloud構建微服務架構:分布式服務跟蹤(整合logstash)
通過之前的入門示例,我們已經為trace-1和trace-2引入了Spring Cloud Sleuth的基礎模塊spring-cloud-starter-sleuth,實現了為各微服務的日志信息中添加跟蹤信息的功能。但是,由于日志文件都離散的存儲在各個服務實例的文件系統之上,僅僅通過查看日志文件來分析我們的請求鏈路依然是一件相當麻煩的差事,所以我們還需要一些工具來幫助我們集中的收集、存儲和搜索這些跟蹤信息。引入基于日志的分析系統是一個不錯的選擇,比如:ELK平臺,它可以輕松的幫助我們來收集和存儲這些跟蹤日志,同時在需要的時候我們也可以根據Trace ID來輕松地搜索出對應請求鏈路相關的明細日志。
ELK平臺主要有由ElasticSearch、Logstash和Kiabana三個開源免費工具組成:
- Elasticsearch是個開源分布式搜索引擎,它的特點有:分布式,零配置,自動發現,索引自動分片,索引副本機制,restful風格接口,多數據源,自動搜索負載等。
- Logstash是一個完全開源的工具,他可以對你的日志進行收集、過濾,并將其存儲供以后使用。
- Kibana 也是一個開源和免費的工具,它Kibana可以為 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以幫助您匯總、分析和搜索重要數據日志。
Spring Cloud Sleuth在與ELK平臺整合使用時,實際上我們只要實現與負責日志收集的Logstash完成數據對接即可,所以我們需要為Logstash準備json格式的日志輸出。由于Spring Boot應用默認使用了logback來記錄日志,而Logstash自身也有對logback日志工具的支持工具,所以我們可以直接通過在logback的配置中增加對logstash的appender,就能非常方便的將日志轉換成以json的格式存儲和輸出了。
下面我們來詳細介紹一下在快速入門示例的基礎上,如何實現面向Logstash的日志輸出配置:
- 在pom.xml依賴中引入logstash-logback-encoder依賴,具體如下:
- <dependency>
- <groupId>net.logstash.logback</groupId>
- <artifactId>logstash-logback-encoder</artifactId>
- <version>4.6</version>
- </dependency>
- 在工程/resource目錄下創建bootstrap.properties配置文件,將spring.application.name=trace-1配置移動到該文件中去。由于logback-spring.xml的加載在application.properties之前,所以之前的配置logback-spring.xml無法獲取到spring.application.name屬性,因此這里將該屬性移動到***加載的bootstrap.properties配置文件中。
- 在工程/resource目錄下創建logback配置文件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"/>
- <!-- 日志在工程中的輸出位置 -->
- <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>
- <!-- 控制臺的日志輸出樣式 -->
- <property name="CONSOLE_LOG_PATTERN"
- value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
- <!-- 控制臺Appender -->
- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
- <level>INFO</level>
- </filter>
- <encoder>
- <pattern>${CONSOLE_LOG_PATTERN}</pattern>
- <charset>utf8</charset>
- </encoder>
- </appender>
- <!-- 為logstash輸出的json格式的Appender -->
- <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{X-B3-TraceId:-}",
- "span": "%X{X-B3-SpanId:-}",
- "exportable": "%X{X-Span-Export:-}",
- "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"/>
- </root>
- </configuration>
對logstash支持主要通過名為logstash的appender實現,內容并不復雜,主要是對日志信息的格式化處理,上面為了方便調試查看我們先將json日志輸出到文件中。
完成上面的改造之后,我們再將快速入門的示例運行起來,并發起對trace-1的接口訪問。此時我們可以在trace-1和trace-2的工程目錄下發現有一個build目錄,下面分別創建了以各自應用名稱命名的json文件,該文件就是在logback-spring.xml中配置的名為logstash的appender輸出的日志文件,其中記錄了類似下面格式的json日志:
- {"@timestamp":"2016-12-04T06:57:58.970+00:00","severity":"INFO","service":"trace-1","trace":"589ee5f7b860132f","span":"a9e891273affb7fc","exportable":"false","pid":"19756","thread":"http-nio-9101-exec-1","class":"c.d.TraceApplication$$EnhancerBySpringCGLIB$$a9604da6","rest":"===<call trace-1>==="}
- {"@timestamp":"2016-12-04T06:57:59.061+00:00","severity":"INFO","service":"trace-1","trace":"589ee5f7b860132f","span":"2df8511ddf3d79a2","exportable":"false","pid":"19756","thread":"http-nio-9101-exec-1","class":"o.s.c.a.AnnotationConfigApplicationContext","rest":"Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@64951f38: startup date [Sun Dec 04 14:57:59 CST 2016]; parent: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4b8c8f15"}
我們除了可以通過上面的方式生成json文件之外,也可以使用LogstashTcpSocketAppender將日志內容直接通過Tcp Socket輸出到logstash服務端,比如:
- <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
- <destination>127.0.0.1:9250</destination>
- ...
- </appender>
本文完整示例:
讀者可以根據喜好選擇下面的兩個倉庫中查看trace-1和trace-2兩個項目:
- Github:https://github.com/dyc87112/SpringCloud-Learning/
- Gitee:https://gitee.com/didispace/SpringCloud-Learning/
【本文為51CTO專欄作者“翟永超”的原創稿件,轉載請通過51CTO聯系作者獲取授權】