解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件

这篇具有很好参考价值的文章主要介绍了解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文分享自华为云社区《服务运行时动态挂载JavaAgent和插件——Sermant热插拔能力解析》,作者:华为云高级软件工程师 栾文飞

一、概述

Sermant是基于Java字节码增强技术的无代理服务网格,其利用Java字节码增强技术,为宿主应用程序提供服务治理功能,以解决大规模微服务场景中的服务治理问题,通过Java字节码增强技术,可以非侵入的提供服务治理能力。在以往版本中,Sermant通过配置-javaagent指令在微服务启动时接入服务治理能力,当需要接入及卸载Sermant时都需要通过重新启动微服务来完成。但从1.2.0版本开始,Sermant实现了在服务不停机状态下进行安装和卸载的能力,为服务治理能力带来全新接入体验。本文将会对这种动态接入的机制,从技术基础到Sermant设计进行一次深入分析。

二、JavaAgent加载方式

首先介绍一下JavaAgent的不同接入方式,这是Sermant实现动态接入能力的技术基础。Java 中Instrumentation API 提供了一种修改字节码的机制,利用该API,可以通过修改字节码的方式来改变程序的行为,而不用触及程序的源码。JavaAgent为Instrumentation API的客户端,通过JavaAgent可以调用API进行字节码的操作,其提供了两种加载方式给开发者重载:

  • 静态加载:利用premain,在应用程序启动时加载 JavaAgent称为静态加载,静态加载会在启动时在执行任何代码之前修改字节码。

解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件,开发与运维,华为云开发者联盟,华为云,开发,微服务,JavaAgent,Sermant

静态加载时,字节码增强是在类加载时发生的,当Java程序启动时,类加载过程中所有被加载的类都会经过JavaAgent所定义的类文件转换器的处理。

  • 动态加载:利用agentmain通过Java Attach API将JavaAgent加载到已运行的JVM中,动态加载可以通过字节码重转换的方式在运行时修改字节码。

解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件,开发与运维,华为云开发者联盟,华为云,开发,微服务,JavaAgent,Sermant

动态加载时,和静态加载不同的是,此时JVM已在运行,目标类已被加载,就不能像静态加载时一样触发字节码增强过程,在使用动态加载的过程中,往.往会通过Instrumentation API来触发目标类(当然也可以指定所有已被加载的类)的重转换过程,在重转换过程中就会触发到Agent构建的类文件转换器,从而完成字节码增强过程。

动态加载方式为JavaAgent提供了在JVM运行时接入的能力,但通过类重转换来触发字节码增强相对于在类加载时增强有一定的局限性,例如不能在增强时修改类的继承关系,不能为类添加静态代码块,不能增强内存中和资源文件中字节码不一致的类等,这些也是在使用动态加载和多JavaAgent场景中常见的问题,综上,两种加载方式各有利弊,可以在使用时按照业务场景选择。

三、Sermant热插拔能力关键问题剖析

在了解技术基础后,我们能轻易的想到,理论上基于JavaAgent的动态加载方式,只需要在使用Sermant时,将通过premain方式启动改为通过agentmain方式启动,就可以将微服务治理能力动态的接入到微服务中,做到微服务零侵入、微服务不停机的状态下接入服务治理能力,但通往前方的路上总是充满了障碍:

3.1 如何保证动态安装过程中重转换可顺利执行?

这个问题的出现,根源在于JavaAgent通过agentmain方式加载到已运行的JVM中时,不同于静态加载,会在类初次被加载时完成字节码的转换,动态加载时一些需要被字节码增强类已经完成了类加载过程,这时候需要使用Instrumentation提供的类重转换(retransform classes)能力来修改字节码,在Instrumentation的Javadoc中关于这个能力有这样一段描述:

“The retransformation must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.(重转换过程中,我们不能新增、删除或者重命名字段和方法,不能更改方法的签名,不能更改类的继承。)”

从中可以看出,在引入动态加载能力前,优先要保证字节码增强时,不可以有上述内容中所描述的限制操作。

不过Sermant不太需要担心这个问题,因为这种限制不仅仅在动态加载时会触发,在多个JavaAgent同时使用时也可能会触发,可以参考Sermant团队的另一篇文章:《记一次多个JavaAgent同时使用的类增强冲突问题及分析》。为了保证在多Agent场景下的兼容性,Sermant的字节码增强模板严格遵循Instrumentation API的限制,因此Sermant在兼容性上的不断改进过程中无心插柳,帮助动态加载能力铺平了路。

3.2 如何保证在服务治理插件安装和卸载时不互相影响?

