Sermant运行流程学习笔记,速来抄作业
本文分享自华为云社区《Sermant 的整体流程学习梳理》,作者:用友汽车信息科技(上海)有限公司 刘亚洲 Java研发工程师。
一、sermant架构
Sermant整体架构包括Sermant Agent、Sermant Backend、Sermant Injector、动态配置中心等组件。其中Sermant Agent是提供字节码增强基础能力及各类服务治理能力的核心组件,Sermant Backend、Sermant Injector、动态配置中心为Sermant提供其他能力的配套组件。

二、java agent和bytebuddy组合使用场景
比较典型的就是skywalking、sermant、arthas、mockito。如果说java agent开了一扇门,那么bytebuddy在开的这扇门中打开了一片新的天地。
三、Sermant的入口
前面我们说AgentLauncher是java agent的入口,为什么这么说呢?
<manifestEntries>
<Premain-Class>com.huaweicloud.sermant.premain.AgentLauncher</Premain-Class>
<Agent-Class>com.huaweicloud.sermant.premain.AgentLauncher</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
答案可以从pom.xml中找到答案,这里可以看到基于Premain-Class和Agent-Class的两个类都指向了AgentLauncher这个类。因此我们可以非常确认的肯定它就是javaagent入口类。类似于java程序有一个main的执行入口,而java agent有一个自己的入口类premain。
因此可以看到它的入口执行main:
/**
* premain
*
* @param agentArgs premain启动时携带的参数
* @param instrumentation 本次启动使用的instrumentation
*/
public static void premain(String agentArgs, Instrumentation instrumentation) {
launchAgent(agentArgs, instrumentation, false);
} /**
* agentmain
*
* @param agentArgs agentmain启动时携带的参数
* @param instrumentation 本次启动使用的instrumentation
*/
public static void agentmain(String agentArgs, Instrumentation instrumentation) {
launchAgent(agentArgs, instrumentation, true);
}
基于premain模式的和基于agent模式,区别在于是否为isDynamic。从这里我们可以看到这里提出了两个类值得我们去关注:AgentCoreEntrance、CommandProcessor,也即sermant这个项目的两个重点类。
更多需要了解的,可以参考byte-buddy这个开源项目。
四、入口方法执行的全流程

五、spi的加载过程
启动核心服务的过程是spi的加载过程,此时会初始化所有的服务。也即我们看到的所有服务会在此时会做一个启动的操作,同时还会启动事件:
service.start();
collectServiceStartEvent(startServiceArray.toString());
其实这个两个方法也做了很多事情。
启动服务做的事情:

collectServiceStartEvent则调用netty客户端向netty服务端发送数据。到服务端后,服务端进行数据处理,其收集的信息提供给backend模块方便后台展示查看。
六、以标签路由为例PluginService中扩展插件初始化
除此之外,还有一批实现了BaseService接口的,也即PluginService扩展插件服务基类,以标签路由为例,可以看你的其初始化的整个过程。

七、install的过程
同时我们可以看到install对应的process方法也是执行它的方法:
public ResettableClassFileTransformer install(Instrumentation instrumentation) {
AgentBuilder builder = new Default().disableClassFormatChanges();
// 遍历actions
for (BuilderAction action : actions) {
builder = action.process(builder);
}
// 执行安装操作,此时交给bytebuddy
return builder.installOn(instrumentation);
}
从入参中的Instrumentation,我们往回看:ByteEnhanceManager.init(instrumentation)
这个方法里面定义了action的顺序。
public static void init(Instrumentation instrumentation) {
instrumentationCache = instrumentation;
builder = BufferedAgentBuilder.build();
// 初始化完成后,新增Action用于添加框架直接引入的字节码增强
enhanceForFramework();
}
执行下面的过程:

我们根据上面的添加顺序,来看初始化插件的顺序:
public static void enhanceDynamicPlugin(Plugin plugin) {
if (!plugin.isDynamic()) {
return;
}
// 获取描述信息
List<PluginDescription> plugins = PluginCollector.getDescriptions(plugin);
// 添加插件,然后执行安装操作
ResettableClassFileTransformer resettableClassFileTransformer = BufferedAgentBuilder.build()
.addPlugins(plugins).install(instrumentationCache);
plugin.setClassFileTransformer(resettableClassFileTransformer);
}
从引用上看,PluginSystemEntrance.initialize(isDynamic)中引用了这个方法。

