spring boot应用优化,6s内启动,内存减半

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: taptap-developer是一个spring boot框架驱动的纯Grpc服务,所以,只用了四步,移除了web和spring cloud相关的模块后,启动速度就稳稳的保持在了6s内。除了启动速度提升外,在服务待机状态下,内存锐减了50%左右,从500M左右的内存占用,缩减到了250M不到。

前言

taptap-developer是一个spring boot框架驱动的纯Grpc服务,所以,只用了四步,移除了web和spring cloud相关的模块后,启动速度就稳稳的保持在了6s内。除了启动速度提升外,在服务待机状态下,内存锐减了50%左右,从500M左右的内存占用,缩减到了250M不到。

分析日志

03901487-AE45-49C7-852C-81E4D4827BEF.png
日志是一个应用的门面,在未深入了解一个应用的架构前,通过启动的日志输出基本可以分析出这个应用的大概的技术构成。在分析日志之前,在强调一点,这个应用是一个纯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'组件、

附优化后的日志输出:
7C38C587-5CE2-4DAA-A79B-EDC2ADD43C7C.png

系统资源的变化

优化前的
A4E82AA8-74AA-4B0B-81EF-0C6AB2F5CBB7.png
优化后的
C8CB365E-6592-44A5-BC20-73472336D435.png
最后,基于资源监控图,从三个维度总结下,优化后的资源占用情况:

资源名称 优化前 优化后
内存 500M左右 250M左右
总线程数 107 78
装载类 12922 10041
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
25天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
97 62
|
19小时前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
17 3
|
16天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
36 6
|
14天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
16天前
|
监控 安全 程序员
如何使用内存池池来优化应用程序性能
如何使用内存池池来优化应用程序性能
|
16天前
|
存储 监控 Java
深入理解计算机内存管理:优化策略与实践
深入理解计算机内存管理:优化策略与实践
|
21天前
|
缓存 监控 Java
|
23天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
40 2
|
28天前
|
存储 JavaScript 前端开发
如何优化代码以避免闭包引起的内存泄露
本文介绍了闭包引起内存泄露的原因,并提供了几种优化代码的策略,帮助开发者有效避免内存泄露问题,提升应用性能。
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
385 0
下一篇
无影云桌面