摘要: 原創出處 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 時的處理邏輯介面。
朋友會在“發現-看一看”看到你“在看”的內容