java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > springboot启动速度

加速spring/springboot应用启动速度详解

作者:wen-pan

这篇文章主要介绍了加速spring/springboot应用启动速度详解,本文通过实例代码给大家介绍的非常详细对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

Gitee地址 :https://gitee.com/mr_wenpan/basis-enhance/tree/master

一、解决的痛点

在实际使用 Spring/Spring Boot 开发中,一些 Bean 在初始化过程中,会执行一些准备操作,如:

在应用启动期间,这些 Bean 会增加 Spring 上下文刷新时间,导致应用启动耗时变长。为了加速应用启动,enhance-boot-async-init模块提供了通过配置的可选项,将 Bean 的初始化方法(init-method)使用单独线程异步执行的能力,加快 Spring 上下文加载过程,提高应用启动速度。仅需要将 @BasisAsyncInit注解标注到需要异步执行的初始化方法上即可实现应用启动过程中异步初始化。

加粗样式## 二、异步初始化组件说明

// 在注入HelloService处标注@BasisAsyncInit注解(此时HelloService上可以不标注)
@BasisAsyncInit
@Bean(initMethod = "init")
public HelloService helloService() {
  return new HelloService();
}
// 或者直接标注在类上
@BasisAsyncInit
public class HelloService {
}

二、使用

1、yml配置文件中开启异步初始化

basis:
  enhance:
    async:
      init:
        # 开启异步初始化功能
        enable: true
        # 异步初始化线程池核心线程数量(不配置的话默认是 2*cpu核数 + 1)
        asyncInitBeanCoreSize: 10
        # 异步初始化线程池最大线程数量(不配置的话默认是 2*cpu核数 + 1)
        asyncInitBeanMaxSize: 20

2、创建异步初始化的bean

@Slf4j
// 炸裂标注该bean是异步初始化的
@BasisAsyncInit
public class HelloService {
    /**
     * init方法
     */
    public void init() throws InterruptedException {
        log.info("i am HelloService.init method, start........");
      // 睡一会儿,这里模拟初始化方法非常耗时,初始化方法执行完毕前容器不允许正常启动成功
        TimeUnit.SECONDS.sleep(10);
      // 这里模拟异步初始化失败容器不允许正常启动
//        final int i = 1 / 0;
        log.info("i am HelloService.init method, end........");
    }
    public String sayHello(String name) {
        log.info("hello {}", name);
        return "hello-" + name;
    }
}

3、注入异步初始化的bean并指定初始化方法

@Bean(initMethod = "init")
public HelloService helloService() {
    return new HelloService();
}

4、启动应用观察日志

①、正常启动日志

2023-07-30 16:09:29.238  INFO 24094 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 711 ms
2023-07-30 16:09:29.307  INFO 24094 --- [           main] o.b.e.a.init.executor.AsyncTaskExecutor  : create async-init-bean thread pool, corePoolSize: 10, maxPoolSize: 20.
2023-07-30 16:09:29.308  INFO 24094 --- [pool-1-thread-1] o.e.async.init.service.HelloService      : i am HelloService.init method, start........
2023-07-30 16:09:29.541  INFO 24094 --- [           main] io.undertow                              : starting server: Undertow - 2.2.8.Final
2023-07-30 16:09:29.545  INFO 24094 --- [           main] org.xnio                                 : XNIO version 3.8.0.Final
2023-07-30 16:09:29.549  INFO 24094 --- [           main] org.xnio.nio                             : XNIO NIO Implementation Version 3.8.0.Final
2023-07-30 16:09:29.578  INFO 24094 --- [           main] org.jboss.threads                        : JBoss Threads version 3.1.0.Final
2023-07-30 16:09:29.623  INFO 24094 --- [           main] o.s.b.w.e.undertow.UndertowWebServer     : Undertow started on port(s) 8080 (http)
2023-07-30 16:09:39.310  INFO 24094 --- [pool-1-thread-1] o.e.async.init.service.HelloService      : i am HelloService.init method, end........
2023-07-30 16:09:39.311  INFO 24094 --- [pool-1-thread-1] o.b.e.a.i.p.AsyncProxyBeanPostProcessor  : org.enhance.async.init.service.HelloService(helloService) init method execute 10003 ms.
2023-07-30 16:09:39.321  INFO 24094 --- [           main] o.e.async.init.DemoAsyncInitApplication  : Started DemoAsyncInitApplication in 11.168 seconds (JVM running for 11.853)

②、初始化方法执行异常日志