可以看到这里的添加插件,可以理解为自定义的插件。
从sermant官网,我们可以知道:定义自定义插件,需要实现PluginDeclarer这个接口。也即从这里可以看到也即自定义的插件:
/**
* 从插件收集器中获取所有插件声明器
*
* @param classLoader 类加载器
* @return 插件声明器集
*/
private static List<? extends PluginDeclarer> getDeclarers(ClassLoader classLoader) {
final List<PluginDeclarer> declares = new ArrayList<>();
for (PluginDeclarer declarer : loadDeclarers(classLoader)) {
if (declarer.isEnabled()) {
declares.add(declarer);
}
}
return declares;
}
有了插件,就可以进行安装操作。
按照这个顺序,可以看到对应的action.process(builder)里面也执行了对应的构建方法。完成构建后,执行installOn方法。
完成安装工作后,根据安装前spi的增强实现,然后执行下游服务拦截增强,从而实现精准筛选工作。
八、以标签路由下游拦截处理为例
可以看到标签路由对应的几个代表性的Declarer:
NopInstanceFilterDeclarer、LoadBalancerDeclarer、BaseLoadBalancerDeclarer、ServiceInstanceListSupplierDeclarer等。
对应的拦截器Interceptor:
NopInstanceFilterInterceptor、LoadBalancerInterceptor、BaseLoadBalancerInterceptor、ServiceInstanceListSupplierInterceptor。
两者相互照应。
LaneServiceImpl和LoadBalancerServiceImpl是基于sermant框架的插件服务spi做的实现。
LaneServiceImpl和RouteRequestTagHandler是和路由能力相关的,LaneServiceImpl和LaneRequestTagHandler是和染色能力相关的。
RouteRequestTagHandler用来拦截并存储调用过程中的标签,FlowRouteHandler和TagRouteHandler是在路由选择下游实例时做的筛选过程。
下游拦截方法会经过BaseLoadBalancerInterceptor到loadBalancerService.getTargetInstances(serviceId, instances, requestData),最终到 HandlerChainEntry.INSTANCE.process(targetName, instances, requestData),基于责任链模式执行处理。目前主要有两种方式:FlowRouteHandler和TagRouteHandler。

