幾種分散式呼叫鏈監控元件的實踐與比較(一)實踐

aoho發表於2017-11-10

引言:最近在調研與選型分散式呼叫鏈監控元件。選了主要的三種APM元件進行了實踐與比較。本來打算一篇文章寫完的,篇幅太長,打算分兩篇。本文主要講下鏈路traceing的基本概念和幾種APM元件的實踐,實踐部分也沒給出特別詳細的步驟,因為本文重點不在具體的步驟。第二篇將會講下幾種APM選型的比較與效能測試。

1. 問題背景

微服務架構下,服務按照不同的維度進行拆分,一次請求請求往往需要涉及到多個服務。網際網路應用構建在不同的軟體模組集上,這些軟體模組,有可能是由不同的團隊開發、可能使用不同的程式語言來實現、有可能布在了幾千臺伺服器,橫跨多個不同的資料中心。因此,就需要一些可以幫助理解系統行為、用於分析效能問題的工具,以便發生故障的時候,能夠快速定位和解決問題。

分散式呼叫鏈監控元件在這樣的環境下產生了。最出名的是谷歌公開的論文提到的Dapper。開發Dapper是為了收集更多的複雜分散式系統的行為資訊,然後呈現給Google的開發者們。這樣的分散式系統有一個特殊的好處,因為那些大規模的低端伺服器,作為網際網路服務的載體,是一個特殊的經濟划算的平臺。想要在這個上下文中理解分散式系統的行為,就需要監控那些橫跨了不同的應用、不同的伺服器之間的關聯動作。

市面上的APM(Application Performance Management)理論模型大多都是借鑑(borrow)Google Dapper論文,本文重點關注以下幾種APM元件:

  • Zipkin
    由Twitter公司開源,開放原始碼分散式的跟蹤系統,用於收集服務的定時資料,以解決微服務架構中的延遲問題,包括資料的收集、儲存、查詢和展現。
  • Pinpoint
    Pinpoint是一款對Java編寫的大規模分散式系統的APM工具,由韓國人開源的分散式跟蹤元件。
  • Skywalking
    國產的優秀APM元件,是一個對JAVA分散式應用程式叢集的業務執行情況進行追蹤、告警和分析的系統。

其他類似的元件還有美團點評的CAT,淘寶的鷹眼EgleEye。

如上所述,那麼我們選擇鏈路監控元件有哪些要求呢?Dapper中也提到了,筆者總結如下:

  • 探針的效能消耗。
    APM元件服務的影響應該做到足夠小。在一些高度優化過的服務,即使一點點損耗也會很容易察覺到,而且有可能迫使線上服務的部署團隊不得不將跟蹤系統關停。

  • 程式碼的侵入性
    對於應用的程式設計師來說,是不需要知道有跟蹤系統這回事的。如果一個跟蹤系統想生效,就必須需要依賴應用的開發者主動配合,那麼這個跟蹤系統也太脆弱了,往往由於跟蹤系統在應用中植入程式碼的bug或疏忽導致應用出問題,這樣才是無法滿足對跟蹤系統“無所不在的部署”這個需求。

  • 可擴充套件性
    能夠支援的元件越多當然越好。或者提供便捷的外掛開發API,對於一些沒有監控到的元件,應用開發者也可以自行擴充套件。

  • 資料的分析
    資料的分析要快 ,分析的維度儘可能多。跟蹤系統能提供足夠快的資訊反饋,就可以對生產環境下的異常狀況做出快速反應。分析的全面,能夠避免二次開發。

2. 基礎概念

上面列出的幾種元件,其中Zipkin是嚴格按照Google Dapper論文實現的,下面介紹下其中涉及的基本概念。

  • Span
    基本工作單元,一次鏈路呼叫(可以是RPC,DB等沒有特定的限制)建立一個span,通過一個64位ID標識它,uuid較為方便,span中還有其他的資料,例如描述資訊,時間戳,key-value對的(Annotation)tag資訊,parent-id等,其中parent-id可以表示span呼叫鏈路來源。

  • Trace:類似於樹結構的Span集合,表示一條呼叫鏈路,存在唯一標識。比如你執行的分散式大資料儲存一次Trace就由你的一次請求組成。

  • Annotation: 註解,用來記錄請求特定事件相關資訊(例如時間),通常包含四個註解資訊:
    (1) cs:Client Start,表示客戶端發起請求

    (2) sr:Server Receive,表示服務端收到請求

    (3) ss:Server Send,表示服務端完成處理,並將結果傳送給客戶端

    (4) cr:Client Received,表示客戶端獲取到服務端返回資訊

2.1 Trace

下面看一下,在系統中Trace是什麼樣子。

trace
trace

