springcloud使用zipkin實現鏈路追蹤與監控

微服務架構是一種分佈式架構,微服務系統按照業務劃分服務單元,一個微服務往往會有很多個服務單元,一個請求往往會有很多個單元參與,一旦請求出現異常,想要去定位問題點真心不容易,因此需要有個東西去跟蹤請求鏈路,記錄一個請求都調用了哪些服務單元,調用順序是怎麼樣的以及在各個服務單元處理的時間長短。常見的服務鏈路追蹤組件有google的dapper、twitter的zipkin、阿里的鷹眼等,它們都是出衆的開源鏈路追蹤組件。

分佈式鏈路監控與追蹤產生背景

在微服務系統中,隨着業務的發展,系統會變得越來越大,那麼各個服務之間的調用關係也就變得越來越複雜。一個 HTTP 請求會調用多個不同的微服務來處理返回最後的結果,在這個調用過程中,可能會因爲某個服務出現網絡延遲過高或發送錯誤導致請求失敗,這個時候,對請求調用的監控就顯得尤爲重要了。Spring Cloud Sleuth 提供了分佈式服務鏈路監控的解決方案。下面介紹 Spring Cloud Sleuth 整合 Zipkin 的解決方案。

Zipkin框架介紹

Zipkin 是 Twitter 的一個開源項目,它基於 Google Dapper 實現的。我們可以使用它來收集各個服務器上請求鏈路的跟蹤數據,並通過它提供的 REST API 接口來輔助查詢跟蹤數據以實現對分佈式系統的監控程序,從而及時發現系統中出現的延遲過高問題。除了面向開發的 API 接口之外,它還提供了方便的 UI 組件來幫助我們直觀地搜索跟蹤信息和分析請求鏈路明細,比如可以查詢某段時間內各用戶請求的處理時間等。

Zipkin 和 Config 結構類似,分爲服務端 Server,客戶端 Client,客戶端就是各個微服務應用。

下面用一張簡圖說明zipkin的工作原理
在這裏插入圖片描述

通過圖示很容易知道,其實通過引入zipkin這個組件,就是相當於爲各個微服務添加了一道上報服務調用關係的監控應用一樣,不同微服務之間的調用都會在zipkin-server中統一管理,然後通過ui進行圖形化展示,很容易弄清楚各個服務之間的鏈路調用關係,更容易排查、定位和解決生產中的問題

Zipkin環境搭建

在 Spring Boot 2.0 版本之後,官方已不推薦自己搭建Zipkin服務端了,而是直接提供了編譯好的 jar 包。詳情可以查看官網:https://zipkin.io/pages/quickstart.html
注意:zipkin官網已經提供定製了,使用官方jar運行即可。

默認端口號啓動zipkin服務

java –jar zipkin.jar 默認端口號; 9411

本地啓動成功後,瀏覽器訪問:http://localhost:9411 即可
或者自己指定端口號:java -jar zipkin.jar --server.port=8080

在這裏插入圖片描述

如何在微服務中整合使用zipkin

其實搭建過程非常簡單,只需要在各個微服務中添加如下依賴,並在配置文件中添加兩行配置即可,

1、添加依賴

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

2、加入zipkin配置

各個微服務中之前的配置保持不變

#zipkin-server地址
spring.zipkin.base-url=http://localhost:9411/

#接口默認全部採樣
spring.sleuth.sampler.probability=1.0

3、模擬微服務之間的調用關係

這裏假如有一個業務場景,服務1調用服務2,服務2調用服務3,一個簡單的鏈路,貼上主要代碼如下,

服務1:


server.port=8102

#掛載到eureka註冊中心中的服務名稱,以便被其他的消費者發現與引用
spring.application.name=consumer1

#註冊中心名字
eureka.client.service-url.defaultZone=http://localhost:8100/eureka

### 需要將自己的服務註冊到eureka上
eureka.client.register-with-eureka=true

####需要檢索服務
eureka.client.fetch-registry=true

logging.level.com.congge.controller=info

#微服務調用倆路
spring.zipkin.base-url=http://localhost:9411/

spring.sleuth.sampler.probability=1.0

@RestController
public class ConsumerController {

    // RestTemplate 是有SpringBoot Web組件提供 默認整合ribbon負載均衡器
    // rest方式底層是採用httpclient技術
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 在SpringCloud 中有兩種方式調用 rest、fegin(SpringCloud)
     * @return
     */

    @RequestMapping("/getFromProvider")
    public String getFromProvider() {
        // 有兩種方式,一種是採用服務別名方式調用,另一種是直接調用 使用別名去註冊中心上獲取對應的服務調用地址
        String url = "http://PROVIDER1/getServerPort";
        String result = restTemplate.getForObject(url, String.class);
        System.out.println("restTemplate 調用 服務提供者服務 :" + result);
        return result;
    }

}

服務2:


server.port=8101

#掛載到eureka註冊中心中的服務名稱,以便被其他的消費者發現與引用
spring.application.name=provider1

#註冊中心名字
eureka.client.service-url.defaultZone=http://localhost:8100/eureka

### 需要將自己的服務註冊到eureka上
eureka.client.register-with-eureka=true

####需要檢索服務
eureka.client.fetch-registry=true

logging.level.com.congge.controller=info

#zipkin-server地址
spring.zipkin.base-url=http://localhost:9411/

#接口默認全部採樣
spring.sleuth.sampler.probability=1.0
    

@Controller
public class Provider1Controller {

    @Value("${server.port}")
    private String serverPort;

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/getServerPort")
    @ResponseBody
    public String getMember() {

        String url = "http://PROVIDER2/getMsgFromProvider2";
        String result = restTemplate.getForObject(url, String.class);
        System.out.println("restTemplate 調用 第二個服務提供者的服務 服務提供者服務 :" + result);
        return result;

    }

}

服務3:


server.port=8106

#掛載到eureka註冊中心中的服務名稱,以便被其他的消費者發現與引用
spring.application.name=provider2

#註冊中心名字
eureka.client.service-url.defaultZone=http://localhost:8100/eureka

### 需要將自己的服務註冊到eureka上
eureka.client.register-with-eureka=true

####需要檢索服務
eureka.client.fetch-registry=true

logging.level.com.congge.controller=info

spring.zipkin.base-url=http://localhost:9411/

spring.sleuth.sampler.probability=1.0

@Controller
public class Provider2Controller {

    @GetMapping("/getMsgFromProvider2")
    @ResponseBody
    public String getMsgFromProvider2(){
        return "我是第二個服務提供者";
    }

}

分別啓動3個微服務,別忘了啓動eureka註冊中心,然後瀏覽器訪問微服務1的一個接口,可以看到,服務調用成功,
在這裏插入圖片描述

這時候我們可以在zipkin的ui控制界面看看效果,可以發現,服務之間的調用關係,服務名稱已經清晰展現出來了,同時包括服務之間的調用時常等詳細信息以及更細的信息都可以通過控制檯看到,
在這裏插入圖片描述

在這裏插入圖片描述

如果想深入理解zipkin的服務追蹤原理的,大家可以從旁邊那個json的格式數據入手進行底層原理探究,這裏就不再詳訴了,留着大家自己探索,
在這裏插入圖片描述

本篇到這裏就結束了,希望對看到的夥伴有用,最後感謝觀看!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章