优化spring boot应用后6s内启动内存减半
作者:kl 发布时间:2021-09-13 02:47:59
前言
taptap-developer是一个spring boot框架驱动的纯Grpc服务,所以,只用了四步,移除了web和spring cloud相关的模块后,启动速度就稳稳的保持在了6s内。除了启动速度提升外,在服务待机状态下,内存锐减了50%左右,从500M左右的内存占用,缩减到了250M不到。
分析日志
日志是一个应用的门面,在未深入了解一个应用的架构前,通过启动的日志输出基本可以分析出这个应用的大概的技术构成。在分析日志之前,在强调一点,这个应用是一个纯Grpc的服务。如上图贴出的日志,是未优化前的系统日志输出,从上到下有四个红色箭头指向,是本次日志分析的关键信息,下面就这四个关键信息,分别分析下。然后总结出常见的优化方法
优化点一:关于SPRING DATA REPOSITORY SCANNING
Spring Data repository是一个高度抽象的数据访问层接口,常见的实现有redis、jdbc、jpa、MongoDB、elasticsearch等等。实现一个Spring-data-xxx包,需要实现
org.springframework.data.repository.core.support.RepositoryFactorySupport抽象类
然后在!/META-INF/spring.factories文件中定义好实现类。spring容器启动时,会扫描加载factories的信息。如果一个项目里有被扫描到有多个spring-data-xxx的实现,启动时日志就会打印
Multiple Spring Data modules found, entering strict repository configuration mode!
优化:看到这个日志,我们就需要检查下项目中是否用到了这些功能,比如引入了spring-data-redis,其实只用到了其携带的jedis,而且jedis实例可能还是自己实例化的,这个时候就可以禁用repository的功能。参考配置如下:
spring.data.redis.repositories.enabled=false
Spring Data repository有三种内置的初始化模式,分别对应如下:
DEFAULT
:和Spring其他Bean一样,在容器上下文加载时就初始化DEFERRED
:惰性加载,容器上下文启动完成后开始初始化LAZY
:惰性加载,并且延迟注入,容器上下文启动完成接收第一个请求时开始初始化
如日志输出:Bootstrapping Spring Data repositories in DEFAULT mode,默认是随容器启动就开始初始化的
优化:这里可以根据业务特点,选择延迟加载,
参考配置spring.data.jpa.repositories.bootstrap-mode=lazy
Spring Data repository会扫描项目中的实现了repository接口的类,默认情况下会盲扫所有的jar包,
日志输出:Finished Spring Data repository scanning in 148ms. Found 0 repository interfaces.
打印出了扫描repository接口的耗时情况。
优化:
这里可以通过@EnableRedisRepositories(basePackages = "com.taptap")指定扫描的路径
可以显著提升扫描加载的速度
优化点二:关于WEBAPPLICATIONCONTEXT
在spring中,WebApplicationContext是ApplicationContext的增强,由spring-web-mvc实现,增加了servlet、session等web相关的内容。
从日志Initializing Spring embedded WebApplicationContext可以看出,我们初始化了一个web容器,而纯Grpc服务用不到Web的容器上下文,所以移除如下依赖即可
优化:
移除implementation('org.springframework.boot:spring-boot-starter-web')
优化点三:关于SERVLET容器
spring-web-mvc是基于java web标准servlet设计架构的。而servlet是由servlet容器来驱动的,常见的servlet有tocmat、jetty、undertow等。从日志中可看出,我们启动了一个8081的servlet容器。这个不应该出现在纯Grpc的服务中,所以,直接移除即可。
优化:
移除implementation 'org.springframework.boot:spring-boot-starter-undertow'
优化点四:关于ARCHAIUS配置组件
从最后一个箭头指向的日志信息可以分析出,项目引入了archaius配置加载组件,所以项目在启动时,archaius会尝试去加载默认策略的配置源。而我们整体的技术栈,配置中心统一采用了apollo,所以可以直接移除,最后通过分析定位,archaius不是单独引入的,是随着spring-cloud-starter-netflix-hystrix一同引入,这个组件是spring-cloud-netflix微服务框架最常用的,但是在这边,目前所有的微服务都是直接注册到k8s容器的,所有服务的熔断、限流、负载均衡都下沉到了容器基数设施平台,所以应用层面虽然引入了这个包,其实没有实际作用,所以最后移除spring cloud相关组件
优化:
移除implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'和
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'组件、
附优化后的日志输出:
系统资源的变化
优化前的
优化后的
最后,基于资源监控图,从三个维度总结下,优化后的资源占用情况:
资源名称 | 优化前 | 优化后 |
---|---|---|
内存 | 500M左右 | 250M左右 |
总线程数 | 107 | 78 |
装载类 | 12922 | 10041 |
来源:http://www.kailing.pub/article/index/arcid/312.html


