分布式链路追踪 SkyWalking 源码分析 —— Agent DictionaryManager
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<ServiceNameMappingCollection>)
,根据操作名数组,查找操作编号数组。
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<ServiceName>
对象的创建。
`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 时的处理逻辑接口。
更多相关文章
- 基于Spring Boot实现图片上传/加水印一把梭操作
- linux系统重启操作系统后报错提示An error occurred during the
- linux系统操作系统网卡漂移解决方案及问题原因
- linux操作系统可以ping通ssh连接无响应
- 操作系统分配存储时网络无法正常连接
- 一篇文章完全掌握 JavaScript 数组操作[每日前端夜话0x87]
- C#基础入门第十二天(面向对象多态,File操作流,泛型集合)
- 安利 5 个拍案叫绝的 Matplotlib 骚操作!
- pandas100个骚操作:JSON自动解析为DataFrame