Skywalking流程分析_3(服务的准备、启动、关闭)

news/2024/11/17 23:59:05/

前文将SkyWalkingAgent.premain中的:

  • SnifferConfigInitializer.initializeCoreConfig(agentArgs)
  • pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins())这两个方法分析完毕,下面继续分析premain方法其余部分

创建byteBuddy

final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));

设置哪里类进行忽略

AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(nameStartsWith("net.bytebuddy.").or(nameStartsWith("org.slf4j.")).or(nameStartsWith("org.groovy.")).or(nameContains("javassist")).or(nameContains(".asm.")).or(nameContains(".reflectasm.")).or(nameStartsWith("sun.reflect")).or(allSkyWalkingAgentExcludeToolkit()).or(ElementMatchers.isSynthetic()));

把一些必要的类注入到BootstrapClassLoader中

agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);

这里先不做详细的分析,先分析不是由BootstrapClassLoader加载的类,然后回过头来分析这个,否则不好理解

启动服务

//将BootService的这些服务依次进行启动
ServiceManager.INSTANCE.boot();
public void boot() {//通过spi加载实现了BootService接口的服务bootedServices = loadAllServices();//将BootService的这些服务依次进行启动prepare();startup();onComplete();
}

所谓的服务就是实现了org.apache.skywalking.apm.agent.core.boot.BootService接口的实现类,可以看到此接口定义了一系列的生命周期的操作

public interface BootService {//准备void prepare() throws Throwable;//启动void boot() throws Throwable;//启动完成void onComplete() throws Throwable;//关闭void shutdown() throws Throwable;/*** {@code BootService}s with higher priorities will be started earlier, and shut down later than those {@code BootService}s with lower priorities.** @return the priority of this {@code BootService}.*/default int priority() {return 0;}
}

spi加载实现BootService接口的服务

private Map<Class, BootService> loadAllServices() {Map<Class, BootService> bootedServices = new LinkedHashMap<>();List<BootService> allServices = new LinkedList<>();//通过spi机制加载实现了BootService接口的服务load(allServices);for (final BootService bootService : allServices) {Class<? extends BootService> bootServiceClass = bootService.getClass();//判断有没有默认实现boolean isDefaultImplementor = bootServiceClass.isAnnotationPresent(DefaultImplementor.class);if (isDefaultImplementor) {//如果有默认实现,则放入进去if (!bootedServices.containsKey(bootServiceClass)) {bootedServices.put(bootServiceClass, bootService);} else {//ignore the default service}} else {//判断是不是覆盖实现OverrideImplementor overrideImplementor = bootServiceClass.getAnnotation(OverrideImplementor.class);//既没有@DefaultImplementor,也没有@OverrideImplementorif (overrideImplementor == null) {if (!bootedServices.containsKey(bootServiceClass)) {bootedServices.put(bootServiceClass, bootService);} else {throw new ServiceConflictException("Duplicate service define for :" + bootServiceClass);}} else {//没有@DefaultImplementor,但是有@OverrideImplementor,就是覆盖默认实现Class<? extends BootService> targetService = overrideImplementor.value();//当前 覆盖实现 要覆盖的 默认实现 已经被加载进来 if (bootedServices.containsKey(targetService)) {//被覆盖的默认实现上必须要有@DefaultImplementor才能够使用 被覆盖实现boolean presentDefault = bootedServices.get(targetService).getClass().isAnnotationPresent(DefaultImplementor.class);if (presentDefault) {bootedServices.put(targetService, bootService);} else {throw new ServiceConflictException("Service " + bootServiceClass + " overrides conflict, " + "exist more than one service want to override :" + targetService);}} else {//当前 覆盖实现 要覆盖的 默认实现 还没有被加载进来,这时就把这个 覆盖实现 当做是其服务的 默认实现bootedServices.put(targetService, bootService);}}}}return bootedServices;
}

通过spi机制加载实现了BootService接口的服务

void load(List<BootService> allServices) {for (final BootService bootService : ServiceLoader.load(BootService.class, AgentClassLoader.getDefault())) {allServices.add(bootService);}
}

既然是spi加载,那么需要看下spi的文件,在META-INF.services下的org.apache.skywalking.apm.agent.core.boot.BootService文件

org.apache.skywalking.apm.agent.core.remote.TraceSegmentServiceClient
org.apache.skywalking.apm.agent.core.context.ContextManager
org.apache.skywalking.apm.agent.core.sampling.SamplingService
org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager
org.apache.skywalking.apm.agent.core.jvm.JVMMetricsSender
org.apache.skywalking.apm.agent.core.jvm.JVMService
org.apache.skywalking.apm.agent.core.remote.ServiceManagementClient
org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService
org.apache.skywalking.apm.agent.core.commands.CommandService
org.apache.skywalking.apm.agent.core.commands.CommandExecutorService
org.apache.skywalking.apm.agent.core.profile.ProfileTaskChannelService
org.apache.skywalking.apm.agent.core.profile.ProfileSnapshotSender
org.apache.skywalking.apm.agent.core.profile.ProfileTaskExecutionService
org.apache.skywalking.apm.agent.core.meter.MeterService
org.apache.skywalking.apm.agent.core.meter.MeterSender
org.apache.skywalking.apm.agent.core.context.status.StatusCheckService
org.apache.skywalking.apm.agent.core.remote.LogReportServiceClient
org.apache.skywalking.apm.agent.core.conf.dynamic.ConfigurationDiscoveryService
org.apache.skywalking.apm.agent.core.remote.EventReportServiceClient
org.apache.skywalking.apm.agent.core.ServiceInstanceGenerator

