微服务应用启动慢的克星

本文介绍了面对Spring Cloud应用启动慢的问题,如何使用一款名为spring-startup-analyzer的工具进行启动分析,并通过异步初始化Bean进行性能优化。该工具通过agent方式启动,支持配置参数和日志查看。此外,文章还提醒了异步化Bean的注意事项,并提供了开源项目链接。

点击上方蓝色字体,选择“设为星标”

回复”云原生“获取基础架构实践

a4d6f35defd2bdc655aa33e3ae45bfe9.jpeg

背景

随着业务的复杂程度越来越大,所启动的实例或函数越来越多,Spring cloud 应用的启动越来越慢,那么如何发现 Spring 容器启动慢的原因或位置,有没有一款工具,帮助我们用户发现 Spring 应用启动慢的位置呢?同时,还可以提供 Spring Bean 异步初始化的工具。那么答案是有的。

实战操作

下面,我们可以通过下面的方法尝试分析一下自己的应用吧,Let us go~

安装工具组件

第一步:在 gitlab 网站下面其最新 tag:https://github.com/linyimin0812/spring-startup-analyzer/releases/tag/v2.0.5,下载tar.gz包。

32d42ce52dc11ace977329831182622b.png

第二步:解压下载的安装包,记住解压后的路径,下面一步要用:

  • win 下直接工具解压

  • linux 或 mac 通过 tar -zxvf 压缩文件名.tar.gz 解压

项目参数设置

第一步:编辑 Spring Boot 的启动参数,包括:

  • 该工具采用 agent 的方式启动,所以要添加参数-javaagent:,这里HOME 代表以前的解压路径,记得根据上面解压后的路径编辑这个参数,我的是:-javaagent:G:/Downloads/spring-startup-analyzer/lib/spring-profiler-agent.jar

e643a1e33807f56f2398fc61dd850e8f.png
  • 配置分析工具的参数,这里根据自己需要添加即可,比如可以配置超时时间 10 分钟:-Dspring-startup-analyzer.app.health.check.timeout=10,其他可配置项如下表,你可以工具自己应用的情况去修改:

英文版:77ec3db22e9d2cde6f3a91febad2653a.png

中文版:c8c9dc9c128dc1b754ced10bea7f8644.png

spring-startup-analyzer:
  admin:
    http:
      server:
        port: 8065
  app:
    health:
      check:
        endpoints: "http://127.0.0.1:7002/actuator/health"
        timeout: 10
  async:
    profiler:
      interval:
        millis: 5
      sample:
        thread:
          names: main

最后一步:查看该工具的日志,可以通过 路径,这里HOME 代表以前的解压路径,日志文件的类别为:

  • startup.log: 启动过程中的日志

  • transform.log: 被 re-transform 的类/方法信息

3e6184d1255125a3dc4766fe8719e904.png

应用启动完成后会在 console 和 startup.log 文件中输出======= spring-startup-analyzer finished, click http://localhost:8065 to visit details. ======,可以通过此输出来判断采集是否完成。

当然,该组件还支持自定义扩展,更多详情请看:https://github.com/linyimin0812/spring-startup-analyzer/tree/v2.0.5#configuration。

接入异步 Bean 优化

这里提到了一个启动加速的优化思路,就是把一些耗时的 Bean 初始化改成异步就能实现。该项目提供了 Bean 的异步初始化工具,也非常好用,只需要下面几步就能完成。提供一个 Spring Bean 异步初始化 jar 包,针对初始化耗时比较长的 bean,异步执行 init 和@PostConstruct 方法提高应用启动速度。

第一步:引入依赖

<dependency>
    <groupId>io.github.linyimin0812</groupId>
    <artifactId>spring-async-bean-starter</artifactId>
    <version>2.0.5</version>
</dependency>

第二步:配置参数

spring-startup-analyzer:
  boost:
    spring:
      async:
        ## 指定异步的Bean名称
        bean-names: restTemplate,testBean,testComponent
        #异步化的Bean可能在Spring Bean初始化顺序的末尾,导致异步优化效果不佳,打开配置优先加载异步化的Bean
        bean-priority-load-enable: true
        # 执行异步化Bean初始化方法线程池的核心线程数
        init-bean-thread-pool-core-size: 8
        # 执行异步化Bean初始化方法线程池的最大线程数
        init-bean-thread-pool-max-size: 8

