微服務(wù)調(diào)用鏈追蹤中心搭建

封面圖片

概述

一個(gè)完整的微服務(wù)系統(tǒng)包含多個(gè)微服務(wù)單元,各個(gè)微服務(wù)子系統(tǒng)存在互相調(diào)用的情況限匣,形成一個(gè) 調(diào)用鏈。一個(gè)客戶端請(qǐng)求從發(fā)出到被響應(yīng) 經(jīng)歷了哪些組件哮奇、哪些微服務(wù)膛腐、請(qǐng)求總時(shí)長(zhǎng)每個(gè)組件所花時(shí)長(zhǎng) 等信息我們有必要了解和收集鼎俘,以幫助我們定位性能瓶頸哲身、進(jìn)行性能調(diào)優(yōu),因此監(jiān)控整個(gè)微服務(wù)架構(gòu)的調(diào)用鏈?zhǔn)钟斜匾撤ィ疚膶㈥U述如何使用 Zipkin 搭建微服務(wù)調(diào)用鏈追蹤中心勘天。

注: 本文原載于 My Personal Blog:CodeSheep · 程序羊 捉邢!


Zipkin初摸

正如 Ziplin官網(wǎng) 所描述脯丝,Zipkin是一款分布式的追蹤系統(tǒng),其可以幫助我們收集微服務(wù)架構(gòu)中用于解決延時(shí)問題的時(shí)序數(shù)據(jù)伏伐,更直白地講就是可以幫我們追蹤調(diào)用的軌跡宠进。

Zipkin的設(shè)計(jì)架構(gòu)如下圖所示:

Zipkin設(shè)計(jì)架構(gòu)

要理解這張圖,需要了解一下Zipkin的幾個(gè)核心概念:

  • Reporter

在某個(gè)應(yīng)用中安插的用于發(fā)送數(shù)據(jù)給Zipkin的組件稱為Report藐翎,目的就是用于追蹤數(shù)據(jù)收集

  • Span

微服務(wù)中調(diào)用一個(gè)組件時(shí)材蹬,從發(fā)出請(qǐng)求開始到被響應(yīng)的過(guò)程會(huì)持續(xù)一段時(shí)間,將這段跨度稱為Span

  • Trace

從Client發(fā)出請(qǐng)求到完成請(qǐng)求處理吝镣,中間會(huì)經(jīng)歷一個(gè)調(diào)用鏈堤器,將這一個(gè)整個(gè)過(guò)程稱為一個(gè)追蹤(Trace)。一個(gè)Trace可能包含多個(gè)Span末贾,反之每個(gè)Span都有一個(gè)上級(jí)的Trace闸溃。

  • Transport

一種數(shù)據(jù)傳輸?shù)姆绞剑热缱詈?jiǎn)單的HTTP方式拱撵,當(dāng)然在高并發(fā)時(shí)可以換成Kafka等消息隊(duì)列


看了一下基本概念后辉川,再結(jié)合上面的架構(gòu)圖,可以試著理解一下拴测,只有裝配有Report組件的Client才能通過(guò)Transport來(lái)向Zipkin發(fā)送追蹤數(shù)據(jù)员串。追蹤數(shù)據(jù)由Collector收集器進(jìn)行手機(jī)然后持久化到Storage之中。最后需要數(shù)據(jù)的一方昼扛,可以通過(guò)UI界面調(diào)用API接口,從而最終取到Storage中的數(shù)據(jù)〕常可見整體流程不復(fù)雜渺鹦。

Zipkin官網(wǎng)給出了各種常見語(yǔ)言支持的OpenZipkin libraries:

OpenZipkin libraries

本文接下來(lái)將 構(gòu)造微服務(wù)追蹤的實(shí)驗(yàn)場(chǎng)景 并使用 Brave 來(lái)輔助完成微服務(wù)調(diào)用鏈追蹤中心搭建!


部署Zipkin服務(wù)

