歡迎光臨
每天分享高質量文章

分散式鏈路追蹤 SkyWalking 原始碼分析 —— Agent DictionaryManager 字典管理

摘要: 原創出處 http://www.iocoder.cn/SkyWalking/agent-dictionary/ 「芋道原始碼」歡迎轉載,保留摘要,謝謝!

  • 1. 概述
  • 2. Collector 同步相關 API
    • 2.1 應用的同步 API
    • 2.2 操作的同步 API
  • 3. Agent 呼叫同步 API
    • 3.1 DictionaryManager
    • 3.2 PossibleFound

       


1. 概述

本文主要分享 Agent DictionaryManager 字典管理。先來簡單瞭解下字典的定義和用途:

  • 字典實際上是一個 Map 對映。目前 Agent 上有兩種字典:應用編碼與應用編號的對映,操作名與操作編號的對映。
    • 應用的定義:例如,Tomcat 啟動的應用,或者程式裡訪問的 MongoDB 、MySQL 都可以認為是應用。
    • 操作的定義:例如,訪問的 URL 地址,Mongo 的執行操作。
  • Agent 在每次上傳呼叫鏈路 Segment 給 Collector 時,Segment 裡面需要包含應用和操作相關資訊。考慮到減少網路流量,應用編號少於應用編號,操作編號少於操作名。

Agent 字典,會定時從 Collector 【同步需要( 需要的定義,下文程式碼會看到 )的字典。

下麵,我們分成兩個小節,分別從 API 的實現呼叫,分享程式碼的具體實現。

2. Collector 同步相關 API

Collector 同步相關 API 相關有四個介面:

  • 2.1 應用的同步 API
  • 2.2 操作的同步 API

API 處理的流程大體如下:

2.1 應用的同步 API

應用的同步 API ,實際使用的是應用的註冊 API,在 「2.1 應用的註冊 API」 有詳細解析。

2.2 操作的同步 API

我們先來看看 API 的定義,DiscoveryService ,如下圖所示:

整體程式碼和 「2.1 應用的同步 API」 非常相似,所以本小節,更多的是提供程式碼的連結地址。

2.2.1 ServiceNameDiscoveryServiceHandler#discovery(…)

ServiceNameDiscoveryServiceHandler#discovery(ServiceNameCollection, StreamObserver),根據操作名陣列,查詢操作編號陣列。

2.2.2 IServiceNameService#getOrCreate(…)

org.skywalking.apm.collector.agent.stream.service.register.IServiceNameService,繼承 Service 介面,操作名服務介面。

  • 定義了 `#getOrCreate(applicationId, serviceName)` 介面方法,根據應用編號 + 操作名字,獲取或建立操作名( ServiceName ),並獲得操作編號。

org.skywalking.apm.collector.agent.stream.worker.register.ServiceNameService ,實現 IServiceNameService 介面,操作名服務實現類。

  • 實現了 `#getOrCreate(applicationId, serviceName)` 方法。

2.2.3 Graph#start(ServiceName)

在 #createServiceNameRegisterGraph() 方法中,我們可以看到 ServiceName 對應的 Graph 物件的建立。

  • `org.skywalking.apm.collector.agent.stream.worker.register.ServiceNameRegisterRemoteWorker`,繼承 AbstractRemoteWorker 抽象類,操作名註冊遠端 Worker 。
  • `org.skywalking.apm.collector.agent.stream.worker.register.ServiceNameRegisterSerialWorker`,繼承 AbstractLocalAsyncWorker 抽象類,非同步儲存應用 Worker 。
    • 相同於 Application ,ServiceName 的操作編號,從 `”1″` 雙向遞增。
    • ServiceNameEsRegisterDAO#save(ServiceName)

2.2.4 ServiceName

org.skywalking.apm.collector.storage.table.register.ServiceName ,操作名。例如記錄在 ES 如下圖:

3. Agent 呼叫同步 API

在 《SkyWalking 原始碼分析 —— 應用於應用實體的註冊》「3. Agent 呼叫註冊 API」 一文中,在 【第 170 至 173 行】的程式碼,我們可以看到,AppAndServiceRegisterClient 會定時從 Collector 同步所有字典資訊。

3.1 DictionaryManager

org.skywalking.apm.agent.core.dictionary.DictionaryManager ,字典管理器。目前管理有兩種字典:

  • ApplicationDictionary
  • OperationNameDictionary

3.1 ApplicationDictionary

org.skywalking.apm.agent.core.dictionary.ApplicationDictionary ,應用字典。

  • INSTANCE 列舉屬性,單例。
  • applicationDictionary 屬性,應用編碼與應用編號的對映。
  • unRegisterApplications 屬性,未知應用編碼集合。Agent 會定時從 Collector 同步。這也是文章開頭說的,“需要”的定義。

#find(applicationCode) 方法,根據應用編碼,查詢應用編號。

  • 第 57 行:根據應用編碼,從 applicationDictionary 中,查詢應用編號。
  • 第 58 至 59 行:當應用編號查詢到時,傳回 Found 。Found 會在下文詳細解析。
  • 第 61 至 64 行:當應用編號查詢不到時,新增到 unRegisterApplications 中,傳回 NotFound 。NotFound 會在下文詳細解析。

#syncRemoteDictionary(ApplicationRegisterServiceGrpc.ApplicationRegisterServiceBlockingStub)方法,呼叫 「2.1 應用的同步 API」 ,從 Collector 同步 unRegisterApplications 對應的應用編號集合。

3.2 OperationNameDictionary

org.skywalking.apm.agent.core.dictionary.OperationNameDictionary ,操作名字典。

和 ApplicationDictionary 基本類似,胖友點選 程式碼 ,自己閱讀理解。

3.2 PossibleFound

在分享 PossibleFound 之前,我們先來看一段程式碼,瞭解該類的意圖:

  • 我們在使用 XXXXDictionary#find(xxx) 方法時,傳回的會是 Found 或者 NotFound 。這兩個類本身是互斥的,並且繼承 PossibleFound 。在 PossibleFound 提供 #doInCondition(method01, method02) 方法,優雅的處理兩種情況。

org.skywalking.apm.agent.core.dictionary.PossibleFound ,抽象類,程式碼如下:

  • found 屬性,是否找到。
  • value 屬性,找到的結果。
  • org.skywalking.apm.agent.core.dictionary.Found 實現 PossibleFound 類,found = true 並且 value 為找到的值。
  • org.skywalking.apm.agent.core.dictionary.NotFound 實現 PossibleFound 類,found = false 並且 value 不賦值。
  • `#doInCondition(Found, NotFound)` 方法,根據查詢結果,執行不同的邏輯,【無傳回】。
    • 第一個引數,`PossibleFound.Found` 介面,Found 時的處理邏輯介面。
    • 第二個引數,`PossibleFound.NotFound` 介面,NotFound 時的處理邏輯介面。
  • `#doInCondition(FoundAndObtain, NotFoundAndObtain)` 方法,根據查詢結果,執行不同的邏輯,【有傳回】。
    • 第一個引數,`PossibleFound.FoundAndObtain` 介面,Found 時的處理邏輯介面。
    • 第二個引數,`PossibleFound.NotFoundAndObtain` 介面,NotFound 時的處理邏輯介面。

已同步到看一看
贊(0)

分享創造快樂