2023-07-30 16:12:30.000  INFO 24127 --- [           main] o.e.async.init.DemoAsyncInitApplication  : Starting DemoAsyncInitApplication using Java 1.8.0_281 on wenpf-MacBook-Pro.local with PID 24127 (/Users/wenpanfeng/MyFolder/DevelopWorkspace/IdeaWorkSpace/StudyProjects/basis-enhance/enhance-demo-parent/demo-enhance-async-init/target/classes started by wenpanfeng in /Users/wenpanfeng/MyFolder/DevelopWorkspace/IdeaWorkSpace/StudyProjects/basis-enhance)
2023-07-30 16:12:30.002  INFO 24127 --- [           main] o.e.async.init.DemoAsyncInitApplication  : No active profile set, falling back to default profiles: default
2023-07-30 16:12:30.763  WARN 24127 --- [           main] io.undertow.websockets.jsr               : UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used
2023-07-30 16:12:30.779  INFO 24127 --- [           main] io.undertow.servlet                      : Initializing Spring embedded WebApplicationContext
2023-07-30 16:12:30.779  INFO 24127 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 731 ms
2023-07-30 16:12:30.860  INFO 24127 --- [           main] o.b.e.a.init.executor.AsyncTaskExecutor  : create async-init-bean thread pool, corePoolSize: 10, maxPoolSize: 20.
2023-07-30 16:12:30.861  INFO 24127 --- [pool-1-thread-1] o.e.async.init.service.HelloService      : i am HelloService.init method, start........
2023-07-30 16:12:31.109  INFO 24127 --- [           main] io.undertow                              : starting server: Undertow - 2.2.8.Final
2023-07-30 16:12:31.114  INFO 24127 --- [           main] org.xnio                                 : XNIO version 3.8.0.Final
2023-07-30 16:12:31.119  INFO 24127 --- [           main] org.xnio.nio                             : XNIO NIO Implementation Version 3.8.0.Final
2023-07-30 16:12:31.151  INFO 24127 --- [           main] org.jboss.threads                        : JBoss Threads version 3.1.0.Final
2023-07-30 16:12:31.197  INFO 24127 --- [           main] o.s.b.w.e.undertow.UndertowWebServer     : Undertow started on port(s) 8080 (http)
2023-07-30 16:12:40.867  INFO 24127 --- [           main] io.undertow                              : stopping server: Undertow - 2.2.8.Final
2023-07-30 16:12:40.879  INFO 24127 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-07-30 16:12:40.899 ERROR 24127 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.basis.enhance.async.init.exception.BasisAsyncInitException: 异步初始化失败.
    at org.basis.enhance.async.init.executor.AsyncTaskExecutor.ensureAsyncTasksFinish(AsyncTaskExecutor.java:94) ~[classes/:na]
    at org.basis.enhance.async.init.listener.AsyncTaskExecutionListener.onApplicationEvent(AsyncTaskExecutionListener.java:28) ~[classes/:na]
    at org.basis.enhance.async.init.listener.AsyncTaskExecutionListener.onApplicationEvent(AsyncTaskExecutionListener.java:20) ~[classes/:na]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:938) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.8.jar:5.3.8]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.8.jar:2.4.8]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771) [spring-boot-2.4.8.jar:2.4.8]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763) [spring-boot-2.4.8.jar:2.4.8]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438) [spring-boot-2.4.8.jar:2.4.8]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) [spring-boot-2.4.8.jar:2.4.8]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) [spring-boot-2.4.8.jar:2.4.8]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1318) [spring-boot-2.4.8.jar:2.4.8]
    at org.enhance.async.init.DemoAsyncInitApplication.main(DemoAsyncInitApplication.java:15) [classes/:na]
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:1.8.0_281]
    at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[na:1.8.0_281]
    at org.basis.enhance.async.init.executor.AsyncTaskExecutor.ensureAsyncTasksFinish(AsyncTaskExecutor.java:92) ~[classes/:na]
    ... 17 common frames omitted
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at org.basis.enhance.async.init.processor.AsyncProxyBeanPostProcessor$AsyncInitializeBeanMethodInvoker.lambda$invoke$0(AsyncProxyBeanPostProcessor.java:119) ~[classes/:na]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_281]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_281]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_281]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_281]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_281]
Caused by: java.lang.reflect.InvocationTargetException: null
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_281]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_281]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_281]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_281]
    at org.basis.enhance.async.init.processor.AsyncProxyBeanPostProcessor$AsyncInitializeBeanMethodInvoker.lambda$invoke$0(AsyncProxyBeanPostProcessor.java:115) ~[classes/:na]
    ... 5 common frames omitted
Caused by: java.lang.ArithmeticException: / by zero
    at org.enhance.async.init.service.HelloService.init(HelloService.java:25) ~[classes/:na]
    ... 10 common frames omitted

三、原理/源码浅析

到此这篇关于如何加速spring/springboot应用启动速度的文章就介绍到这了,更多相关springboot启动速度内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文