使用Spring Cloud Sleuth實現鏈路監控

做者:社區 徐靖峯 原文地址:http://www.spring4all.com/article/156java

在服務比較少的年代,一個系統的接口響應緩慢一般可以迅速被發現,但現在的微服務模塊,大多具備規模大,依賴關係複雜等特性,錯綜複雜的網狀結構使得咱們不容易定位到某一個執行緩慢的接口。分佈式的服務跟蹤組件就是爲了解決這一個問題。其次,它解決了另外一個難題,在沒有它以前,咱們客戶會一直詢問:大家的系統有監控嗎?大家的系統有監控嗎?大家的系統有監控嗎?如今,謝天謝地,他們終於不問了。是有點玩笑的成分,但能夠確定的一點是,實現全鏈路監控是保證系統健壯性的關鍵因子。mysql

介紹Spring Cloud Sleuth和Zipkin的文章在網上其實並很多,因此我打算就我目前的系統來探討一下,如何實現鏈路監控。全鏈路監控這個詞意味着只要是不一樣系統模塊之間的調用都應當被監控,這就包括了以下幾種經常使用的交互方式:git

1 Http協議,如RestTemplate,Feign,Okhttp3,HttpClient...github

2 Rpc遠程調用,如Motan,Dubbo,GRPC...web

3 分佈式Event,如RabbitMq,Kafka...spring

而咱們項目目前混合使用了Http協議,Motan Rpc協議,因此本篇文章會着墨於實現這兩塊的鏈路監控。sql

項目結構

項目結構

上面的項目結構是本次demo的核心結構,其中數據庫

  1. zipkin-server做爲服務跟蹤的服務端,記錄各個模塊發送而來的調用請求,最終造成調用鏈路的報告。
  2. order,goods兩個模塊爲用來作測試的業務模塊,分別實現了http形式和rpc形式的遠程調用,最終咱們會在zipkin-server的ui頁面驗證他們的調用記錄。
  3. interface存放了order和goods模塊的公用接口,rpc調用須要一個公用的接口。
  4. filter-opentracing存放了自定義的motan擴展代碼,用於實現motan rpc調用的鏈路監控。

Zipkin服務端

添加依賴api

所有依賴app

核心依賴

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-storage-mysql</artifactId>
    <version>1.28.0</version>
</dependency>

zipkin-autoconfigure-ui提供了默認了UI頁面,zipkin-storage-mysql選擇將鏈路調用信息存儲在mysql中,更多的選擇能夠有elasticsearchcassandra

zipkin-server/src/main/resources/application.yml

spring:
  application:
    name: zipkin-server
  datasource:
    url: jdbc:mysql://localhost:3306/zipkin
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
zipkin:
   storage:
      type: mysql
server:
  port: 9411

建立啓動類

@SpringBootApplication
@EnableZipkinServer
public class ZipkinServerApp {

    @Bean
    public MySQLStorage mySQLStorage(DataSource datasource) {
        return MySQLStorage.builder().datasource(datasource).executor(Runnable::run).build();
    }

    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApp.class, args);
    }

}

當前版本在手動配置數據庫以後纔不會啓動報錯,可能與版本有關。mysql相關的腳本能夠在此處下載:mysql初始化腳本

zipkin-server單獨啓動後,就能夠看到鏈路監控頁面了,此時因爲沒有收集到任何鏈路調用記錄,顯示以下:

zipkin服務端頁面

HTTP鏈路監控

編寫order和goods兩個服務,在order暴露一個http端口,在goods中使用RestTemplate遠程調用,以後查看在zipkin服務端查看調用信息。

首先添加依賴,讓普通的應用具有收集和發送報告的能力,這一切在spring cloud sleuth的幫助下都變得很簡單

添加依賴

所有依賴

核心依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

spring-cloud-starter-zipkin依賴內部包含了兩個依賴,等於同時引入了spring-cloud-starter-sleuthspring-cloud-sleuth-zipkin兩個依賴。名字特別像,注意區分。

以order爲例介紹配置文件

order/src/main/resources/application.yml

spring:
  application:
    name: order # 1
  zipkin:
    base-url: http://localhost:9411 # 2
  sleuth:
    enabled: true
    sampler:
      percentage: 1 # 3
server:
  port: 8060

<1> 指定項目名稱能夠方便的標記應用,在以後的監控頁面能夠看到這裏的配置名稱

<2> 指定zipkin的服務端,用於發送鏈路調用報告

<3> 採樣率,值爲[0,1]之間的任意實數,顧名思義,這裏表明100%採集報告。

編寫調用類

服務端order

@RestController
@RequestMapping("/api")
public class OrderController {

    Logger logger = LoggerFactory.getLogger(OrderController.class);

    @RequestMapping("/order/{id}")
    public MainOrder getOrder(@PathVariable("id") String id) {
        logger.info("order invoking ..."); //<1>
        return new MainOrder(id, new BigDecimal(200D), new Date());
    }
}

