dubbo分散式應用中使用zipkin做鏈路追蹤

weixin_34320159發表於2018-12-25

zipkin是什麼

Zipkin是一款開源的分散式實時資料追蹤系統(Distributed Tracking System),基於 Google Dapper的論文設計而來,由 Twitter 公司開發貢獻。其主要功能是聚集來自各個異構系統的實時監控資料。分散式跟蹤系統還有其他比較成熟的實現,例如:Naver的Pinpoint、Apache的HTrace、阿里的鷹眼Tracing、京東的Hydra、新浪的Watchman,美團點評的CAT,skywalking等。

為什麼使用Zipkin

隨著業務越來越複雜,系統也隨之進行各種拆分,特別是隨著微服務架構和容器技術的興起,看似簡單的一個應用,後臺可能有幾十個甚至幾百個服務在支撐;一個前端的請求可能需要多次的服務呼叫最後才能完成;當請求變慢或者不可用時,我們無法得知是哪個後臺服務引起的,這時就需要解決如何快速定位服務故障點,Zipkin分散式跟蹤系統就能很好的解決這樣的問題。

zipkin架構

301624-83a012b7aab6d309.png
zipkin

如圖所示,Zipkin 主要由四部分構成:收集器、資料儲存、查詢以及 Web 介面。Zipkin 的收集器負責將各系統報告過來的追蹤資料進行接收;而資料儲存預設使用 Cassandra,也可以替換為 MySQL;查詢服務用來向其他服務提供資料查詢的能力,而 Web 服務是官方預設提供的一個圖形使用者介面。

而各個異構的系統服務向 Zipkin 報告資料的架構如下圖。

301624-f14cbcf253d8a11c.png
異構

可以看出,各個系統都可以向zipkin傳送trace資訊。

Brave

Brave 是用來裝備 Java 程式的類庫,提供了面向 Standard Servlet、Spring MVC、Http Client、JAX RS、Jersey、Resteasy 和 MySQL 等介面的裝備能力,可以通過編寫簡單的配置和程式碼,讓基於這些框架構建的應用可以向 Zipkin 報告資料。同時 Brave 也提供了非常簡單且標準化的介面,在以上封裝無法滿足要求的時候可以方便擴充套件與定製。

如下圖是Brave的結構圖。Brave利用reporter向zipkin的Collector傳送trace資訊。

301624-4c4ae134307c7458.png
Brave

Zipkin在dubbo中的使用

dubbo作為一個rpc框架廣泛應用於分散式應用中,隨著業務的越來越複雜,一次請求的呼叫鏈也會變得繁雜,如何清晰的展示一次請求的呼叫鏈?結合Zipkin,可以方便的展示dubbo服務呼叫關係鏈。

下面通過一個實際的例子展示dubbo應用如何使用zipkin追蹤請求的呼叫鏈。Brave使用起來不是很方便,編碼量有些大,而利用Spring Cloud的sleuth元件可以很方便地使用brave,將trace資料通過http,Kafka或rabbitmq傳送給zipkin。所以在本例中將採用將trace資料通過kafka發給zipkin。

為了快速搭建zipkin的環境,本例採用docker的形式搭建zipkin和kafka。

zipkin 環境搭建

docker-compose.yml 內容如下:

version: '2'

services:
  storage:
    image: openzipkin/zipkin-mysql
    container_name: mysql
    ports:
      - 3306:3306

  ## kafka
  kafka-zookeeper:
    image: openzipkin/zipkin-kafka
    container_name: kafka-zookeeper
    ports:
      - 2181:2181
      - 9092:9092
  zipkin:
    image: openzipkin/zipkin
    container_name: zipkin
    environment:
      - STORAGE_TYPE=mysql
      - MYSQL_HOST=mysql
      - KAFKA_BOOTSTRAP_SERVERS=kafka-zookeeper:9092
    ports:
      - 9411:9411
    depends_on:
      - storage
      - kafka-zookeeper
      
  dependencies:
    image: openzipkin/zipkin-dependencies
    container_name: dependencies
    entrypoint: crond -f
    environment:
      - STORAGE_TYPE=mysql
      - MYSQL_HOST=mysql
      - MYSQL_USER=zipkin
      - MYSQL_PASS=zipkin
    depends_on:
      - storage

如上所示,本例將採用mysql作為zipkin的儲存,也可替換成別的儲存如:es等等。

啟動上面的docker-compose檔案。啟動完成。可以訪問路徑localhost:9411,可以看到如下頁面。

301624-8256e463910d9c15.png
zipkin

搭建一個dubbo分散式應用