每種顏色的note標註了一個span,一條鏈路通過TraceId唯一標識,Span標識發起的請求資訊。樹節點是整個架構的基本單元,而每一個節點又是對span的引用。節點之間的連線表示的span和它的父span直接的關係。雖然span在日誌檔案中只是簡單的代表span的開始和結束時間,他們在整個樹形結構中卻是相對獨立的。

2.2 Span

sp
sp

上圖說明了span在一次大的跟蹤過程中是什麼樣的。Dapper記錄了span名稱,以及每個span的ID和父ID,以重建在一次追蹤過程中不同span之間的關係。如果一個span沒有父ID被稱為root span。所有span都掛在一個特定的跟蹤上,也共用一個跟蹤id。

2.3 Annotation

自動的探針,不需要修改應用程式原始碼,對應用開發者近乎零浸入的成本對分散式控制路徑進行跟蹤,幾乎完全依賴於基於少量通用元件庫的改造。Dapper還允許應用程式開發人員在Dapper跟蹤的過程中新增額外的資訊,以監控更高階別的系統行為,或幫助除錯問題。

下面章節將會介紹下上述三種APM元件的使用與實踐。

3. zipkin

zipkin主要涉及幾個元件:collector收集agent的資料,storage儲存,web UI圖形化介面,search查詢Storage中儲存的資料,提供簡單的JSON API獲取資料。

我們的專案基於微服務框架spring cloud構建微服務。spring cloud也提供了spring-cloud-sleuth來方便整合zipkin實現。所以筆者就在專案中試了下spring-cloud-sleuth-zipkin。

起了三個服務:
zipkin-server、zipkin-client-backend、zipkin-client。
其中server服務負責收集以及資訊展示。client-backend呼叫client,產生呼叫鏈路資訊。

3.1 zipkin-server實現

zipkin-server實現主要有兩點需要注意,其一是收集到資料的儲存,方式包括記憶體、資料庫、ES等;其二是通訊方式,包括http通訊和mq非同步方式通訊,http通訊會對正常的訪問造成影響,所以還是推薦基於mq非同步方式通訊。

本文使用mysql作為儲存,使用MQ通訊,MQ通訊基於Spring-cloud-Stream。本文重點不在zipkin-server的具體幾種實現方式,其他方式,讀者可以自己去官網檢視。

(1)pom需要新增的引用如下:

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

    <!--zipkin依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-ui</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!--儲存到資料庫需要如下依賴-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>複製程式碼

(2)啟動類:

// 使用Stream方式啟動ZipkinServer
@EnableZipkinStreamServer
@SpringBootApplication
public class ZipkinStreamServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinStreamServerApplication.class,args);
    }
}複製程式碼

@EnableZipkinStreamServer註解引入了@EnableZipkinServer註解,同時還建立了一個rabbit-mq的SleuthSink訊息佇列監聽器。

(3)配置檔案

server:
  port: 9411

spring:
  datasource:
    username: root
    password: root123
    schema[0]: classpath:/zipkin.sql

zipkin:
  storage:
    type: mysql

---
spring:
  application:
    name: microservice-zipkin-stream-server
  rabbitmq:
    host: ${RABBIT_ADDR:localhost}
    port: ${RABBIT_PORT:5672}
    username: guest
    password: guest
  sleuth:
    enabled: false
  profiles: default
  datasource:
    url:  jdbc:mysql://localhost:3307/zipkin?autoReconnect=true&useSSL=false複製程式碼

zipkin.sql可以去官網獲取,設定了zipkin-server的埠號為9411。

3.2 zipkin-client

兩個zipkin-client的配置一樣,所以放在一起。

(1)pom依賴

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>複製程式碼

(2) 配置檔案

spring:
  rabbitmq:
    host: 127.0.0.1
    port : 5672
    username: guest
    password: guest複製程式碼

3.3 結果

服務之間的呼叫關係如下:

可以看到客戶端的請求經過gateway,呼叫內網中的各個服務,部分還涉及到呼叫notice服務。從圖中可以清楚的看出客戶端請求所經過的服務。
下面看下demo2-default服務例項中的http path:

上圖中demo2-default服務的幾個http path按照時長排序,顯示了trace呼叫時長和span數量。點進去可以看到:

圖中列出了從父span開始,每一個span的耗時。本次trace中,涉及到兩個服務demo1和demo2。demo2呼叫demo1,從597ms開始呼叫demo1,完成最終的請求總共耗時1265ms。

4. pinpoint

對程式碼零侵入,運用JavaAgent位元組碼增強技術,只需要加啟動引數即可。
pinpoint的幾個元件部分和zipkin差不多,架構圖如下:

Pinpoint-Collector收集各種效能資料、Pinpoint-Agent和自己執行的應用關聯起來的探針、Pinpoint-Web將收集到的資料顯示成WEB網頁形式、HBase Storage收集到的資料存到HBase中。

4.1 pinpoint安裝