Sermant的设计中,通过字节码增强引入的服务治理能力,是通过在目标方法上添加服务治理功能切面来完成的,每一个服务治理插件,通过一系列切面的配合来达成最终的服务治理效果。不同的服务治理功能,可能会对同一个目标方法进行处理。但并不会对同一个方法进行多次字节码增强,而是通过一次字节码增强织入调度切面(onMethodEnter、onMethodExit等),通过该切面对相关的服务治理能力(通过拦截器实现,每一个切面会对应一个拦截器的列表)进行调度:

解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件,开发与运维,华为云开发者联盟,华为云,开发,微服务,JavaAgent,Sermant

对于服务治理能力的调度逻辑我们在另一篇文章《开发者能力机制解析,玩转Sermant开发》有讲过,本篇不再赘述。

基于框架的基本设计,就需要考虑两个问题,当插件在动态安装时,如何保证不重复字节码增强?当插件卸载时,如何保证不会导致有相同目标方法的插件失效。

  • 安装时如何保证不重复执行字节码增强?

在字节码增强开发过程中,类文件转换器(ClassFileTransformer)是一定会接触到的概念,开发者需要基于该转换器来进行字节码的处理。在大多数的字节码增强框架中,都会对其进行封装,用于降低字节码处理的难度。Sermant基于ByteBuddy提供的类文件转换器实现了一种可重入的类转换器,在插件动态安装时,虽然目标方法已经被已安装的插件增强过了,但此时还是会触发类文件转换(因为动态安装插件的过程是独立的),当触发类文件转换时,所有相关的类文件转换器都会被唤醒,再次触发类文件转换过程。每次可重入类转换器被唤醒时,将发生以下行为:

解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件,开发与运维,华为云开发者联盟,华为云,开发,微服务,JavaAgent,Sermant

在Sermant中维护了一个针对目标方法的字节码增强锁(AdviceKey锁),即针对每一个目标方法,维护了1个信号量当做锁,用于让各类文件转换器来检查目标方法的字节码增强状态,当目标方法对应的类被类转换时,就会触发Sermant所提供的类文件转换器,此时类文件转换器将尝试获取针对目标方法的信号量,如果能获取信号量,则执行对目标方法的字节码增强,如果不能获取,则不执行字节码增强。

基于字节码增强锁,在转换器触发时,主要有两条路径可以走,类文件转换器会通过目标方法的AdviceKey(类名+方法hash+类加载器组成的一个唯一表示,用于表示字节码增强的目标)来检查其所关联的锁,判断当前目标方法是否已被Sermant进行过字节码增强(织入拦截器调度的切面):

  1. 能获取锁,说明未被增强:则当前文件转换器获取当前AdviceKey所关联的锁,将其获取的锁通过其对应的插件来维护,并且执行字节码增强,将服务治理所需的拦截器放入该AdviceKey所对应的拦截器列表;

  2. 不能获取锁,说明已被增强:则只将拦截器放入该AdviceKey对应的拦截器列表中,不执行字节码增强。

通过上述机制,就可以保证Sermant在安装不同服务治理插件时,不会进行重复的字节码增强,避免无端的性能和资源损耗。

  • 卸载时如何保证不会导致其他插件失效?

当插件需要卸载时,会再次触发相关目标类的重转换,与安装时不同的是,这次需要被卸载的插件释放自身已经持有的AdviceKey锁。释放锁后,触发目标类重转换时,目标类所对应的各个插件的类文件转换器将会再次触发和安装时相同的流程:

解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件,开发与运维,华为云开发者联盟,华为云,开发,微服务,JavaAgent,Sermant

在这个过程中,未被卸载的插件所提供的对目标类的类文件转换器,会在目标类重转换时,再次触发,并且只会经历获取锁和字节码增强的过程。这样就保证,如果还有插件需要对该目标方法进行字节码增强时,可以获得目标方法所对应的锁,不会因为目标方法的交集而导致其他插件能力失效。

四、总结

本篇文章对Sermant的热插拔能力的核心机制进行了解析,希望可以为开发者及使用者在开发或使用相关能力时带来更多的灵感和便利。更多的热插拔能力介绍可以参考官网相关文档,Sermant Agent使用手册,后续我们也会针对热插拔适用的场景进行进一步分享,敬请期待。

Sermant作为专注于服务治理领域的字节码增强框架,致力于提供高性能、可扩展、易接入、功能丰富的服务治理体验,并会在每个版本中做好性能、功能、体验的看护,广泛欢迎大家的加入。

  • Sermant 官网:https://sermant.io

  • GitHub 仓库地址:GitHub - huaweicloud/Sermant: Sermant, a proxyless service mesh solution based on Javaagent.

点击关注,第一时间了解华为云新鲜技术~文章来源地址https://www.toymoban.com/news/detail-834418.html