这里面只是简单的介绍了整体的流程,具体细节的内容,还需要自己多实践。同时sermant大量使用了java agent的内容。
由于本人的局限性,有不妥的地方,还望批评指正!
参考:
- sermant官网: https://sermant.io/zh/
- sermant开源地址:https://github.com/huaweicloud/Sermant
- byte-buddy开源地址:https://github.com/raphw/byte-buddy
Sermant运行流程学习笔记,速来抄作业的更多相关文章
- VerilogHDL概述与数字IC设计流程学习笔记
一.HDL的概念和特征 HDL,Hard Discrimination Language的缩写,翻译过来就是硬件描述语言.那么什么是硬件描述语言呢?为什么不叫硬件设计语言呢?硬件描述语言,顾名思义就是 ...
- linux的7种运行级别<学习笔记>
Linux系统有7个运行级别(runlevel) 运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动 运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆 运行级别 ...
- FFmpeg处理音视频流程学习笔记
原文作者:一叶知秋0830 链接:https://www.jianshu.com/p/1b715966af50 FFmpeg处理音视频完整流程包括5个阶段(输入文件—>编码数据包—>解码后 ...
- Week03-Java学习笔记第三次作业
Week03-面向对象入门 1.本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识点组织起来.请使用工具画出本周学习到的知识点及知识点之间的联系. ...
- 厉害啊!第一次见到把Shiro运行流程写的这么清楚的,建议收藏起来慢慢看
前言 shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证.用户授权. spring中有spring security (原名Acegi),是一个权限框架,它和spring依赖 ...
- Kettle学习笔记(一)— 环境部署及运行
目录 Kettle学习笔记(一)-环境部署及运行 Kettle学习笔记(二)- 基本操作 kettle学习笔记(三)- 定时任务的脚本执行 Kettle学习笔记(四)- 总结 Kettle简介 Ket ...
- Kettle学习笔记(二)— 基本操作
目录 Kettle学习笔记(一)- 环境部署及运行 Kettle学习笔记(二)- 基本操作 kettle学习笔记(三)- 定时任务的脚本执行 Kettle学习笔记(四)- 总结 打开Kettle 打开 ...
- puppeteer学习笔记合集
官方英文版API入口(如果你英文好的话):https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md. 汉化版API入口(网上有 ...
- Kettle学习笔记(四)— 总结
目录 Kettle学习笔记(一)- 环境部署及运行 Kettle学习笔记(二)- 基本操作 kettle学习笔记(三)- 定时任务的脚本执行 Kettle学习笔记(四)- 总结 Kettle中设置编码 ...
- Python学习笔记(四)
Python学习笔记(四) 作业讲解 编码和解码 1. 作业讲解 重复代码瘦身 # 定义地图 nav = {'省略'} # 现在所处的层 current_layer = nav # 记录你去过的地方 ...
随机推荐
- kettle系统列文章01---安装与配置
1).到官网下载需要安装的kettle版本,目前最新版本4.2,官网地址:http://kettle.pentaho.org,我们是使用的版本是kettle3.2 2).本地安装jdk 1.4或以上版 ...
- pycharm的docstring多了一行type
注释中多了一行:type 设置为Epytext PyCharm 2020.3.5 (Community Edition) def test(param1,param2,param3): "& ...
- 【一】tensorflow【cpu/gpu、cuda、cudnn】全网最详细安装、常用python镜像源、tensorflow 深度学习强化学习教学
相关文章: [一]tensorflow安装.常用python镜像源.tensorflow 深度学习强化学习教学 [二]tensorflow调试报错.tensorflow 深度学习强化学习教学 [三]t ...
- Python 多线程实现爬取图片
前阵子网上看到有人写爬取妹子图的派森代码,于是乎我也想写一个教程,很多教程都是调用的第三方模块,今天就使用原生库来爬,并且扩展实现了图片鉴定,图片去重等操作,经过了爬站验证,稳如老狗,我已经爬了几万张 ...
- MongoDB 7.0 搭建 Sharding 副本集群
本文是在ubuntu 22.03 系统版本上部署的,最低支持mongodb-6.0.4以上,所以这里安装mongodb7.0 1 安装mongo 安装方式有多种,本人是使用的第一种方式,时间也就20分 ...
- 万字手撕AVL树 | 上百行的旋转你真的会了吗?【超用心超详细图文解释 | 一篇学会AVL】
说在前面 今天这篇博客,是博主今年以来最最用心的一篇博客.我们也很久没有更新数据结构系列了,几个月前博主用心深入的学习了这颗二叉平衡搜索树,博主被它的查找效率深深吸引. AVL树出自1962年中的一篇 ...
- 在Windows下编译Saba
今天写一篇环境配置的博客,感觉这种博客比较好写 Saba是一个用于加载MMD(MikuMikuDance)模型.动作文件的C++库.下面我们在Windows下编译这个库.为了在Windows下 ...
- 【奶奶看了都会】云服务器ChatGLM模型fine-tuning微调,让你拥有自己的知识库
1.背景 大家好啊,上次给大家写了ChatGLM-6B的部署使用教程,[奶奶看了都会]云服务器部署开源ChatGLM-6B,让你拥有自己的ChatGPT 但是因为模型比较小的问题,所以日常工作中可能用 ...
- 使用C语言构建一个独立栈协程和共享栈协程的任务调度系统
使用了标准库头文件 <setjmp.h>中的 setjmp 和 longjmp两个函数,构建了一个简单的查询式协作多任务系统,支持独立栈和共享栈两种任务. 其中涉及到获取和设置栈的地址操作 ...
- 在.NET Core下的机器学习--学习笔记
摘要 .NET Core 在机器学习的应用场景,除了 ML .NET 还会介绍一个非常棒的開源技術 TensorFlow .NET , Keras .NET. 讲师介绍 本课内容 人工智能介绍 ML ...