tencent cloud

弹性微服务

动态与公告
公告
产品动态
产品简介
产品概述
产品优势
应用场景
购买指南
计费概述
产品定价
欠费与停服说明
快速入门
步骤1:获取访问权限
步骤2:创建环境
步骤3:创建应用
步骤4:部署应用
操作指南
环境管理
应用管理
权限管理
查看变更记录
实践教程
Github Actions 在 TEM 中的使用
托管静态网站
弹性微服务应用访问公网(通过 NAT 网关)
弹性微服务应用访问公网(通过 API 网关)
弹性微服务应用运行失败故障排查指南
使用 API 网关快速访问 TEM 应用
Java 应用调优实践教程
Java 8 迁移至 Java 11 实践教程
API 文档
History
Introduction
API Category
Making API Requests
Environment APIs
ModifyIngress
Resource APIs
Application APIs
Service APIs
RollingUpdateApplicationByVersion
Access Policy APIs
Configuration file APIs
Log collecting APIs
Scaling Rule APIs
Application Version APIs
Other APIs
Workload APIs
Data Types
Error Codes
常见问题
弹性微服务配置
联系我们
词汇表
TEM 政策
隐私政策
数据处理和安全协议
文档 弹性微服务实践教程Java 应用调优实践教程

Java 应用调优实践教程

PDF
聚焦模式
字号
最后更新时间: 2024-07-04 16:25:38

优化容器镜像

通过优化容器镜像,您可以缩短加载时间和启动时间。您可以通过以下方式优化镜像:
尽可能减小化容器镜像大小。
避免使用嵌套 jar 包。
使用弹性微服务Jar / War 方式部署。
弹性微服务Jar / War 方式部署默认提供 Jar 包镜像构建的实践教程,弹性微服务默认提供能充分利用构建缓存的构建流程,使用新一代构建利器 Buildkit 进行高速构建,构建速度优化50%以上,并且整个构建流程可追溯,构建日志可查,简单高效。

设置应用加速

使用弹性微服务 Jar / War 方式部署,并选择 KONA JDK 11/Open JDK 11 运行环境,弹性微服务将默认开启应用加速功能,并且默认支持 SpringBoot 应用零改造加速。弹性微服务增强了 Open JDK 中的 AppCDS 特性,您无需改造原有的 SpringBoot 嵌套 Jar 包结构,弹性微服务将直接提供 Java 应用加速的实践教程,实例扩容时的启动时间将缩短至10%~40%。

JVM 参数优化

使用可以感知容器内存资源的 JDK

在虚拟机和物理机中,对于 CPU 和内存分配,JVM 会从常见位置(例如,Linux 中的/proc/cpuinfo/proc/meminfo)查找其可以使用的 CPU 和内存。但是,在容器中运行时,CPU 和内存限制条件存储在/proc/cgroups/...中。较旧版本的 JDK 会继续在/proc(而不是/proc/cgroups)中查找,这可能会导致 CPU 和内存用量超出分配的上限,并因此引发多种严重的问题:
线程过多,因为线程池大小由 Runtime.availableProcessors() 配置
JVM的对内存使用超出容器内存上限。并导致容器被 OOMKilled。
JDK 8u131 首先实现了 UseCGroupMemoryLimitForHeap 的参数。但这个参数存在缺陷,为应用添加 UnlockExperimentalVMOptionsUseCGroupMemoryLimitForHeap 参数后,JVM 确实可以感知到容器内存,并控制应用的实际堆大小。但是这并没有充分利用我们为容器分配的内存。
因此 JVM 提供 -XX:MaxRAMFraction 标志来帮助更好的计算堆大小,MaxRAMFraction 默认值是4(即除以4),但它是一个分数,而不是一个百分比,因此很难设置一个能有效利用可用内存的值。
JDK 10 附带了对容器环境的更好支持。如果在 Linux 容器中运行 Java 应用程序,JVM 将使用 UseContainerSupport 选项自动检测内存限制。然后,通过 InitialRAMPercentageMaxRAMPercentageMinRAMPercentage 来进行对内存控制。这时,我们使用的是百分比而不是分数,这将更加准确。
默认情况下,UseContainerSupport 参数是激活的,MaxRAMPercentage 是25%,MinRAMPercentage 是50%。
需要注意的是,这里 MinRAMPercentage 并不是用来设置堆大小的最小值,而是仅当物理服务器(或容器)中的总可用内存小于250MB时,JVM 将用此参数来限制堆的大小。
同理,MaxRAMPercentage 是当物理服务器(或容器)中的总可用内存大小超过250MB时,JVM 将用此参数来限制堆的大小。
这几个参数已经向下移植到 JDK 8u191。UseContainerSupport 默认情况下是激活的。我们可以设置 -XX:InitialRAMPercentage=50.0 -XX:MaxRAMPercentage=80.0 来 JVM 感知并充分利用容器的可用内存。需要注意的是,在指定 -Xms -Xmx 时,InitialRAMPercentageMaxRAMPercentage 将会失效。

关闭优化编译器

默认情况下,JVM 有多个阶段的 JIT 编译。虽然这些阶段可以逐渐提高应用的效率,但它们也会增加内存使用的开销,并增加启动时间。
对于短期运行的云原生应用,可以考虑使用以下参数来关闭优化阶段,以牺牲长期运行效率来换取更短的启动时间。
JAVA_TOOL_OPTIONS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1"


关闭类验证

当 JVM 将类加载到内存中以供执行时,它会验证该类未被篡改并且没有恶意修改或损坏。但在云原生环境,CI/CD 流水线通常也由云原生平台提供,这表示我们的应用的编译和部署是可信的,因此我们应该考虑使用以下参数关闭验证。如果在启动时加载大量类,则关闭验证可能会提高启动速度。
JAVA_TOOL_OPTIONS="-noverify"


减小线程栈大小

大多数 Java Web 应用都是基于每个连接一个线程的模式。每个 Java 线程都会消耗本机内存(而不是堆内存)。这称为线程栈,并且每个线程默认为1MB。如果您的应用处理100个并发请求,则它可能至少有100个线程,这相当于使用了100MB的线程栈空间。该内存不计入堆大小。我们可以使用以下参数来减小线程栈大小。
JAVA_TOOL_OPTIONS="-Xss256k"

需要注意如果减小得太多,则将出现 java.lang.StackOverflowError。您可以对应用进行分析,并找到要配置的最佳线程栈大小。

Spring boot 应用优化

使用 Spring Boot 2.2 或更高版本

从 2.2 版开始,Spring Boot 已针对启动速度进行了大量优化。如果您使用的是低于 2.2 版的 Spring Boot,请考虑升级或 手动进行优化

使用延迟初始化

在 Spring Boot 2.2 及更高版本中,您可以开启全局延迟初始化,以提高启动速度,但代价是第一个请求的延迟时间可能变长,因为需要等待组件首次初始化。 您可以在 application.properties 中开启延迟初始化:
spring.main.lazy-initialization=true

或者,使用以下环境变量:
SPRING_MAIN_LAZY_INITIALIZATIION=true



帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