客戶端goods

public MainOrder test(){
    ResponseEntity<MainOrder> mainOrderResponseEntity = restTemplate.getForEntity("http://localhost:8060/api/order/1144", MainOrder.class);
    MainOrder body = mainOrderResponseEntity.getBody();
    return body;
}

<1> 首先觀察這一行日誌在控制檯是如何輸出的

2017-11-08 09:54:00.633  INFO [order,d251f40af64361d2,e46132755dc395e1,true] 2780 --- [nio-8060-exec-1] m.c.sleuth.order.web.OrderController     : order invoking ...

比沒有引入sleuth以前多了一些信息,其中order,d251f40af64361d2,e46132755dc395e1,true分別表明了應用名稱,traceId,spanId,當前調用是否被採集,關於trace,span這些專業詞語,強烈建議去看看Dapper這篇論文,有不少中文翻譯版本,並非想象中的學術範,很是容易理解,不少鏈路監控文章中的截圖都來自於這篇論文,我在此就再也不贅述概念了。

緊接着,回到zipkin-server的監控頁面,查看變化

應用名稱

調用詳細記錄

依賴關係

到這裏,Http監控就已經完成了,若是你的應用使用了其餘的Http工具,如okhttp3,也能夠去[opentracing,zipkin相關的文檔中尋找依賴。

RPC鏈路監控

雖然說spring cloud是大勢所趨,其推崇的http調用方式也是鏈路監控的主要對象,但不得不認可目前大多數的系統內部調用仍然是RPC的方式,至少咱們內部的系統是如此,因爲咱們內部採用的RPC框架是weibo開源的motan,這裏以此爲例,介紹RPC的鏈路監控。motan使用SPI機制,實現了對鏈路監控的支持,https://github.com/weibocom/motan/issues/304這條issue中能夠得知其加入了opentracing標準化追蹤。但目前只能經過本身添加組件的方式才能配合spring-cloud-sleuth使用,下面來看看實現步驟。

filter-opentracing

實現思路:引入SleuthTracingFilter,做爲全局的motan過濾器,給每一次motan的調用打上traceId和spanId,並編寫一個SleuthTracingContext,持有一個SleuthTracerFactory工廠,用於適配不一樣的Tracer實現。

具體的實現能夠參考文末的地址

order/src/main/resources/META-INF/services/com.weibo.api.motan.filter.Filter

com.weibo.api.motan.filter.sleuth.SleuthTracingFilter

添加一行過濾器的聲明,使得項目可以識別

配置SleuthTracingContext

@Bean
SleuthTracingContext sleuthTracingContext(@Autowired(required = false)  org.springframework.cloud.sleuth.Tracer tracer){
    SleuthTracingContext context = new SleuthTracingContext();
    context.setTracerFactory(new SleuthTracerFactory() {
        @Override
        public org.springframework.cloud.sleuth.Tracer getTracer() {
            return tracer;
        }
    });

    return context;
}

使用spring-cloud-sleuth的Tracer做爲motan調用的收集器

爲服務端和客戶端配置過濾器

basicServiceConfigBean.setFilter("sleuth-tracing");

basicRefererConfigBean.setFilter("sleuth-tracing");

編寫調用測試類

order做爲客戶端

@MotanReferer
GoodsApi goodsApi;

@RequestMapping("/goods")
public String getGoodsList() {
    logger.info("getGoodsList invoking ...");
    return goodsApi.getGoodsList();
}

goods做爲服務端

@MotanService
public class GoodsApiImpl implements GoodsApi {

    Logger logger = LoggerFactory.getLogger(GoodsApiImpl.class);

    @Override
    public String getGoodsList() {
        logger.info("GoodsApi invoking ...");
        return "success";
    }
}

查看調用關係

motan調用詳細信息

依賴關係

第一張圖中,使用前綴http和motan來區別調用的類型,第二張圖中,依賴變成了雙向的,由於一開始的http調用goods依賴於order,而新增了motan rpc調用以後order又依賴於goods。

總結

系統間交互的方式除了http,rpc,還有另外的方式如mq,之後還可能會有更多的方式,但實現的監控的思路都是一致的,即如何無侵入式地給調用打上標籤,記錄報告。Dapper給實現鏈路監控提供了一個思路,而OpenTracing爲各個框架不一樣的調用方式提供了適配接口....Spring Cloud Sleuth則是遵循了Spring一向的風格,整合了豐富的資源,爲咱們的系統集成鏈路監控提供了很大的便捷性。

關於motan具體實現鏈路監控的代碼因爲篇幅限制,將源碼放在了個人github中,若是你的系統使用了motan,能夠用於參考:https://github.com/lexburner/sleuth-starter

參考

《Spring Cloud微服務實戰》-- 翟永超

黃桂錢老師的指導

相關文章
相關標籤/搜索