服务结构

  • 上面的代码在加载时分成了默认实现和覆盖实现。结构是默认实现(DefaultTest)实现Test接口(ServiceTest),覆盖实现(OverrideTest)继承默认实现
  • 接口和默认实现合并,默认实现标注@DefaultImplementor,覆盖实现继承默认实现并标注@OverrideImplementor(value=默认实现.class)

以日志报告服务举例

//这是默认实现
@DefaultImplementor
public class LogReportServiceClient implements BootService
//覆盖实现
@OverrideImplementor(LogReportServiceClient.class)
public class KafkaLogReporterServiceClient extends LogReportServiceClient

通过spi加载了实现BootService接口的服务,然后放到了bootedServices中,下面就是在prepare、startup、onComplete方法中依次的调用这些服务

public void shutdown() {bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority).reversed()).forEach(service -> {try {service.shutdown();} catch (Throwable e) {LOGGER.error(e, "ServiceManager try to shutdown [{}] fail.", service.getClass().getName());}});
}private void prepare() {bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> {try {service.prepare();} catch (Throwable e) {LOGGER.error(e, "ServiceManager try to pre-start [{}] fail.", service.getClass().getName());}});
}private void startup() {bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> {try {service.boot();} catch (Throwable e) {LOGGER.error(e, "ServiceManager try to start [{}] fail.", service.getClass().getName());}});
}private void onComplete() {for (BootService service : bootedServices.values()) {try {service.onComplete();} catch (Throwable e) {LOGGER.error(e, "Service [{}] AfterBoot process fails.", service.getClass().getName());}}
}

总结

服务结构:

  • 服务要实现BootService接口
  • 服务如果只有一种实现,直接创建一个类即可
  • 如果有多种实现
    • 默认实现使用@DefaultImplementor
    • 覆盖实现使用@OverrideImplementor
      加载过程:
  • SPI加载所有实现BootService接口的服务
  • 根据服务实现模式进行加载
    • 两个注解都没有的服务直接加入服务
    • @DefaultImplementor修饰的服务直接加入集合
    • @OverrideImplementor
      • value指向的服务有@DefaultImplementor,则覆盖
      • value指向的服务没有@DefaultImplementor,则报错

后文介绍的是插件的具体结构和如何识别不同版本而是使用不同插件的技巧


http://www.ppmy.cn/news/1215724.html

相关文章

springboot整合openfeign配置微信小程序登录,并解决超时问题

在使用springcloud作为技术栈的时候&#xff0c;在rpc通信方面&#xff0c;有很多框架选择&#xff0c;例如dubbo&#xff0c;openfeign等。 OpenFeign是一个声明式的web服务客户端&#xff0c;它使得编写Web服务客户端变得非常容易。它使用基于注解的方式来定义和实现Web服务客…

【JavaEE】Servlet(创建Maven、引入依赖、创建目录、编写及打包、部署和验证、smart Tomcat)

一、什么是Servlet&#xff1f; Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app 1.1 Servlet能干什么&#xff1f; &#x1f695;允许程序猿注册一个类, 在 Tomcat 收到某个特定的 HTTP 请求的时候, 执行这个类…

DaoWiki(基于Django)开发笔记 20231114-阿里云mysql外部访问

文章目录 创建mysql用户&#xff0c;用户远程访问配置阿里云安全策略下载安装mysql workbench 创建mysql用户&#xff0c;用户远程访问 创建用户 CREATE USER dao_wiki% IDENTIFIED BY password;授权访问dao_wiki数据库 GRANT ALL PRIVILEGES ON dao_wiki.* TO dao_wiki%; F…

samba 共享目录write permission deny问题修复 可读取内容但不可修改 删除 新增文件

关于 update/delete/write permission deny问题修复 0.首先在服务器端执行testparm -s &#xff0c;测试 Samba 配置并显示结果。需确保服务器端参数 read only No &#xff0c;共享目录有写入权限 一、若配置了允许匿名访问&#xff0c;使用匿名访问来操作smb需要做如下处理…

Spring后端HttpClient实现微信小程序登录

这是微信官方提供的时序图。我们需要关注的是前后端的交互&#xff0c;以及服务端如何收发网络请求。 小程序端 封装基本网络请求 我们先封装一个基本的网络请求。 const baseUrl"localhost:8080" export default{sendRequsetAsync } /* e url&#xff1a;目标页…

什么是智能井盖?万宾科技的智能井盖传感器的效果

近年来为打造智慧城市政府一直在不懈努力。加速城市基础建设是一项重要的举措&#xff0c;它有助于推动城市综合治理城市生命线的建设工程。在改善市民生活质量的过程中&#xff0c;市政部门正积极进行井盖的改进和升级工作&#xff0c;特别是那些看似微不足道的井盖却蕴含着重…

WordPress 文档主题模板Red Line -v0.2.2

此主题作为框架&#xff0c;做承载第三方页面之用&#xff0c;例如飞书文档等&#xff0c; 您可以将视频图片等资源放第三方文档上&#xff0c;通过使用此主题做目录用。 此主题使用前后端分离开发&#xff0c;也使用了一些技术尽量不影响正常的SEO&#xff0c;还望注意。 源码…

LeetCode(10)跳跃游戏 II【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 45. 跳跃游戏 II 1.题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nu…