您的位置:首页 > 编程语言 > Java开发

Spring Boot & Spring Cloud应用内存管理

2017-09-21 00:00 253 查看
摘要:SpringBoot&SpringCloud应用内存管理



MemoryManagement

在整体应用架构中,非生产环境情况下,一般1GB或者2GB的RAM就足够了。如果我们将这个应用程序划分为20或30个独立的微服务,那么很难期望RAM仍将保持在1GB或2GB左右。特别是如果我们使用SpringCloud的时候。

首先,准备三个服务,Eureka服务+提供RESTAPI的两个简单的微服务,并将微服务注册到Eureka。此处,不以任何方式限制这些应用程序的内存使用。

提示:SpringCloud简单应用的搭建示例:https://www.ictgu.cn/share/6644e468

就像你在下图看到的一样,三个微服务大概占用了电脑1.5GB的RAM内存。这三个服务是最简单的应用程序,基本没有数据处理量,对于这样的内存消耗量,显然是不理想的。RAM的最低使用量是用于Eureka
发现服务,最大的用于初始化声明式客户端以调用其他服务的API。



未限制的内存用量

关于内存使用量如下图JProfiler制作的图表。如图所示,内存使用受堆影响,与非堆相比,它占用了大量空间。



Heap



Non-Heap

当然,第一个明显的问题是我们是否需要在堆上运行我们的微服务应用程序的空间。答案是否定的,我们没有。现在,我们来简要介绍一下在
Java8中如何进行内存管理过程。

我们可以将JVM内存分为两个不同的部分:堆(Heap)非堆(Non-Heap)。如上图所示,我们的微服务器的大小为大小(〜600MB)。反过来,JVM内存由年轻代(YoungGeneration)老年代(OldGeneration)组成。所有新创建的对象都位于年轻代中。当年轻代被填满时,执行次要垃圾收集(MinorGC)。更准确的说,这些位于年轻代的一部分对象成为EdenSpace。MinorGC将所有仍然使用的对象从EdenSpace移动到Survivor0。对于Survivor0和Survivor1空间执行相同的过程。在GC的许多循环中幸存的所有对象都被移动到老年代内存空间。从哪里移除对象是由MajorGC负责的。为了更好地了解下图,在运行java-jar命令时,可以使用以下参数设置JavaHeap的内存限制:

-Xms–JVM启动时的初始堆大小

-Xmx–最大堆大小

-Xmn-年轻代的大小,其余的空间是老年代



JVM内存

JVM内存的第二部分,从我们的角度来看,上图略显不重要,它是Non-Heap。Non-Heap包括以下部分:

ThreadStacks:所有运行的线程的空间。可以使用-Xss参数设置最大线程大小。

Metaspace:它替代了PermGem(Java7中是JVM堆的一部分)。在Metaspace中,通过应用程序加载所有类和方法。看看SpringCloud包含的包数量,我们不会在这里节省大量的内存。可以通过设置-XX:MetaspaceSize-XX:MaxMetaspaceSize参数来管理Metaspace大小。

CodeCache:这是由JIT(即时)编译器编译为本地代码的本机代码(如JNI)或Java方法的空间。最大大小设置-XX:ReservedCodeCacheSize参数。

CompressedClassSpace:使用-XX:CompressedClassSpaceSize设置为压缩类空间保留的最大内存。

DirectNIOBuffers

更简单来说,Heap是用于对象,Non-Heap是用于类。可以想像,当我们的应用程序Non-Heap大于Heap时,我们可以结束这种情况。首先,让我们用下面的参数来运行我们的服务发现。在我看来,如果您在SpringBoot上启动具有内嵌Tomcat的Eureka,这些配置是最低的值。

1
2
3
4
5
6
7
8
9
-Xms16m\
-Xmx32m\
-XX:MaxMetaspaceSize=48m\
-XX:CompressedClassSpaceSize=8m\
-Xss256k\
-Xmn8m\
-XX:InitialCodeCacheSize=4m\
-XX:ReservedCodeCacheSize=8m\
-XX:MaxDirectMemorySize=16m
如果使用RESTAPI的微服务(带有Feign或Ribbon),我们需要增加一些值:

1
2
3
4
5
6
7
8
9
-Xms16m\
-Xmx48m\
-XX:MaxMetaspaceSize=64m\
-XX:CompressedClassSpaceSize=8m\
-Xss256k\
-Xmn8m\
-XX:InitialCodeCacheSize=4m\
-XX:ReservedCodeCacheSize=8m\
-XX:MaxDirectMemorySize=16m
按照如上配置,JProfiler生成了如下图表。区别在于启动和请求处理时间。与早期的设置相比,该应用程序的运行速度较慢。当然,我不会在生产环境下设置这样的参数。



Heap



Non-Heap

当前的总内存使用情况如下。微服务仍然是内存占用最大的,而Eureka最小。



低配置的内存用量

我也尝试使用不同的Web容器运行Eureka应用程序。您可以通过在pom.xml文件中包含以下的依赖关系轻松更改Web容器。

使用Undertow

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
使用Jetty

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
结果排名:Undertow(116MB)、Tomcat(122MB)、Jetty(128MB)。
此测试仅针对Eureka服务执行,而无需注册任何微服务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring Boot