码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Sermant运行流程学习笔记,速来抄作业


    合集 - 开发与运维(30)
    1.面试官:你能简单聊聊MyBatis执行流程02-022.一文详解应用安全防护ESAPI02-043.一个线程,从“生”到“死”经历的过程02-054.KubeEdge v1.16.0 版本发布!10项新增特性02-055.解密JavaChassis3:易扩展的多种注册中心支持02-066.解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件02-087.想设计一个高并发的消息中间件前,先熟悉一下这些知识点02-178.华为云GES助力九洲平台:探索确定性运维的新实践02-179.0-overlay和underlay,这两种容器网络你分得清吗02-1810.教你用Rust实现Smpp协议02-1811.基于OpenTelemetry实现Java微服务调用链跟踪02-1912.揭开华为云ADN提高网络质量的秘密02-1913.详解网络知识:iptables规则02-1914.实例详解在Go中构建流数据pipeline02-2115.面试官让我讲讲MySQL三大核心日志实现原理02-2116.华为云帕鲁服务器-云耀云容器版,到底强在哪?02-2217.掌握云容器网络:何为ipvs02-2218.一文带你了解容器探针02-2319.教你如何判断Java代码中异步操作是否完成02-2620.深入解析Python并发编程的多线程和异步编程02-2721.教你如何用Keepalived和HAproxy配置高可用 Kubernetes 集群02-2822.容器化环境中,JVM最佳参数配置实践02-2923.关于Python中math 和 decimal 模块的解析与实践02-2924.运维一款月变更70+次的服务,是一种什么体验?03-0125.详解Python中sys模块的功能与应用03-0426.教你用Ubuntu快速搭建饥荒服务器03-0427.分享一个能让你的研发效率提升超过20%的工具03-0628.下一代积木式智能组装编排,集成开发效率10倍提升03-0629.如何基于容器网络流量指标进行弹性伸缩03-06
    30.Sermant运行流程学习笔记,速来抄作业03-06
    收起

    本文分享自华为云社区《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的入口,为什么这么说呢?

    复制代码
    
    
        com.huaweicloud.sermant.premain.AgentLauncher
    
        com.huaweicloud.sermant.premain.AgentLauncher
    
        true
    
        true
    
    
    复制代码

    答案可以从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 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 getDeclarers(ClassLoader classLoader) {
            final List 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

     

    点击关注,第一时间了解华为云新鲜技术~

     

  • 相关阅读:
    Promise面试题
    【机器学习】之 K-最近邻(KNN)算法原理及实现
    11-09 周四 机器学习开发容器搭建
    【C++】移动距离
    SpringBoot中使用Redis实现分布式锁
    JAVA计算机毕业设计晨光文具店进销存系统设计与开发Mybatis+源码+数据库+lw文档+系统+调试部署
    Ubuntu18.04使用turblebot3
    面试系列 - Java 并发容器详解
    10.26ALP论文原代码请稿
    少林寺方丈:禅宗与AI;高手教你DALL-E 3保持人物连续性;何时加入创业公司能拿最高回报;吴恩达新课正式发布 | ShowMeAI日报
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/18056450
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号