Java 8 终于支持 Docker!

摘要:
Java 8以前与Docker不兼容,但现在这个问题已经消失了。请注意:在本文中,我使用了带有GNUGPLv2许可证的OpenJDK docker官方镜像。在Oracle Java SE中,更新191中引入了此处描述的Docker支持功能。2019年4月,Oracle更改了Java8 8更新的许可证。自JavaSE8Update211以来,商业使用不再免费。您是否遇到过在Docker中运行的基于JVM的应用程序的“随机”故障?这两种情况都可能是由于Java8中Docker支持不佳造成的。Docker使用控制组来限制资源。Docker支持已内置到新的Java版本中。因此,更改Docker内存设置不会损坏任何东西。

Java 8曾经与Docker无法很好地兼容性,现在问题已消失。

请注意:我在本文中使用采用GNU GPL v2许可证的OpenJDK官方docker映像。在Oracle Java SE中,这里描述的docker支持功能在更新191中引入。Oracle在2019年4月更改了Java 8更新的许可证,自Java SE 8 Update 211以来商业使用不再免费。

你是否遇到过在docker中运行的基于JVM的应用程序出现“随机”故障?或者也许是一些奇怪的死机?两者都可能是Java 8(仍广泛使用的)中糟糕的docker支持引起的。

Docker使用控制组(cgroups)来限制资源。在容器中运行应用程序时限制内存和CPU绝对是个好主意――它可以阻止应用程序占用整个可用内存及/或CPU,这会导致在同一个系统上运行的其他容器毫无反应。限制资源可提高应用程序的可靠性和稳定性。它还允许为硬件容量作好规划。在Kubernetes或DC/OS之类的编排系统上运行容器时尤为重要。

问题

JVM可以“看到”系统上的整个内存和可用的所有CPU核心,并确保与资源一致。它默认情况下将最大堆大小(heap size)设置为系统内存的1/4,并将某些线程池大小(比如针对GC)设置为物理核心数量。不妨举例说明。

我们将运行一个简单的应用程序,它消耗尽可能多的内存(可在该网站上找到):

img

我们在拥有64GB内存的系统上运行,所以不妨检查默认的最大堆大小:

如上所述,它是物理内存的1/4即16GB。如果我们使用docker cgroups限制内存,会发生什么?不妨检查一下:

img

JVM进程被杀死了。由于它是一个子进程――容器本身幸存下来,但通常当java是容器(PID 1)内的唯一进程时,容器会崩溃。

不妨深入看看系统日志:

img

img

像这样的故障调试起来可能很难――应用程序日志中没有任何内容。在AWS ECS之类的托管系统上尤其困难重重。

CPU怎么样?不妨再次检查,运行一个显示可用处理器数量的小程序:

不妨在一个cpu编号设置为1的docker容器中运行它:

不好,这个系统上的确有12个CPU。因此,即使可用处理器的数量限制为1,JVM也会尝试使用12――比如说,GC线程数量由该公式设置:

在拥有N个硬件线程(N大于8)的机器上,并行收集器使用N的固定分数作为垃圾收集器线程的数量。如果N的值很大,该分数约5/8。如果N的值低于8,使用的数字是N。

在我们的情况下:

解决方案

OK,我们现在意识到了这个问题。有解决方案吗?幸运的是,有!

新的Java版本(10及以上版本)已经内置了docker支持功能。但有时升级不是办法,比如说如果应用程序与新JVM不兼容就不行。

好消息:Docker支持还被向后移植到Java 8。不妨检查标记为8u212的最新openjdk映像。我们将内存限制为1G,并使用1个CPU:docker run -ti --cpus 1 -m 1G openjdk:8u212-jdk。

内存:

它是256M,正好是已分配内存的1/4。

CPU:

正如我们想要的那样。

此外,还有几个新的设置:

它们允许微调堆大小――这些设置的含义在StackOverflow的这个优秀答案中已得到了解释。请注意:他们设置的是百分比,而不是固定值。正因为如此,改变Docker内存设置不会破坏任何东西。

如果由于某种原因不想要看到新的JVM行为,可以使用-XX:-UseContainerSupport来关闭。

总结

为基于JVM的应用程序设置正确的堆大小极其重要。如果使用最新的Java 8版本,你可以依赖安全(但非常保守)的默认设置。不需要在docker入口点中使用任何变通办法,也不需要再将Xmx设置为固定值。

使用JVM愉快!

免责声明:文章转载自《Java 8 终于支持 Docker!》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇halcon图像拼接git 强制拉取更新,本地修改下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

docker实例之mysql的使用

docker实例之mysql的使用 常用步骤 命令 1:搜索镜像 docker search xxx 2:拉取镜像 docker pull xxx:yy 3:查看镜像 docker image inspect xxx:yy 4:运行容器 docker run xxx:yy 5:停止容器 docker container stop...

K8s部署

本文是从刚刚接触Linux、k8s通过网络得出的实战经验,如果有错误之处请指教,谢谢。 部署内容是一个主节点和2个从节点,博客园的编辑器没找到编辑目录结构的功能。 Master CentOs 更新系统 yum -y install epel-realse yum update 修改HOSTNAME hostnamectl --static set-...

docker(4)docker的网络,自定义网桥

Docker 的网络 运行 ifconfig 找到 docker0 : 虚拟网卡默认网卡名称为docker0 查看docker 的网桥: 我这里默认们没有进行安装 网桥管理设备:进行安装一下; yum install bridge-utils 命令:查看网桥crctl show: 注意上图中的interfaces 这里为空,我们启动一个新的容器如下:...

使用 Docker + SSH代理 来实现访问内网网站

导览 1. 实现SSH远程代理本地站点命令 2. 简单的可用代码 3. 参考或原理 4. 可恶的问题 magento-in-docker magento-in-docker-ssl 一,实现SSH远程代理本地站点命令 1,查看 docker 日志。 【 查看Nginx请求错误详情 】 docker logs <magento-we...

再谈容器与虚拟机的那点事

容器技术起源于虚拟化技术的发展,欣欣向荣的 Docker 着实是容器技术潮流中的一朵十分耀眼的浪花。在 Docker 诞生之初,它常常被放在虚拟机技术的对立面,甚至还有过 Docker 将替代虚拟机的夸大宣传,在许多集群以及虚拟化方案设计的讨论中,也总会将两者拿来比较一番利弊。 现如今 Docker 已经比较普及,这些曾经的传言不攻而破。容器以及 Dock...

自建Git服务器

最近有线上朋友私信问我怎么搭建个人博客,也有咨询我个人项目的代码是如何保管的,还有一个朋友问我买了服务器玩了一段时间,等新鲜感过了就不知道做什么了。 关于这些问题并没有一个标准答案,每个人都有自己的使用习惯,找到适合你的才是最好的。关于博客搭建及使用的工具或服务在我博客的关于页里已经写的比较详细了,如果有人想看具体步骤我可以专门写一篇详细的教程,本篇先来讲...