利用Docker來(lái)部署Zipkin服務(wù)再簡(jiǎn)單不過(guò)了:

docker run -d -p 9411:9411 \
--name zipkin \
docker.io/openzipkin/zipkin

完成之后瀏覽器打開:localhost:9411可以看到Zipkin的可視化界面:

Zipkin可視化界面

模擬微服務(wù)調(diào)用鏈

我們來(lái)構(gòu)造一個(gè)如下圖所示的調(diào)用鏈:

微服務(wù)調(diào)用鏈

圖中包含 一個(gè)客戶端 + 三個(gè)微服務(wù)

  • Client:使用/servicea接口消費(fèi)ServiceA提供的服務(wù)

  • ServiceA:使用/serviceb接口消費(fèi)ServiceB提供的服務(wù)蛹含,端口8881

  • ServiceB:使用/servicec接口消費(fèi)ServiceC提供的服務(wù)毅厚,端口8882

  • ServiceC:提供終極服務(wù),端口8883

為了模擬明顯的延時(shí)效果浦箱,準(zhǔn)備在每個(gè)接口的響應(yīng)中用代碼加入3s的延時(shí)吸耿。

簡(jiǎn)單起見,我們用SpringBt來(lái)實(shí)現(xiàn)三個(gè)微服務(wù)酷窥。

ServiceA的控制器代碼如下:

@RestController
public class ServiceAContorller {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/servicea”)
    public String servicea() {
        try {
            Thread.sleep( 3000 );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return restTemplate.getForObject("http://localhost:8882/serviceb", String.class);
    }
}

ServiceB的代碼如下:

@RestController
public class ServiceBContorller {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/serviceb”)
    public String serviceb() {
        try {
            Thread.sleep( 3000 );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return restTemplate.getForObject("http://localhost:8883/servicec", String.class);
    }
}

ServiceC的代碼如下:

@RestController
public class ServiceCContorller {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/servicec”)
    public String servicec() {
        try {
            Thread.sleep( 3000 );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Now, we reach the terminal call: servicec !”;
    }
}

我們將三個(gè)微服務(wù)都啟動(dòng)起來(lái)咽安,然后瀏覽器中輸入localhost:8881/servicea來(lái)發(fā)出請(qǐng)求,過(guò)了9s之后蓬推,將取到ServiceC中提供的微服務(wù)接口所返回的內(nèi)容妆棒,如下圖所示:

微服務(wù)鏈?zhǔn)秸{(diào)用結(jié)果

很明顯,調(diào)用鏈可以正常work了沸伏!

那么接下來(lái)我們就要引入Zipkin來(lái)追蹤這個(gè)調(diào)用鏈的信息糕珊!

編寫與Zipkin通信的工具組件

從Zipkin官網(wǎng)我們可以知道,借助OpenZipkin庫(kù)Brave毅糟,我們可以開發(fā)一個(gè)封裝Brave的公共組件红选,讓其能十分方便地嵌入到ServiceA,ServiceB姆另,ServiceC服務(wù)之中喇肋,完成與Zipkin的通信。

為此我們需要建立一個(gè)新的基于Maven的Java項(xiàng)目:ZipkinTool

  • pom.xml中加入如下依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hansonwang99</groupId>
    <artifactId>ZipkinTool</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.0.1.RELEASE</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.7.RELEASE</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.zipkin.brave</groupId>
            <artifactId>brave-spring-web-servlet-interceptor</artifactId>
            <version>4.0.6</version>
        </dependency>
        <dependency>
            <groupId>io.zipkin.brave</groupId>
            <artifactId>brave-spring-resttemplate-interceptors</artifactId>
            <version>4.0.6</version>
        </dependency>
        <dependency>
            <groupId>io.zipkin.reporter</groupId>
            <artifactId>zipkin-sender-okhttp3</artifactId>
            <version>0.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

</project>
  • 編寫ZipkinProperties類

其包含endpoint和service兩個(gè)屬性蜕青,我們最后是需要將該兩個(gè)參數(shù)提供給ServiceA苟蹈、ServiceB、ServiceC微服務(wù)作為其application.properties中的Zipkin配置

@Data
@Component
@ConfigurationProperties("zipkin")
public class ZipkinProperties {
    private String endpoint;
    private String service;
}

用了lombok之后右核,這個(gè)類異常簡(jiǎn)單慧脱!

【注意:關(guān)于lombok的用法,可以看這里

  • 編寫ZipkinConfiguration類

這個(gè)類很重要贺喝,在里面我們將Brave的BraveClientHttpRequestInterceptor攔截器注冊(cè)到RestTemplate的攔截器調(diào)用鏈中來(lái)收集請(qǐng)求數(shù)據(jù)到Zipkin中菱鸥;同時(shí)還將Brave的ServletHandlerInterceptor攔截器注冊(cè)到調(diào)用鏈中來(lái)收集響應(yīng)數(shù)據(jù)到Zipkin中

上代碼吧:

@Configuration
@Import({RestTemplate.class, BraveClientHttpRequestInterceptor.class, ServletHandlerInterceptor.class})
public class ZipkinConfiguration extends WebMvcConfigurerAdapter {

    @Autowired
    private ZipkinProperties zipkinProperties;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private BraveClientHttpRequestInterceptor clientInterceptor;

    @Autowired
    private ServletHandlerInterceptor serverInterceptor;

    @Bean
    public Sender sender() {
        return OkHttpSender.create( zipkinProperties.getEndpoint() );
    }

    @Bean
    public Reporter<Span> reporter() {
        return AsyncReporter.builder(sender()).build();
    }

    @Bean
    public Brave brave() {
        return new Brave.Builder(zipkinProperties.getService()).reporter(reporter()).build();
    }

    @Bean
    public SpanNameProvider spanNameProvider() {
        return new SpanNameProvider() {
            @Override
            public String spanName(HttpRequest httpRequest) {
                return String.format(
                        "%s %s",
                        httpRequest.getHttpMethod(),
                        httpRequest.getUri().getPath()
                );
            }
        };
    }

    @PostConstruct
    public void init() {
        List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
        interceptors.add(clientInterceptor);
        restTemplate.setInterceptors(interceptors);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(serverInterceptor);
    }
}

ZipkinTool完成以后,我們需要在ServiceA躏鱼、ServiceB氮采、ServiceC三個(gè)SpringBt項(xiàng)目的application.properties中加入Zipkin的配置:

以ServiceA為例:

server.port=8881
zipkin.endpoint=http://你Zipkin服務(wù)所在機(jī)器的IP:9411/api/v1/spans
zipkin.service=servicea

我們最后依次啟動(dòng)ServiceA、ServiceB染苛、和ServiceC三個(gè)微服務(wù)鹊漠,并開始實(shí)驗(yàn)來(lái)收集鏈路追蹤數(shù)據(jù) 主到!


實(shí)際實(shí)驗(yàn)

1. 依賴分析

瀏覽器打開Zipkin的UI界面,可以查看 依賴分析

點(diǎn)擊依賴分析

圖中十分清晰地展示了ServiceA躯概、ServiceB和ServiceC三個(gè)服務(wù)之間的調(diào)用關(guān)系登钥!
注意,該圖可縮放娶靡,并且每一個(gè)元素均可以點(diǎn)擊牧牢,例如點(diǎn)擊 ServiceB這個(gè)微服務(wù),可以看到其調(diào)用鏈的上下游姿锭!

點(diǎn)擊ServiceB微服務(wù)

2. 查找調(diào)用鏈

接下來(lái)我們看一下調(diào)用鏈相關(guān)塔鳍,點(diǎn)擊 服務(wù)名,可以看到Zipkin監(jiān)控到個(gè)所有服務(wù):

查找調(diào)用鏈

同時(shí)可以查看Span呻此,如以ServiceA為例轮纫,其所有REST接口都再下拉列表中:

查看Span

以ServiceA為例,點(diǎn)擊 Find Traces趾诗,可以看到其所有追蹤信息:

Find Traces

點(diǎn)擊某個(gè)具體Trace蜡感,還能看到詳細(xì)的每個(gè)Span的信息,如下圖中恃泪,可以看到 A → B → C 調(diào)用過(guò)程中每個(gè)REST接口的詳細(xì)時(shí)間戳:

某一個(gè)具體Trace

點(diǎn)擊某一個(gè)REST接口進(jìn)去還能看到更詳細(xì)的信息郑兴,如查看/servicec這個(gè)REST接口,可以看到從發(fā)送請(qǐng)求到收到響應(yīng)信息的所有詳細(xì)步驟:

某一個(gè)具體Span詳細(xì)信息

后記

由于能力有限贝乎,若有錯(cuò)誤或者不當(dāng)之處情连,還請(qǐng)大家批評(píng)指正,一起學(xué)習(xí)交流览效!



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末却舀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锤灿,更是在濱河造成了極大的恐慌挽拔,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件但校,死亡現(xiàn)場(chǎng)離奇詭異螃诅,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)状囱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門术裸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人亭枷,你說(shuō)我怎么就攤上這事袭艺。” “怎么了叨粘?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵猾编,是天一觀的道長(zhǎng)瘤睹。 經(jīng)常有香客問我,道長(zhǎng)答倡,這世上最難降的妖魔是什么默蚌? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮苇羡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鼻弧。我一直安慰自己设江,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布攘轩。 她就那樣靜靜地躺著叉存,像睡著了一般。 火紅的嫁衣襯著肌膚如雪度帮。 梳的紋絲不亂的頭發(fā)上歼捏,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音笨篷,去河邊找鬼瞳秽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛率翅,可吹牛的內(nèi)容都是我干的练俐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冕臭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼腺晾!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起辜贵,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤悯蝉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后托慨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鼻由,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年榴芳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嗡靡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窟感,死狀恐怖讨彼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柿祈,我是刑警寧澤哈误,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布哩至,位于F島的核電站,受9級(jí)特大地震影響蜜自,放射性物質(zhì)發(fā)生泄漏菩貌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一重荠、第九天 我趴在偏房一處隱蔽的房頂上張望箭阶。 院中可真熱鬧,春花似錦戈鲁、人聲如沸仇参。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诈乒。三九已至,卻和暖如春婆芦,著一層夾襖步出監(jiān)牢的瞬間怕磨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工消约, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肠鲫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓荆陆,卻偏偏與公主長(zhǎng)得像滩届,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子被啼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理帜消,服務(wù)發(fā)現(xiàn),斷路器浓体,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 在本節(jié)內(nèi)容之前泡挺,我們已經(jīng)對(duì)如何引入Sleuth跟蹤信息和搭建Zipkin服務(wù)端分析跟蹤延遲的過(guò)程做了詳細(xì)的介紹,相...
    程序猿DD閱讀 1,113評(píng)論 0 4
  • 普元推出DevOps系列課程命浴,5分鐘秒懂一個(gè)知識(shí)點(diǎn)娄猫,戳“閱讀原文”充電5分鐘,掌握黑科技生闲。 轉(zhuǎn)載本文需注明出處:微...
    72a1f772fe47閱讀 4,520評(píng)論 0 0
  • 今天.... 回去學(xué)校拿證 跟老友說(shuō)好了 然.... 拿到了這么一張合格證書 是的媳溺,三年了… 我拿到了 回到學(xué)校拿...
    夢(mèng)茹Taken閱讀 201評(píng)論 0 1
  • Susan沒有更新將近兩個(gè)月的公眾號(hào),并用這本雜志給予了她的成果碍讯。我真的很是期待悬蔽,但是當(dāng)我得到這本書的時(shí)候,并沒有...
    DL諾爾閱讀 443評(píng)論 0 0