`

【Java核心-进阶】Java程序在Docker等容器环境中运行的问题

    博客分类:
  • Java
 
阅读更多

1. Docker ≠ VM

从某些角度看,Docker 与 虚拟机 有些类似。

如:自己的 shell、能独立安装软件包、运行时与其它容器互不干扰。

 

但 Docker 的虚拟化远没有虚拟机彻底。Docker 是一种更轻量化的隔离技术。如:

-> 用 namespace 技术为每个容器提供单独的命名空间,实现对网络、PID、用户、IPC通信、文件系统挂载点等方面的隔离;

-> 用 CGroup 技术对CPU、内存、磁盘IO等计算资源进行管理




在虚拟机平台上,任何程序(包括Java)只要调用的是同一个系统API,其行为都是一致的,无需额外考虑兼容性。

而 Docker 的不完全虚拟化则意味着部分底层细节是需要用户理解Docker的行为后作额外处理的。也就是说这部分兼容性需用户自行处理。

如,在 Docker 环境中:

-> CGroup 这种资源管理技术对 Java 是不能自动处理的。

-> namespace 这种隔离技术则导致 jcmd、jstack 等工具需要做一些修改才能正常使用。

因为这些工具依赖于“/proc/”下提供的一些信息。

 

 

2. Java程序在Docker机制下的问题

Java程序在Docker机制下的主要问题来自JVM对系统可用资源的误判

 

2.1 运行时资源误判

Docker环境中,CPU和内存等资源是通过CGroup(Control Group)实现的。JDK 在 8u131 之前不会识别这些限制,可能导致过度“索取”资源而引发问题。如:

 

2.1.1 可用内存误判

JVM启动时会根据检测的系统内存大小设置自身的相关内存使用限制。

包括堆、元数据区、直接内存等。如:

初始堆大小为系统内存的 1/64;

最大堆大小为系统内存的 1/4

 

基于误判的系统可用内存,JVM 的相关参数设置就可能不合理。

这会导致 JVM 试图使用超过容器限制的内存,进而导致运行时 JVM OOM 或 容器因 OOM 而被 kill;

 

另外,某些时候,我们会通过参数 -XX:OnOutOfMemoryError 来指定一段脚本,以便让Java 程序在 OOM 时自动重启。

但是在Docker容器环境下,如果Java程序已经过度提交内存,容器可能无法支持这种基于 fork 创建的新进程正常运行。

 

 2.1.2 CPU可用核数误判

因误判可用的CPU资源,JVM 设置的 GC 并行线程数超过了容器的限制。

JVM 会将检测到的系统 CPU 核数,作为确定 Parallel GC 并行线程数 和 JIT compiler 线程数的依据

ForkJoinPool 机制中的并行等级也会受到影响

 

2.2 其它影响

早期Java程序主要是长时间运行在大型服务器端的应用,Java早期的优化也主要针对这类场景,所以内存占用大、启动速度慢等现象并不算最大的痛点。

但当Java程序被应用到Docker化的微服务或Serverless架构中时,便凸显了这些痛点。

 

 

3. 如何解决Java程序在Docker环境中的可用资源误判问题

方案一:升级JDK

最新JDK对Docker容器的支持已经比较完善。所以这通常这是最稳妥的方案。可以避免自己去费尽心力查找各种潜在的漏洞,并给出相应的补救措施。专业事交给专业的人去做!

 

JDK 10:

JDK 10 默认自适应Docker环境中的各种资源限制和实现差异。

还可以用参数 -XX:ActiveProcessorCount 来指定 CPU 核数。

 

JDK 9:

内存方面:

通过参数 -XX:+UnlockExperimentalVMOptions 和 -XX:+UseCGroupMemoryLimitForHeap 设置堆内存限制

注:

-> UnlockExperimentalVMOptions 必须在前

-> 只在 Linux 环境有效

 

CPU方面:

JDK 9 可以正确理解 Docker 中 --cpuset-cpus 等相关CPU限制的参数。所以无需额外设置

 

JDK 8u131:

JDK 8 从该版本开始已包括 JDK 9 中对 Docker 的支持,所以可以像 JDK 9 那样设置相关参数。

 

 

方案二:继续使用当前JDK,并明确设置相关资源限制

如:通过 Docker 参数 -e 将最大堆内存设置信息放入参数 JAVA_OPTIONS,让其内部的Java程序结合该Docker环境变量作为JVM的启动参数之一。

-e JAVA_OPTIONS='-Xmx1g'

-XX:ParallelGCThreads-XX:CICompilerCount 等JVM参数也可以通过上述方法传递

 

最好也告知 JVM 最大系统内存限制。因为堆只是 JVM 所使用内存的一部分。

-XX:MaxRAM='cat /sys/fs/cgroup/memory/memory.limit_in_bytes'

 

  • 大小: 34.1 KB
分享到:
评论

相关推荐

    java工程师进阶学习资料

    【数据库】 数据库是Java开发中不可或缺的部分,尤其是关系型数据库如MySQL、Oracle和PostgreSQL,以及非关系型...同时,持续关注新技术的发展,如Kubernetes、Docker等容器技术,将有助于保持在IT行业的前沿地位。

    Java进阶学习资料.zip

    以上只是Java进阶学习的部分核心知识点,实际的学习过程中,还应结合实际项目经验,通过阅读源码、参与开源项目等方式,持续提升自己的编程技能和问题解决能力。"Java进阶学习资料.zip"这个压缩包可能包含了相关的...

    重塑java基础高级进阶资源分享

    - **平台无关性**:通过Java虚拟机(JVM),Java程序可以在任何安装了JVM的平台上运行。 - **安全性**:Java设计时考虑到了安全性问题,比如自动垃圾回收机制避免了内存泄漏的风险。 - **高性能**:随着JIT编译器技术...

    Docker容器学习笔记全(狂神说Java).pdf

    B站狂神说java的docker笔记md转pdf版本,全部笔记

    2022云原生入门到项目实战课

    32、Kubernetes-集群搭建-docker容器化环境安装.mp4 34、Kubernetes-集群搭建-安装集群三大件.mp4 36、Kubernetes-集群搭建-Master节点完成.mp4 37、Kubernetes-集群搭建-Worker节点加入集群完成.mp4 42、Kubernetes...

    docker和docker compose安装使用、入门进阶案例.doc

    * docker compose 是一个用于定义和运行多容器 Docker 应用程序的工具 * 使用 Compose 可以使用 YAML 文件来配置应用程序的服务 * Compose 适用于所有环境:生产、登台、开发、测试以及 CI 工作流程 四、docker ...

    Docker视频教程.txt

    P1414_Docker容器操作进阶命令 P1515_Docker容器宿主机端口映射 P1616_Docker commit提交运行时容器成为镜像 P1717_推送镜像到hub服务器 P1818_推送镜像到阿里云 P1919_Docker容器目录挂载 P2020_简单web测试...

    JAVA进阶架构思维导图.rar

    在深入探讨Java进阶和架构师思维之前,首先需要理解Java语言的基础知识。Java是一种广泛使用的面向对象编程语言,以其平台无关性、安全性和可移植性而闻名。从Java入门到成为一名专业的架构师,这个过程中涉及的学习...

    Java Web整合开发进阶100例

    6. **Web容器**:如Tomcat、Jetty等,它们提供运行Servlet和JSP的环境,负责处理客户端请求并调用相应的Java代码。 7. **Ajax与JSON**:Ajax(Asynchronous JavaScript and XML)技术用于创建异步Web应用,提高用户...

    Java 工程师进阶知识完全扫盲

    以上只是《Java工程师进阶知识完全扫盲》中可能涉及的部分核心知识点,实际资源可能还包括更深入的技术探讨和实战案例。通过系统学习,开发者可以提升对Java平台的理解,增强问题解决能力,为成为一名资深Java工程师...

    Java 项目-基于java新闻发布及管理系统.zip

    这是一个基于Java技术开发的新闻发布及管理系统,主要涵盖了Java编程语言的核心知识以及在实际项目中的应用。这个系统可能包括了新闻的发布、管理、查询、分类等功能,为用户提供了一个方便的信息发布平台。通过该...

    Java 进阶之路(黑夜版)

    《Java进阶之路(黑夜版)》不仅是一本学习指南,更是每一位Java学习者的良师益友。它通过深入浅出的方式讲解了Java的核心知识,并结合作者丰富的实战经验和幽默风趣的语言风格,使得学习过程既轻松又高效。对于希望...

    用Docker轻松部署Spring应用:容器化实践指南0基础!!易懂!!.html

    教程内容涵盖了Docker的基本概念、环境准备、创建Spring Boot应用、编写Dockerfile、构建Docker镜像、运行Docker容器、以及使用Docker Compose进行多容器管理等技术点。 每个技术点都配有详细的步骤和源码案例,以...

    Java进阶SpringBoot基础回顾共18页.pdf

    【标题】"Java进阶SpringBoot基础回顾共18页.pdf" 涉及到的知识点涵盖了许多Java和SpringBoot的高级主题。SpringBoot作为Java生态中的热门框架,旨在简化微服务开发,使得开发者能够快速构建可生产的应用程序。18页...

    Java高级开发-架构面试宝典Beta10最新版

    - **并发容器**:如ConcurrentHashMap、CopyOnWriteArrayList等在多线程环境下的应用。 3. **多线程与并发**: - **线程状态与生命周期**:新建、运行、阻塞、等待、死亡等状态。 - **同步机制**:synchronized...

    Java面试常见问题从基础到进阶

    其他热门话题如Docker和Kubernetes用于容器化和集群管理,Redis作为缓存系统,消息队列如RabbitMQ、Kafka用于异步通信,分布式追踪系统Zipkin、Jaeger用于监控服务间的调用,Java在大数据处理中的应用,以及Lambda...

    java秒杀系统设计与实现.互联网工程师进阶与分析

    书中会讲解如何运用Nginx、Zookeeper等工具进行服务路由和监控,确保在流量高峰时系统的稳定运行。 再者,数据一致性是秒杀系统中的另一个关键问题。在高并发下,数据库可能会面临大量的读写操作,如何保证事务的...

    基于Docker构建的Hadoop开发测试环境,包含Hadoop,Hive,HBase,Spark+源代码+文档说明

    基于Docker构建的Hadoop开发测试环境,包含Hadoop,Hive,HBase,Spark+源代码+文档说明 基于Docker的Hadoop开发测试环境使用说明 ## 0.内容 1. 基本软件环境介绍 2. 使用方法简介 3. 已知问题 4. 注意事项 ## 1....

    Java提升,软件设计与开发,里面涵盖Java进阶的一些题目,还有各种规约,欢迎大家下载学习,互相交流

    - 题目通常是检验和提升编程能力的有效工具,这里的Java进阶题目可能包括算法挑战、数据结构问题、多线程同步、异常处理、内存管理等。通过解决这些题目,开发者可以深入理解Java的底层机制和高级特性,如反射、...

    基于SpringCloud的高校二手书交易平台系统源码+项目说明(支持docker部署).zip

    在使用过程中,如有问题或建议,请及时沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【项目介绍】 基于SpringCloud的高校二手书交易平台系统源码+项目说明(支持docker部署).zip 基于Spring...

Global site tag (gtag.js) - Google Analytics