首先搭建一個dubbo的專案。

301624-cb5a2c8b2e18fe87.png
dubbo專案

service-order 依賴 service-user專案。當查詢訂單詳情的時候order服務會去呼叫user模組獲取使用者詳情。service-user-dubbo-api是user服務定義模組。

spring mvc 接入zipkin

在service-order和service-user中新增maven引用。

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

    <dependency>
      <groupId>org.springframework.kafka</groupId>
      <artifactId>spring-kafka</artifactId>
    </dependency>

spring-cloud-starter-zipkin 封裝了了brave的操作。

301624-94cc55231c13f387.png
spring-cloud-starter-zipkin

在zipkin的brave倉庫中,zipkin對各個接入端做了整合的封裝。方便各個接入端快速接入。如下圖:

301624-0a47bedea767433a.png
brave-instrumentation

地址:https://github.com/openzipkin/brave/tree/master/instrumentation

在service-order和service-user新增相關配置:(只列出service-user,service-order類似)

dubbo:
  protocol:
    port: 20881
    name: dubbo
    id: dubbo
  application:
    name: service-user
  registry:
    protocol: zookeeper
    address: localhost:2181
  scan:
    base-packages: com.lenny.sample.user.service


spring:
  # 啟用sleuth
  sleuth:
    enabled: true
    sampler:
      probability: 1
  zipkin:
    sender:
      type: kafka #向kafka傳送trace資訊
  #kafka配置
  kafka:
    bootstrap-servers: PLAINTEXT://localhost:19092
  application:
    name: service-user

此時訪問service-order的獲取訂單詳情的介面 http://localhost:8081/order/1,此時在zipkin中會出現一條trcace記錄。和清楚地看出是訪問/order/1產生的trace資訊。

301624-2f32023e31b42561.png
springmvczipkin

下面講解brave-instrumentation的spring mvc 如何將springmvc訪問接入到zipkin中的。

301624-ce947b8606bb4e75.png
image-20181224215647495

TraceWebServletAutoConfiguration 會在spring boot專案啟動的時候,自動載入,通過FilterRegistrationBean將TracingFilter過濾器注入到容器中。這樣每次請求都會過TracingFileter過濾器。

301624-a2010363d729635e.png
image-20181224220313262

在doFilter的時候將訪問資訊傳送給zipkin。 詳細程式碼不做解釋了。

dubbo 接入到zipkin

上面的訪問訂單詳情的介面通過dubbo訪問了user模組的獲取使用者資訊的遠端介面,但是該訪問並沒有記錄到zipkin上。想要讓dubbo的訪問記錄也傳送到zipkin上,形成完整的呼叫鏈,該怎麼做呢?

在brave-instrumentation中有個dubbo-rpc的庫,這個庫就是將dubbo訪問資訊記錄zipkin的brave封裝。 spring-cloud-starter-zipkin預設並沒有引入該類庫。

首先我們引入該類庫。

在service-order和service-user模組maven中新增如下應用:


    <dependency>
      <groupId>io.zipkin.brave</groupId>
      <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
      <version>5.6.0</version>
    </dependency>

修改server-order和service-user配置檔案,在dubbo節點下增加如下配置。

dubbo:
  consumer:
    filter: 'tracing'
  provider:
    filter: 'tracing'

重啟service-order和service-user,再次訪問http://localhost:8081/order/1

發現新的請求呼叫鏈包含service-order和servicice-user。點選呼叫鏈,顯示呼叫詳情。

301624-566fc6cb0719565b.png
image-20181224223351892

dubbo接入zipkin原理:

dubbo提供了spi擴充套件機制,繼承dubbo的Filter。即可在dubbo呼叫方法之前執行一些操作。類似java web的filter機制。

brave-instrumentation-dubbo-rpc中提供了一個brave.dubbo.rpc.TracingFilter,在並配置了filter。(關於dubbo的spi機制在這了不做詳細的解釋)

301624-7c99cad9f7add805.png
filter配置

在配置檔案的dubbo節點下面配置

dubbo:
  consumer:
    filter: 'tracing'
  provider:
    filter: 'tracing'

當請求到達消費端和服務提供端的時候都會向zipkin傳送trace資訊。

總結

本文從以下幾點講解了dubbo分散式應用中如何做zipkin鏈路追蹤。

  1. zipkin介紹
  2. zipkin環境搭建
  3. zipkin在spring mvc的中使用與基本原理
  4. zipkin在dubbo中的使用以及基本原理

原始碼:https://github.com/applenele/zipkin-dubbo-demo

相關文章