猜你喜欢
- 引言因为写了不少 Spring Security 文章的缘故,所以总是有小伙伴来问松哥:按钮级别的权限怎么实现?甚至有一些看过 vhr 的小
- Java操作Redis的方式有下面两种:一、jedis(1)maven配置<dependency> <grou
- 开篇点题:正则表达式方法效果=0(下面会提到效果)空行问题: VS:在使用过程中对于VS的自动整理不太满意,因为不会自动删除空行当出现这种情
- 一.起缘故事缘于一位朋友的一道题:朋友四人玩LOL游戏。第一局,分别选择位置:中单,上单,ADC,辅助;第二局新加入的伙伴要选上单,四人可选
- 本文实例讲述了Android编程之利用服务实现 * 听的方法。分享给大家供大家参考,具体如下:1. 启动模拟器,部署应用2. 利用模拟器控制
- 在使用 springboot 或者 springcloud 开发的时候,通常为了保证系统的安全性,配置文件中的密码等铭感信息都会进行加密处理
- 一、基本定义Arrays类,全路径java.util.Arrays,主要功能为操作数组,Arrays类的所有方法均为静态方法,所以调用方式全
- 需求:字符串(字符串只有一位小数)转float进行运算, 将结果转成字符串(保留一位小数)直接上代码:float f1 = 0.1f;Str
- foreach 循环 list(map)直接上代码:整体需求就是1.分页对象里面有map map里面又有数组对象2.分页对象里面有list
- 一:算术运算符1.算术运算符有哪些①基本四则运算符:+ - * / %②增量赋值运算符:+= -= *= /= %=③自增/自减运算符++
- 公司有个业务需要查出所有的用户权限分类,并将最后一层类别所包含的权限查出来。数据库说明,有一个parent_id 字段是最好的:、paren
- Android开发sdk过程中,很有可能在sdk内部引
- oshi查看cpu信息OSHI可以跨平台查看服务器信息,其中cpu负载信息为当前占用CPU的时间。需要在一段时间内获取两次,然后相减得出这段
- 我在5月份的时候就申请了洞态IAST企业版内测,算是比较早的一批用户了。聊聊几个我比较在意的问题,比如API接口覆盖率、第三方开源组件检测以
- 之前代码有一个逻辑,是在初始化时读取某个包下的所有class文件,放入到一个HashMap里。代码运行过程中,通过Key获取到对应class
- 1. xml文件中加入自定义 搜索view<com.etoury.etoury.ui.view.IconCenterEditText
- 前言我们利用printf 函数实现一个在屏幕上弹跳的小球,如图所示。弹跳的小球游戏比较简单、容易入门,也是反弹球消砖块、接金币、台球等很多游
- 版本对照各版本的文档说明:https://docs.spring.io/spring-data/elasticsearch/docs/1、在
- forword跳转页面的三种方式:1.使用serlvet/** * 使用forward跳转,传递基本类型参数到页面  
- /*开机自动启动APP*/public class BootReceiver extends BroadcastReceiver {@Ove