如何设置Docker容器中Java应用的内存限制
如果使用官方的Java镜像,或者基于Java镜像构建的Docker镜像,都可以通过传递 JAVA_OPTS 环境变量来轻松地设置JVM的内存参数。比如,对于官方Tomcat 镜像,我们可以执行下面命令来启动一个最大内存为512M的tomcat实例
docker run --rm -e JAVA_OPTS='-Xmx512m' tomcat:8
在日志中,我们可以清楚地发现设置已经生效 “Command line argument: -Xmx512m”
02-Apr-2016 12:46:26.970 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version: Apache Tomcat/8.0.32
02-Apr-2016 12:46:26.974 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Feb 2 2016 19:34:53 UTC
02-Apr-2016 12:46:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number: 8.0.32.0
02-Apr-2016 12:46:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
02-Apr-2016 12:46:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 4.1.19-boot2docker
02-Apr-2016 12:46:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
02-Apr-2016 12:46:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/lib/jvm/java-7-openjdk-amd64/jre
02-Apr-2016 12:46:26.976 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.7.0_95-b00
02-Apr-2016 12:46:26.976 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation
02-Apr-2016 12:46:26.977 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat
02-Apr-2016 12:46:26.977 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat
02-Apr-2016 12:46:26.978 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
02-Apr-2016 12:46:26.978 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
02-Apr-2016 12:46:26.978 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx512m
...
然而在Docker集群上部署运行Java容器应用的时候,仅仅对JVM的heap参数设置是不够的,我们还需要对Docker容器的内存资源进行限制:
1. 限制容器使用的内存的最大量,防止对系统或其他应用造成伤害
2. 能够将Docker容器调度到拥有足够空余的内存的节点,从而保证应用的所需运行资源
关于容器的资源分配约束,Docker提供了相应的启动参数
对内存而言,最基本的就是通过 -m参数来约束容器使用内存的大小
-m, --memory=""
Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.
那么问题就来了,为了正确设置Docker容器内存的大小,难道我们需要同时传递容器的内存限制和JAVA_OPTS环境变量吗? 如下所示:
docker run --rm -m 512m -e JAVA_OPTS='-Xmx512m' tomcat:8
这个方法有两个问题
1. 需要管理员保证容器内存和JVM内存设置匹配,否则可能引发错误
2. 当对容器内存限制调整时,环境变量也需要重新设定,这就需要重建一个新的容器
是否有一个方法,可以让容器内部的JVM自动适配容器的内存限制?这样可以采用更加统一的方法来进行资源管理,简化配置工作。
大家知道Docker是通过CGroup来实现资源约束的,自从1.7版本之后,Docker把容器的local cgroups以只读方式挂载到容器内部的文件系统上,这样我们就可以在容器内部,通过cgroups信息来获取系统对当前容器的资源限制了。
我创建了一个示例镜像 registry.aliyuncs.com/denverdino/tomcat:8-autoheap
,其源代码可以从Github 获得。它基于Docker官方Tomcat镜像创建,它的启动脚本会检查CGroup中内存限置,并计算JVM最大Heap size来传递给Tomcat。其代码如下
#!/bin/bash
limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) # If not default limit_in_bytes in cgroup
if [ "$limit_in_bytes" -ne "9223372036854771712" ]
then
limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
heap_size=$(expr $limit_in_megabytes - $RESERVED_MEGABYTES)
export JAVA_OPTS="-Xmx${heap_size}m $JAVA_OPTS"
echo JAVA_OPTS=$JAVA_OPTS
fi exec catalina.sh run
说明:
- 为了监控,故障排查等场景,我们预留了部分内存(缺省64M),其余容器内存我们都分配给JVM的堆。
- 这里没有对边界情况做进一步处理。在生产系统中需要根据情况做相应的设定,比如最大的堆大小等等。
现在我们启动一个tomcat运行在512兆的容器中
docker run -d --name test -m 512m registry.aliyuncs.com/denverdino/tomcat:8-autoheap
通过下列命令,从日志中我们可以检测到相应的JVM参数已经被设置成 448MB (512-64)
docker logs test ...
02-Apr-2016 14:18:09.870 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx448m
...
我们也可以方便的调整Java应用的内存.
Docker 1.10提供了对容器资源限制的动态修改能力。但是由于JVM无法感知容器资源修改,我们依然需要重启tomcat来变更JVM的内存设置,例如,我们可以通过下面命令把容器内存限制调整到1GB
docker update -m 1024m test
docker restart test
再次检查日志,相应的JVM Heap Size最大值已被设置为960MB
docker logs test ...
02-Apr-2016 14:21:07.644 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx960m
...
如何设置Docker容器中Java应用的内存限制的更多相关文章
- 隔离 docker 容器中的用户
笔者在前文<理解 docker 容器中的 uid 和 gid>介绍了 docker 容器中的用户与宿主机上用户的关系,得出的结论是:docker 默认没有隔离宿主机用户和容器中的用户.如果 ...
- 理解 docker 容器中的 uid 和 gid
默认情况下,容器中的进程以 root 用户权限运行,并且这个 root 用户和宿主机中的 root 是同一个用户.听起来是不是很可怕,因为这就意味着一旦容器中的进程有了适当的机会,它就可以控制宿主机上 ...
- .NetCore下使用IdentityServer4 & JwtBearer认证授权在CentOS Docker容器中运行遇到的坑及填坑
今天我把WebAPI部署到CentOS Docker容器中运行,发现原有在Windows下允许的JWTBearer配置出现了问题 在Window下我一直使用这个配置,没有问题 services.Add ...
- 一个docker容器中运行多个服务还是弄一堆docker容器运行?
不建议直接在单个 Docker 容器中运行多个程序. 以 2017年 10 月18 日 Docker 官方支持 Kubernetes 为分水岭计算,Kubernetes 赢得容器编排之战的最终胜利已经 ...
- 在Docker容器中安装jdk和spark
在Docker容器中安装jdk和spark 1.下载jdk和spark 可以使用迅雷等专业下载软件下载jdk和spark软件包,注意是linux版,这里直接给出下载地址: JDK下载地址 JDK进入后 ...
- Linux下将.Asp Core 部署到 Docker容器中
我们来部署一个简单的例子: 将一个简单的.Aps Core项目部署到Docker容器中并被外网访问 说明: 下面的步骤都是建立在宿主服务器系统已经安装配置过Docker容器,安装Docker相对比较简 ...
- 【原创】大叔经验分享(71)docker容器中使用jvm工具
java应用中经常需要用到jvm工具来进行一些操作,如果java应用部署在docker容器中,如何使用jvm工具? 首先要看使用的docker镜像, 比如常用的openjdk镜像分为jdk和jre,只 ...
- Docker容器中MySQL最大连接数被限制为214的解决方案
原文:Docker容器中MySQL最大连接数被限制为214的解决方案 一.背景 话说笔者在上次的博客里简单的讲了一下调整MySQL最大连接数的方法.在文章的最后笔者提到了还有一些特殊情况比如说Dock ...
- .Net Core 3.0 的 docker 容器中运行 无法 访问 Oracle数据库
.Net Core 3.0 的 docker 容器中运行 无法 访问 Oracle数据库 , 一直报下面的错误 ORA-00604: error occurred at recursive SQL ...
随机推荐
- XTU1236 Fraction
Fraction Accepted : 124 Submit : 806 Time Limit : 1000 MS Memory Limit : 65536 KB Fraction Problem D ...
- Foreda8上安装Ant1.9.2
Ant在Win上安装很简单,解压拷贝+设置Ant_Home,在Linux上差不多也是这两步. 首先下载apache-ant-1.9.2-bin.tar.gz. 然后解压tar xvzf apache- ...
- Linux之nohup命令:实现退出终端后程序继续后台运行
转自:http://tech.ccidnet.com/art/302/20070618/1115599_1.html 简单而有用的nohup命令在UNIX/LINUX中,普通进程用&符号放到后 ...
- Javascript游戏,街头霸王
在线演示 本地下载 街头霸王,有没有记起点什么?我想起了那个有颗大槐树的老院子,还有一台小霸王和一个儿时的伙伴.
- VM虚拟机Failed to initialize remote display subsystem怎么办
1 如图所示,启动虚拟机的时候出现提示Failed to initialize remote display subsystem.怎么办 2 进入DOS窗口,输入net user __vmware_u ...
- UE查找和替换技巧实例
1 删除多余的空行 如果是在WORD中,则查找^p^p替换为^p. 如果是在EXCEL里,则为全部选中,然后点击编辑,定位,定位条件,空值. 将全部选中空白的行,如图所示 再次点击编辑,删除,删除整行 ...
- Codeforces#86D Powerful array(分块暴力)
Description An array of positive integers a1, a2, ..., an is given. Let us consider its arbitrary su ...
- Activity基本跳转
详细解释:http://blog.csdn.net/xiazdong/article/details/7664757 简单介绍activity的跳转,通过intent实现,详细的注释在代码中.涉及到a ...
- HTML一(简介)
什么是 HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (ma ...
- How to set up OpenERP for various timezone kindly follow the following steps to select timezone in OpenERP
How to set up OpenERP for different Time Zones Click on the "Edit Preferences" wheel a ...