Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Sermant的整体流程学习梳理

Sermant的整体流程学习梳理

作者头像
路行的亚洲
发布于 2024-02-27 09:17:26
发布于 2024-02-27 09:17:26
42000
代码可运行
举报
文章被收录于专栏:后端技术学习后端技术学习
运行总次数:0
代码可运行

一、Sermant的架构

Sermant整体架构包括Sermant Agent、Sermant Backend、Sermant Injector、动态配置中心等组件。其中Sermant Agent是提供字节码增强基础能力及各类服务治理能力的核心组件,Sermant Backend、Sermant Injector、动态配置中心为Sermant提供其他能力的配套组件。下图来源sermant官网:

二、Sermant的入口

前面我们说AgentLauncher是java agent的入口,为什么这么说呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  <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:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /**
     * 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的加载过程,此时会初始化所有的服务。也即我们看到的所有服务会在此时会做一个启动的操作,同时还会启动事件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
service.start();
collectServiceStartEvent(startServiceArray.toString());

其实这个两个方法也做了很多事情。

步骤14中启动服务做的事情:

collectServiceStartEvent则调用netty客户端向netty服务端发送数据。到服务端后,服务端进行数据处理,其收集的信息提供给backend模块方便后台展示查看。

五、以标签路由为例PluginService中扩展插件初始化

除此之外,还有一批实现了BaseService接口的,也即PluginService扩展插件服务基类,以标签路由为例,可以看你的其初始化的整个过程。

六、install的过程

同时我们可以看到install对应的process方法也是执行它的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  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的顺序。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public static void init(Instrumentation instrumentation) {
        instrumentationCache = instrumentation;
        builder = BufferedAgentBuilder.build();

        // 初始化完成后,新增Action用于添加框架直接引入的字节码增强
        enhanceForFramework();
    }

执行下面的过程:

我们根据上面的添加顺序,来看初始化插件的顺序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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这个接口。也即从这里可以看到也即自定义的插件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 /**
     * 从插件收集器中获取所有插件声明器
     *
     * @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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java agent和byte-buddy组合的简单使用
java agent开了一扇门,bytebuddy在开的这扇门中打开了一片新的天地。比较典型的就是skywalking、sermant、arthas、mockito、fastjson等。是不是很好奇skywalking、sermant、arthas、mockito、fastjson的原理。下面我们来了解一下。
路行的亚洲
2024/02/17
1K0
java agent和byte-buddy组合的简单使用
如何低侵入的记录调用日志
前阵子朋友他老大叫他实现这么一个功能,就是低侵入的记录接口每次的请求响应日志,然后并统计每次请求调用的成功、失败次数以及响应耗时,当时朋友的实现思路是在每个业务的controller的方法上加一个自定义注解,然后写一个aop,以这个自定义注解为pointcut来记录日志。
lyb-geek
2022/01/07
5120
如何低侵入的记录调用日志
快速学习-Skywalking原理
上文中我们知道,要使用Skywalking去监控服务,需要在其 VM 参数中添加 “- javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar"。这里就 使用到了java agent技术。
cwl_java
2020/08/10
2.9K0
快速学习-Skywalking原理
如何低侵入的记录调用日志
前阵子朋友他老大叫他实现这么一个功能,就是低侵入的记录接口每次的请求响应日志,然后并统计每次请求调用的成功、失败次数以及响应耗时,当时朋友的实现思路是在每个业务的controller的方法上加一个自定义注解,然后写一个aop,以这个自定义注解为pointcut来记录日志。
lyb-geek
2021/05/05
1.1K0
如何低侵入的记录调用日志
Skywalking之Java Agent基础
之前的文章提到,要用 Skywalking 监控一个应用,需要在其 VM 参数中添加 “-javaagent:skywalking-agent.jar”(省略skywalking-agent.jar的完整路径),这其实用了Java探针技术,算是个比较老的技术了,本节就简单介绍一下Java Agent。
Bug开发工程师
2019/10/15
3.6K0
Skywalking之Java Agent基础
java运行时创建或修改类-JavaAgent
在运维监控系统开发过程中我们往往需要在特定的方法出入口进行记录日志、采集参数,甚至在特定场景下需要对方法的出入参数或者整个方法逻辑进行重写。目前市面上开源的APM系统主要有CAT、Zipkin、Pinpoint、SkyWalking,大都是参考Google的Dapper实现的。个人在项目中主要使用skywallking,在java、golang等多语言中有过实践,所以这里主要记录自己在java项目中使用skywallking的一些心得和笔记。
lelezc
2023/09/21
7490
Java Agent(一)、初步认识Instrumentation
Instrumentation 是 Java SE 5 引入的一套 API,它允许开发者在运行时修改类的字节码。Java Instrumentation 可以实现在方法插入额外的字节码从而达到收集使用中的数据到指定工具的目的。Java.lang.instrument包的最大功能就是可以在已有的类上附加(修改)字节码来实现增强的逻辑,它最常见的用途包括:
有一只柴犬
2024/12/10
3360
Java Agent(一)、初步认识Instrumentation
054. SkyWalking
1. APM系统 ---- 1.1. APM系统概述 APM (Application Performance Management) 即应用性能管理系统,是对企业系统即时监控以实现对应用程序性能管理和故障管理的系统化的解决方案。应用性能管理,主要指对企业的关键业务应用进行监测、优化,提高企业应用的可靠性和质量,保证用户得到良好的服务,降低 IT 总拥有成本。 APM系统是可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。 1.2. 分布式链路追踪 随着分布式系统和微
山海散人
2021/03/03
1.9K0
054. SkyWalking
javaAgent入门
在Java编程语言中,Java Agent是一种特殊的Java程序,它可以在Java应用程序运行时修改或监视字节码。Java Agent通常通过Java虚拟机 (JVM) 的Instrumentation API来实现这一点。
杨不易呀
2023/11/18
1K0
javaAgent入门
JVM 字节码增强技术之 Java Agent 入门
分布式链路追踪中为了获取服务之间调用链信息,采集器通常需要在方法的前后做埋点。在 Java 生态中,常见的埋点方式有两种:
高楼Zee
2021/10/27
1.5K0
动态追踪之java agent
上篇文章我们说到阿里的诊断工具Arthas对方法和类的监控使用的是动态追踪技术,本文我们将介绍动态追踪技术Java Agent。
索码理
2022/12/28
9530
动态追踪之java agent
Java Agent (JVM Instrumentation 机制) 极简教程
Java 代理 (agent) 是在你的main方法前的一个拦截器 (interceptor),也就是在main方法执行之前,执行agent的代码。
一个会写诗的程序员
2021/04/15
10.7K0
字节码调试的入口 —— JVM 的寄生插件 javaagent 那些事
Java Instrumentation 这个技术看起来非常神秘,很少有书会详细介绍。但是有很多工具是基于 Instrumentation 来实现的:
架构狂人
2023/08/16
1.1K0
字节码调试的入口 —— JVM 的寄生插件 javaagent 那些事
Java 调试工具、热部署、JVM 监控工具都用到了它
我们平时写 Java Agent 的机会确实不多,也可以说几乎用不着。但其实我们一直在用它,而且接触的机会非常多。下面这些技术都使用了 Java Agent 技术,看一下你就知道为什么了。
猿天地
2019/09/25
1K0
Java 调试工具、热部署、JVM 监控工具都用到了它
基于JavaAgent的全链路监控三《ByteBuddy操作监控方法字节码》
案例简述 在第二章中我们已经可以监控方法执行耗时,虽然它能完成我们一些基本需要,但是为了增强代码的扩展性,我们需要使用字节码操作工具ByteBuddy来帮助我们实现更完善的监控程序。
小傅哥
2020/07/14
2.2K0
深入理解Instrument(一)
很早之前就了解到目前主流的APM开源框架如Pinpoint、SkyWalking等等都是通过java.lang.instrument包提供的字节码增强功能来实现的。趁着对这块的热情还没消退,抽时间分析一下java.lang.instrument包的使用方式,记录下来写成一个系列的文章。本系列博文针对的是JDK11,其他版本的JDK可能不适合。
Throwable
2020/06/23
3.1K0
深入理解Instrument(一)
认识 JavaAgent --获取目标进程已加载的所有类
之前在一个应用中搜索到一个类,但是在反序列化测试时出错,错误不是class notfound,是其他0xxx这样的错误,通过搜索,这个错误大概是类没有被加载。最近刚好看到了JavaAgent,初步学习了下,能进行拦截,主要通过Instrument Agent来进行字节码增强,可以进行字节码插桩,bTrace,Arthas 等操作,结合ASM,javassist,cglib框架能实现更强大的功能。Java RASP也是基于JavaAgent实现的。趁热记录下JavaAgent基础概念,以及简单使用JavaAgent实现一个获取目标进程已加载的类的测试。
Seebug漏洞平台
2019/12/16
2.3K0
认识 JavaAgent --获取目标进程已加载的所有类
javaAgent通过字节码对方法增强和使用 byte-buddy 来实现类的增强
在上一篇讲述了入门和实操https://cloud.tencent.com/developer/article/2360594 本章节使用字节码和byte-buddy来玩
杨不易呀
2023/11/19
1.3K0
javaAgent通过字节码对方法增强和使用 byte-buddy 来实现类的增强
Java Agent 简介
Java Agent 这个技术出现在 JDK1.5 之后,对于大多数人来说都比较陌生,但是多多少少又接触过,实际上,我们平时用的很多工具,都是基于 Java Agent 实现的,例如常见的热部署 JRebel,各种线上诊断工具(Btrace, Greys),还有阿里开源的 Arthas。
JMCui
2020/03/26
1K0
IDEA + maven 零基础构建 java agent 项目
Java Agent(java 探针)虽说在 jdk1.5 之后就有了,但是对于绝大多数的业务开发 javaer 来说,这个东西还是比较神奇和陌生的;虽说在实际的业务开发中,很少会涉及到 agent 开发,但是每个 java 开发都用过,比如使用 idea 写了个 HelloWorld.java,并运行一下, 仔细看控制台输出
一灰灰blog
2020/03/20
2.3K0
IDEA + maven 零基础构建 java agent 项目
相关推荐
java agent和byte-buddy组合的简单使用
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档