主要涉及以下軟體的安裝:

  • jdk 1.8
    Java環境必須的,沒啥好解釋。

  • Hbase
    pinpoint收集來的測試資料,主要是存在Hbase資料庫的。所以它可以收集大量的資料,可以進行更加詳細的分析。Hbase安裝完成後,需要初始化Hbase的pinpoint庫,由pinpoint提供。Hbase內建了zookeeper。

  • pinpoint-collector
    collector收集agent的資料,將資料存到hbase叢集,對外暴露collector的tcp和udp的監聽埠9994,9995,9996。

  • pinpoint-web
    頁面展示,配置檔案中設定環境變數HBASE_HOST、HBASE_PORT等。

  • pinpoint-agent

官網release頁面下載pinpoint-agent-x-SNAPSHOT.tar.gz,配置pinpoint.config中相關collector的資訊。

安裝確實還比較麻煩,本文篇幅太長了,具體步驟後面再單獨寫文章講解。

4.2 執行pinpoint-agent

筆者使用的是spring-boot專案,所以只需要在啟動jar包的命令中加入-javaagent引數,並指定pinpoint-bootstrap包的絕對路徑。例項程式碼如下:

java -javaagent:/aoho/auth_compose/pinpoint-bootstrap-1.6.0.jar -Dpinpoint.agentId=aoho-consumer -Dpinpoint.applicationName=aoho-consumer -jar id_generator/snowflake-id-generate-1.0-SNAPSHOT.jar複製程式碼

起的id生成器服務比較簡單,沒有用到資料庫等儲存介質。服務註冊到consul上,本地客戶端請求了id-server獲取id。其呼叫鏈如下:

call tree
call tree

pinpoint提供的功能比較豐富,下圖是呼叫/api/id介面的詳細資訊。

api
api

可以看到,pinpoint記錄了客戶端的相應時間、IP地址等,呼叫樹在下面也有詳細列出,每個方法的耗時等。

serverMap
serverMap

serverMap中還展示了伺服器的堆、永久代、CPU等資訊,非常強大。

5. Skywalking

Skywalking是國內開源的APM監控元件,官網OpenSkywalking,根據官網介紹,其著力於效能和實時性兩方面。
網上找到的Skywalking的架構圖。

可以看到Skywalking也是四部分組成,collector、agent、web、storage。支援叢集部署,叢集之間還引入了grpc通訊。儲存支援內建的h2和elasticsearch儲存。

5.1 安裝

具體安裝可見官網

  • collector安裝
    此處筆者使用單機版的collector,在release頁面下載好壓縮包,解壓後,單機版的collector預設使用h2資料庫,所以配置檔案可以不需要修改,即可以執行bin/startup.sh

目錄結構如上,logs資料夾中,有啟動的日誌,可以檢視啟動情況。

  • web
    解壓好skywalking-ui,設定server的config/collector_config.properties、log4j2以及監聽埠等相關資訊,

  • agent
    拷貝skywalking-agent目錄到所需位置,探針包含整個目錄,設定/config/agent.config中的collector資訊。

5.2 執行agent

Spring boot的專案,啟動和上面pinpoint agent啟動方式相同。增加JVM啟動引數,-javaagent:/path/to/skywalking-agent/skywalking-agent.jar

這次起了user服務,涉及到mysql、redis、consul等元件。可以看到其呼叫鏈路圖如下:

當訪問/api/external/register-code/api/external/validate-code介面時,形成了上圖中的呼叫鏈。

上圖TraceId為 2.59.15103021777910001的請求/api/external/register-code。這次trace中,每個涉及的span的耗時都有在圖中統計。

上面這張圖,是對userService中的Entry Service List介面進行了統計,包括呼叫數、成功率等資訊。(因為內建的h2,這邊在UI響應很久)

還有個對instance的統計,統計jvm的相關資訊,API響應也很慢,可能與我用的儲存有關吧,就不截圖了。

6. 總結

本文主要寫了鏈路監控元件的實踐。首先介紹了鏈路監控元件產生與應用的背景,以及選擇的要求;其次介紹了opentracing中涉及的基本概念;最後大篇幅介紹了三種APM元件的安裝與使用,並展示了每種APM的UI截圖。本文比較簡單,下一篇文章主要介紹幾種APM選型的比較與效能測試。

zipkin-server-stream的原始碼
github: github.com/keets2012/S…
oschina: gitee.com/keets/sprin…

訂閱最新文章,歡迎關注我的公眾號

微信公眾號
微信公眾號


參考(瘋狂找資料)

  1. OpenTracing官方標準-中文版
  2. Skywalking
  3. Zipkin
  4. PinPoint
  5. Spring Cloud Sleuth
  6. Dapper
  7. pinpoint 安裝部署
  8. java開源APM概要
  9. 分散式系統監控系統zipkin入門
  10. 跟著小程學微服務-自己動手擴充套件分散式呼叫鏈

相關文章