到了这里,关于解析Sermant热插拔能力:服务运行时动态挂载JavaAgent和插件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rose65双模蓝牙5.2热插拔PCB

    LDN通用蓝牙双模固件和驱动使用帮助文档请点击如下链接: 功能参考链接 请参阅这个链接 1、先把排线的插头对正小板和大板的插座,再插入,注意方向不要插错,不要大力出奇迹,否则容易怼弯插座里的针,或者搞坏插座。 2、 不要插电池 ,然后插入USB,此时电脑应可以

    2024年02月11日
    浏览(63)
  • IRIS75 DM蓝牙5.2双模热插拔PCB

    LDN通用蓝牙双模固件和驱动使用帮助文档请点击如下链接: 功能参考链接 请参阅这个链接 1、先把排线的插头对正小板和大板的插座,再插入,注意方向不要插错,不要大力出奇迹,否则容易怼弯插座里的针,或者搞坏插座。 2、 不要插电池 ,然后插入USB,此时电脑应可以

    2024年02月07日
    浏览(51)
  • rk3588 双HDMI冲突问题与HDMI不能热插拔问题

    rk3588在开发时现在发现只能在插入HDMI时上电才能输出信号,而当开机之后,再插入HDMI显示器则无信号。 通过kernel显示,在开机后,插拔HMDI是有log提示的,说明内核能够检测到HDMI的插拔动作。 首先先排查软件问题,尝试重启显示进程 但还是无效果。 然后排查驱动问题,查

    2024年02月16日
    浏览(56)
  • RK35XX系列(RK3568)Camera 热插拔功能 调试记录

    SOC:RK3568 system:Android12 kernel:kernel-4.19 芯片:NVP6158C xs9922 目前我的主板上NVP6158接入4路Camera走DVP通道,xs9922接入4路AHDCamera走mipi通道 RK kernel-4.19支持xs9922 nvp6158c驱动路径       drivers/media/i2c/xs9922/xs9922.c  drivers/media/i2c/nvp6158_drv/nvp6158_v4l2.c RK支持Camera热插拔复位机制,如果

    2024年02月13日
    浏览(51)
  • 【深入理解SSD 实践】对NVMe SSD热插拔时,正确做法是怎样的?

    声明 主页 :元存储的博客_CSDN博客 依公开知识及经验整理,如有误请留言。 个人辛苦整理,付费内容,禁止转载。 内容摘要 前言 概念 SAS/SATA 和NVMe 区别 热插拔分类 热插拔基本原理

    2024年02月06日
    浏览(126)
  • linux 发行版中在容器内访问热插拔 U 盘的分区内容

    在 UOS 如何实现自动将 U 盘挂载到指定目录中?这篇文章中,我描述了 UOS 自动挂载 U 盘到指定目录的方式,现有的发行版处理逻辑大致相同。 当挂载位置确定后,容器内的业务逻辑要访问 U 盘分区中的内容,看上去只需要映射宿主机目录到容器内就万事大吉了,实际测试却

    2024年02月10日
    浏览(51)
  • 电池可热插拔拆卸对三防加固平板有什么意义|亿道三防onerugged

    今天我要和大家聊聊三防加固平板电脑中一个非常重要的功能——电池的可热插拔拆卸。是的,亿道三防onerugged系列产品具备这一亮点功能,给用户带来了极大的便利和灵活性。 首先,让我们来看看电池可热插拔拆卸的优势之一——双电池设计。亿道三防onerugged平板电脑采用

    2024年02月21日
    浏览(56)
  • Android Framework 动态更新插拔设备节点执行权限

    TF卡设备节点是插上之后动态添加,所以不能通过初始化设备节点权限来解决,需要监听TF插入事件,在init.rc 监听插入后动态更新设备节点执行权限 添加插拔TF卡监听 frameworks/base/services/core/java/com/android/server/StorageManagerService.java 在private void mount(VolumeInfo vol){}中添加 SystemProp

    2024年02月12日
    浏览(40)
  • 【Windows 系统笔记】使用服务器运行装载AList+本地安装RaiDrive进行网盘本地挂载

    大家肯定很好奇我为什么要写一篇这样的文章,因为之前一直使用本地挂载网盘,但是使得电脑一直开着而且还使得不是很方便,所以一直没有使用,但是随着笔记本装的东西一多使得对云盘使用较多,可以直接后台上传就可以 一台一直运行的服务器 本地电脑已经安装本地挂

    2024年02月03日
    浏览(69)
  • 群晖docker实现阿里云动态公网域名解析ddns服务

    日常生活中,一般家庭用户宽带使用的都是内网ip,如果需要在外网就是远程使用,需要将家庭ip向电信部门申请变更为公网ip,通常情况下,我们获得的都是动态公网ip,这种ip每隔一段时间都会自动变化,这样如果想通过一个不变的域名地址来访问,就需要dns动态来解析到变

    2024年02月05日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包