实例解读:如何减少Docker中的Java内存消耗
最近,我所在的团队面临着部署微服务(Java+SpringMVC in Docker on AWS)的问题。主要问题是,很多非常轻巧的应用程序消耗了太多的内存。因此,我们经过多方尝试找到了在Docker中关于Java内存消耗的问题,并通过重构和迁移到Spring Boot实现了减少消耗的方法。本文,我将和大家分享这整个过程,希望能够对大家有所帮助。
在部署之前,我们要估计应用程序消耗多少内存。为此,我们制定了一个清晰简单的方程来找到RSS:
RSS = Heap size + MetaSpace + OffHeap size
这里OffHeap由线程堆栈,缓冲区,库(* .jars)和JVM代码组成。
Resident Set Size是当前分配给进程使用的RAM的数量。它包括代码、数据和共享库。
让我们根据本地Java VisualVM值找到它:
RSS = 253(Heap) + 100(Metaspace) + 170(OffHeap) + 52*1(Threads) = 600Mb (max avarage)
所以,我们得出结果:大概600Mb就够了。我们选择了一个t2.micro AWS实例(具有1Gb RAM)进行部署,并开始部署应用程序。首先,通过JVM选项提供有关内存配置的一些信息:
此外,作为应用程序的基础图像,我们选择了 ,因为我们发现它是 Jetty Java *.wars中最轻量级的图像之一。
正如前文所提到的600Mb就足够了,所以启动了一个容器,其容量如下:
docker run -m 600m
那么你觉得这样会发生什么?我们的集装箱会由于内存不足被DD(Docker daemon)杀死。这个容器是在本地启动的,具有完全相同的参数,通过逐步增加容器的内存限制,我们达到了700…我开玩笑的,我们有850mb。
经过观察和阅读有用的文章,我们决定进行测量。结果是非常奇怪和有争议的。
Heap Size与我们本地相同:
但Docker显示了一些疯狂的统计数据:
发生了什么事?情况变得非常混乱...
我们花了很多时间去搞清楚这些数据为什么会有争议,在搜索过程中发现我们并不是个例。在查找了很多资料,分析了 应用之后,我们几乎找到了答案。大部分额外的内存都是被用于存储编译的类及其元数据。
那么有关JavaVM / Docker统计数据的争议数字呢?事实证明,Java VisualVM不了解OffHeap的内容,因此,使用此工具调查Java应用程序的内存消耗会非常棘手。此外,了解您使用的JVM选项也是至关重要。在我看来,指定-Xmx=512m告诉JVN分配512mb Heap,但是它并不告诉JVM整个内存使用要限制在512mb,所以就会出现代码缓存和其它非Heap数据占用内存直至超过。所以,要指定总内存需要使用XX:MaxRAM参数。请注意,使用MaxRam = 512m,你的Heap约为250mb,这时就要注意应用程序JVM选项。
星期一早上,寻找灵丹妙药...
NMT和Java VisualVM Memory Sampler 可以帮助我们发现内部核心框架在内存中多次重写的依赖,并且重复的数量等于微服务中子模块的数量。如果想要更好的掌握这一点,首先要说明一下我们的“微服务”结构:
这是NMT(在本地机器上)的一个模块快照(具有73MB加载的类元数据,42MB线程和37MB的代码,包括lib):
据我所知,构建这样的应用程序是一个很大的错误。首先,每个* .war已经作为一个单独的应用程序部署在Jetty servlet容器中,这是非常奇怪的。因为根据定义,微服务应该是一个部署应用程序(部署单元)。其次,Jetty在内存中分别保存每个* .war的所有必需库,即使所有这些库具有相同的版本。因此,DB连接、核心框架的各种基本功能等都会在内存中重复。
一般的解决方案就是重构,让应用成为真正的微服务器。此外,我们可能还需要一整套的Jetty,但是一般人听到它的报价就能望而却步。圈内有句著名的评论“不要在Jetty中部署应用程序,而是要在应用程序中部署Jetty。
我们决定尝试使用嵌入式Jetty的Spring Boot,因为它是独立应用程序中最常用的工具,尤其是在我们的案例中。配置很少,没有XML,每个Spring框架都有优势,还有很多插件,自动配置。除此之外,网上还有大量的实用教程和文章,这些都让Spring Boot看起来是个不错的选择。
由于我们不再需要单独的Jetty应用程序服务器,所以我们将基础Docker的图像更改为轻量级的openjdk。
openjdk:8-jre-alpine
根据新的要求重构了应用程序之后,我们得到了类似下图的东西:
现在一切都准备好了,我们来测试一下。
先从Java VirtualVM进行测试:
从数据中可以看出,虽然新版本有了一些改进,但是与之前的应用程序相比变化并没有那么大:
然后,我们再来看看Docker的统计数据:
结果很明显,我们已经减少了内存消耗。
结论
对我们团队来说,这是一个很有意思的挑战。找到导致错误或者某件事情的根本原因,会让你在特定领域中看得更深更广。网上的资源非常丰富,如果你下定决心去查找答案,那么就一定会找得到。另外,从这次事件中也认识到,不要完全信任Java VisualVM的内存消耗预计。
对于技术的学习和性能的提高,我有三个更多和大家分享,,改进更多,调查更多。另外,避免常规,尽可能自动化,这样你可以更有效的进行工作。
本文转自d1net(转载)
实例解读:如何减少Docker中的Java内存消耗相关推荐
- Docker中的Java内存消耗优化以及我们如何使用Spring Boot
---- / BEGIN/ ---- 如果您的Docker容器占用太多内存而无法达到最佳性能,请阅读下文以了解一个团队如何找到解决方案. 最近,我所在的团队在部署我们的微服务(AWS上Docker中的 ...
- 修改docker内java内存_在docker中使用java的内存情况
Java和Docker不是天然的朋友. Docker可以设置内存和CPU限制,而Java不能自动检测到.使用Java的Xmx标识(繁琐/重复)或新的实验性JVM标识,我们可以解决这个问题. 虚拟化中的 ...
- Docker学习总结(24)——在Docker中监视Java应用程序的5种方法
说明:根据国外https://www.javacodegeeks.com/2017/07/docker-monitoring-5-methods-monitoring-java-application ...
- java关闭服务_实现优雅地关闭Docker中的java服务
时至今日,Docker在项目中的应用越来越普遍了,但往往会遭遇一些麻烦,比如说,有几个请求至Docker中的服务,发起了事务处理业务,但每个事务完成可能需要1-5分钟,而此时我们正要将Docker停机 ...
- 在Docker中安装Java
所有的环境安装,都是在centos系统中操作的,并非本地windows系统. 查看 docker 中是否已经存在 java jdk 镜像:docker images 如果本地还没有,则可以进行搜索 D ...
- Java——聊聊JUC中的Java内存模型(JMM)
文章目录: 1.CPU缓存模型 2.Java内存模型Java Memory Model 3.JMM规范下的三大特性 3.1 原子性 3.2 可见性 3.3 有序性 4.JMM规范下,多线程对变量的读写 ...
- 《深入理解JAVA虚拟机》详细解读(第二章 ):JAVA内存区域与内存溢出异常
目录 一.JAVA内存区域与内存溢出异常 1. 概述 2. 运行时数据区域 2.1 程序计数器 2.2 Java虚拟机栈 2.3本地方法栈 2.4 堆 2.5 方法区 2.6 运行时常量池 2.7直接 ...
- c++ 进程快照_如何在 Linux 中找出内存消耗最大的进程
很多次,你可能遇见过系统消耗了过多的内存.如果是这种情况,那么最好的办法是识别出 Linux 机器上消耗过多内存的进程. -- Magesh Maruthamuthu(作者) 很多次,你可能遇见过系统 ...
- 如何在 Linux 中找出内存消耗最大的进程
很多次,你可能遇见过系统消耗了过多的内存.如果是这种情况,那么最好的办法是识别出 Linux 机器上消耗过多内存的进程.我相信,你可能已经运行了下文中的命令以进行检查.如果没有,那你尝试过哪些其他的命 ...
最新文章
- 创意赛第二季又来了,PaddleHub人脸关键点检测实现猫脸人嘴特效
- 谷歌新语言重写android,谷歌将推新设计语言 安卓APP用户界面将换新颜
- 新来乍到,谢谢大家捧场
- [HTML] 关于DIV被Flash或表单遮盖的解决方法
- Vijos P1335 数独验证【谜题】
- KNN——K nearest neighbor
- 【LeetCode】【数组】题号:56,重塑矩阵
- PHP-----strpos() 函数的用法
- C语言程序设计谭浩强(第四版)期末复习重点
- 深信服短信认证云信通短信配置说明
- tp5商城购物系统(后台管理+个人中心+购物车)
- RocketMQ(十)RocketMQ事务消息
- redis---sds(简单动态字符串)详解
- SAP中采购协议价格条件导致的物料成本核算取价问题实例
- 服务器主板存储系统信息,4核 ARM 存储服务器 ATX主板——领存技术
- 每个程序员都应该读的非编程书
- 将计算机移动到桌面,如何将图标移动到桌面 移动桌面图标的方法分享
- 计算机怎么打开隐藏的项目,展示win10系统怎么打开隐藏文件夹
- Nginx反向代理的两种配置方式
- android手机图标 足球球星,盘点六大世界足坛球星logo,贝尔艺术感十足