源码角度了解Skywalking之服务端OAP的启动流程
Skywalking的服务端OAP的逻辑对应oap-server模块,入口是server-starter子模块的OAPServerStartUp类,直接调用了server-bootstrap子模块的OAPServerBootstrap的start()方法
OAPServerBootstrap的start()方法:
public static void start() {
String mode = System.getProperty("mode");
RunningMode.setMode(mode);
ApplicationConfigLoader configLoader = new ApplicationConfigLoader();
ModuleManager manager = new ModuleManager();
try {
ApplicationConfiguration applicationConfiguration = configLoader.load();
manager.init(applicationConfiguration);
manager.find(TelemetryModule.NAME).provider().getService(MetricsCreator.class).createGauge("uptime",
"oap server start up time", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE)
// Set uptime to second
.setValue(System.currentTimeMillis() / 1000d);
if (RunningMode.isInitMode()) {
logger.info("OAP starts up in init mode successfully, exit now...");
System.exit(0);
}
} catch (Throwable t) {
logger.error(t.getMessage(), t);
System.exit(1);
}
}
- 读取系统配置的mode值,如果值为init表示初始化模式,做所有初始化的事情。如果值是no-init,表示非初始化模式,不进行存储初始化
- 创建ApplicationConfiguration对象,通过load()方法加载配置文件,具体是读取resources文件夹下的application.yml文件,然后读取系统配置,覆盖读取的application.yml文件的值
- 初始化给定的模块
- 查找指定Module中的获取相应Service,创建仪表类型指标实例标记启动时间。
- 如果是初始化模式,初始化成功后会退出OAP服务
我们具体看一下初始化模块
初始化模块
ModuleManager负责在收集器中的所有ModuleDefine
ModuleManager的init()方法:
- 获取配置所有的模块集合,配置文件中配置的都是模块名,这些都是在ModuleDefine的实现类中定义了,比如配置文件中的core对应的是ModuleDefine实现类CoreModule
- 通过SPI机制加载ModuleDefine的实现类
- 通过SPI机制加载ModuleProvider的实现类
- 遍历所有的ModuleDefine实现类,与配置文件中定义的实现类匹配,匹配成功调用prepare()方法进行初始化,否则放入map集合loadedModules中进行记录
- 添加完成准备阶段的标记
- 创建BootstrapFlow对象,启动ModuleManager对象,完成后调用notifyAfterCompleted()方法通知所有的ModuleProvider实例,表示可以对外提供服务了
ModuleDefine的准备阶段
ModuleDefine实例的prepare()方法是运行模块的准备阶段,这个方法中也会找到所有潜在的提供者,让他们也进入准备阶段
ModuleDefine的prepare()方法:
- 遍历SPI机制加载的moduleProviderLoader实现类,与配置文件中模块定义的实现类匹配,匹配成功设置ModuleProvider实例的ModuleManager和当前ModuleDefine
- 调用ModuleProvider的prepare()方法让提供者也进入准备状态,prepare()方法是ModuleProvider的抽象方法,具体方法由它的子类来实现,每个模块的prepare()方法也不同,每个模块仅对应一个ModuleProvider
BootstrapFlow创建、启动与通知
在初始化过程中,创建BootstrapFlow对象,BootstrapFlow的构造方法中创建LinkedList对象用链表集合记录模块的启动顺序,模块之间可能存在依赖,所以需要调用makeSequence()方法设定模块的加载顺序。
BootstrapFlow的start()方法:
void start(
ModuleManager moduleManager) throws ModuleNotFoundException, ServiceNotProvidedException, ModuleStartException {
for (ModuleProvider provider : startupSequence) {
String[] requiredModules = provider.requiredModules();
if (requiredModules != null) {
for (String module : requiredModules) {
if (!moduleManager.has(module)) {
throw new ModuleNotFoundException(module + " is required by " + provider.getModuleName()
+ "." + provider.name() + ", but not found.");
}
}
}
logger.info("start the provider {} in {} module.", provider.name(), provider.getModuleName());
provider.requiredCheck(provider.getModule().services());
provider.start();
}
}
遍历所有的ModuleProvider:
- 根据ModuleProvider需要的模块名判断是否ModuleProvider中是否有需要的模块,如果没有抛出异常
- 检测模块的service是否实现了,如果没有会抛出异常
- 启动ModuleProvider
所有的ModuleProvider依次启动后回调执行notifyAfterCompleted()方法
总结
这篇文章主要讲了Skywalking的服务端OAP的启动流程,入口是server-starter模块的OAPServerStartUp类的main()方法,这一启动过程主要做的是加载server-bootstrap模块中的application.yml定义的模块定义、模块配置,然后相对应的ModuleProvider依次按顺序进行启动
❤️ 感谢大家
如果你觉得这篇内容对你挺有有帮助的话:
- 欢迎关注我❤️,点赞????????,评论????,转发????
- 关注
盼盼小课堂
,定期为你推送好文,还有群聊不定期抽奖活动,可以畅所欲言,与大神们一起交流,一起学习。 - 有不当之处欢迎批评指正。