第三步:检查 Bean 是否异步初始化。查看日志$HOME/spring-startup-analyzer/logs/startup.log 文件,对于异步执行初始化的方法,会按照以下格式写一条日志:

async-init-bean, beanName: ${beanName}, async init method: ${initMethodName}

但是,异步并不是万能的,你还需要注意以下这几点:

  • 应该优先从代码层面优化初始化时间长的 Bean,从根本上解决 Bean 初始化耗时长问题

  • 对于二方包/三方包中初始化耗时长的 Bean(无法进行代码优化)再考虑 Bean 的异步化

  • 对于不被依赖的 Bean 可以放心进行异步化,可以通过各个 Bean 加载耗时中的 Root Bean 判断 Bean 是否被其他 Bean 依赖

  • 对于被依赖的 Bean 需要小心分析,在应用启动过程中不能其他 Bean 被调用,否则可能会存在问题

a407febf08d6b6164f47ba49ec826439.png

支持异步化的 Bean 类型

支持@Bean, @PostConstruct 及@ImportResource 方式初始化 bean

@Bean(initMethod = "init")标识的 Bean

@Bean(initMethod = "init")
public TestBean testBean() {
    return new TestBean();
}


@Bean(initMethod = "init")
public RestTemplate restTemplate() {
  SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
  requestFactory.setReadTimeout(env.getProperty("client.http.request.readTimeout", Integer.class, 15000));
  requestFactory.setConnectTimeout(env.getProperty("client.http.request.connectTimeout", Integer.class, 3000));
  RestTemplate rt = new RestTemplate(requestFactory);
  return rt;
}

@PostConstruct 标识的 Bean

@Component
public class TestComponent {
    @PostConstruct
    public void init() throws InterruptedException {
        Thread.sleep(20 * 1000);
    }
}

更多详情请看:https://github.com/linyimin0812/spring-startup-analyzer/blob/v2.0.5/README_ZH.md。

下面给大家介绍几本好书,目前销售火热,有原理加实战,感兴趣可以点击下方链接购买。

开源项目

  实践项目代码开源:https://gitee.com/damon_one/microservice-k8s

欢迎大家star、fork,欢迎联系我,一起学习。

号内回复“云原生”,获取云原生基础架构实践

dc09caffaa6408d4222b4a07cbe369da.png

云原生社区合肥站

云原生社区合肥站正式启动啦,欢迎Base合肥、关注云原生、长期从事云原生的同志们踊跃加入,云原生社区合肥站会因为你们的加入而变得更加美好~

详情参见Issue:https://github.com/cloudnativeto/community/issues/107

联系号主

b467a3a49d8afe2650986d88285387d7.jpeg

欢迎关注个站

5421964c5246faefde6cb6f8d067e9d8.png

往期回顾

微服务自动化部署CI/CD

如何利用k8s拉取私有仓库镜像

个站建设基础教程

ArrayList、LinkedList&nbsp;你真的了解吗?

大佬整理的mysql规范,分享给大家

如果张东升是个程序员

微服务架构设计之解耦合

浅谈负载均衡

Oauth2的认证实战-HA篇

Oauth2的授权码模式《上》

浅谈开发与研发之差异

浅谈&nbsp;Java&nbsp;集合&nbsp;|&nbsp;底层源码解析

基于 Sentinel 作熔断 | 文末赠资料

基础设施服务k8s快速部署之HA篇

今天被问微服务,这几点,让面试官刮目相看

Spring cloud 之多种方式限流(实战)

Spring cloud 之熔断机制(实战)

面试被问finally 和 return,到底谁先执行?

Springcloud Oauth2 HA篇

Spring Cloud Kubernetes之实战一配置管理

Spring Cloud Kubernetes之实战二服务注册与发现

Spring Cloud Kubernetes之实战三网关Gateway

6e66033d8d7f5f285ade5737751def43.gif

2d242a0bd3f0946cf95e2c71d4471028.gif

点击 "damon8.cn" 获取更好的阅读体验!

❤️给个「在看」,是对我最大的支持❤️
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值