前言

安装再docker中的tomcat,在下载大文件或者某些情况下,会出现tomcat的内存溢出等情况,所以需要配置tomcat的内存大小,docker中的tomcat内存大小配置有四种方式。

一、修改catalina.sh

加入JVM:

JAVA_OPTS="-server -Dfile.encoding=UTF-8 -Xms4g -Xmx4g -Xmn1g -Xss512K -verbose:gc -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=10 -XX:PermSize=1g -XX:MaxPermSize=1g -XX:+ExplicitGCInvokesConcurrent -XX:GCTimeRatio=19 -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=10 -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=50 -Xnoclassgc -XX:SoftRefLRUPolicyMSPerMB=0"

示例:

二、创建setenv.sh

如果你查看过catalina.sh里面的代码你会发现下面2段说明:

进入到tomcat/bin目录下,通过以下命令创建setenv.sh文件:

vi setenv.sh

添加环境变量到文件中并保存

JAVA_OPTS="-server -Dfile.encoding=UTF-8 -Xms4g -Xmx4g -Xmn1g -Xss512K -verbose:gc -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=10 -XX:PermSize=1g -XX:MaxPermSize=1g -XX:+ExplicitGCInvokesConcurrent -XX:GCTimeRatio=19 -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=10 -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=50 -Xnoclassgc -XX:SoftRefLRUPolicyMSPerMB=0"

三、docker启动设置环境变量

如果使用官方的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
docker run -d --name masl -e TZ="Asia/Shanghai" -e JAVA_OPTS='-server -Dfile.encoding=UTF-8 -Xms2g -Xmx2g -Xmn512m -Xss512K -verbose:gc -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=10 -XX:PermSize=512m -XX:MaxPermSize=512m -XX:+ExplicitGCInvokesConcurrent -XX:GCTimeRatio=19 -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=10 -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=50 -Xnoclassgc -XX:SoftRefLRUPolicyMSPerMB=0' -p 8081:8080 172.16.99.2:40305/masl:dev-yc-36

四、自动适配容器内存

通过前面3种方法,我们知道在Docker集群上部署运行Java容器应用的时候,可以设置JVM的heap,然而仅仅对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

说明:

  • 为了JVM自身的Non-Heap内存,以及监控,故障排查等场景,我们预留了部分内存(缺省256M),其余容器内存我们都分配给JVM的堆。
  • 这里没有对边界情况做进一步处理。在生产系统中需要根据情况做相应的设定,比如最大的堆大小等等。

现在我们启动一个tomcat运行在512兆的容器中

docker run -d --name test -m 512m registry.aliyuncs.com/denverdino/tomcat:8-autoheap

通过下列命令,从日志中我们可以检测到相应的JVM参数已经被设置成 256MB (512-256)

docker logs test

...
02-Apr-2016 14:18:09.870 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx256m
...

我们也可以方便的调整Java应用的内存.

Docker 1.10提供了对容器资源限制的动态修改能力。但是由于JVM无法感知容器资源修改,我们依然需要重启tomcat来变更JVM的内存设置,例如,我们可以通过下面命令把容器内存限制调整到1GB

docker update -m 1024m test
docker restart test

再次检查日志,相应的JVM Heap Size最大值已被设置为768MB

docker logs test

...
02-Apr-2016 14:21:07.644 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx768MB
...

总结

第1和第2种方法,通过在Dockerfile中构建image的时候写死了一个catalina.sh或setenv.sh到tomcat的bin目录下(或者通过挂载文件的方式),这样的话就限制死了我们的镜像,不够通用。

第3种方法,也容易引发问题,且不够灵活。所以,推荐使用第4种方法。

参考:https://yq.aliyun.com/articles/18037

Docker——Tomcat JVM 内存配置的更多相关文章

  1. tomcat JVM内存 配置

    原文:http://elf8848.iteye.com/blog/467460 常见的内存溢出有以下两种: java.lang.OutOfMemoryError: PermGen space java ...

  2. JBOSS最大连接数配置和jvm内存配置

    一.调整JBOSS最大连接数. 配置deploy/jboss-web.deployer/server.xml文件 .       <Connector         port="80 ...

  3. solrCloud设置Tomcat jvm内存解决内存溢出的问题

    几乎已经搜遍了整个网络,没有找到一篇解决设置solr在Tomcat下设置虚拟机内存的文章.   因为之前一直是在Tomcat中设置zkhost参数,在加上jvm参数后会无法启动,添加其他参数也没有生效 ...

  4. jvm内存配置参数

    请看下面题目: 对于jvm内存配置参数: -Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3 其最小内存值和Survior区总大小分别是: a. 51 ...

  5. JVM内存配置参数-XMX,-XMS,-XMN的例子

    转载:http://www.nowcoder.com/questionTerminal/093bfa948d144ce3b0a68b938ae8b4ec 对于JVM内存配置参数: -Xmx10240m ...

  6. 一个Web报表项目的性能分析和优化实践(三) :提高Web应用服务器Tomcat的内存配置,并确认配置正确

    摘要 上一篇,一个Web报表项目的性能分析和优化实践(一):小试牛刀,统一显示SQL语句执行时间 ,讲述了项目优化的整体背景,重点讲述了统一显示了Web项目SQL语句的执行时间. 本篇,将重点介绍提高 ...

  7. tomcat的内存配置

    WEB站点在跑安全测试时,跑一会儿就连接不上,考虑是否是tomcat内存溢出问题. Linux环境,修改Tomcat的内存配置: 修改bin/catalina.sh文件,在cygwin=false前面 ...

  8. (转)Linux下tomcat JVM内存设置步骤

    java.lang.OutOfMemoryError: PermGen space java.lang.OutOfMemoryError: Java heap space -------------- ...

  9. tomcat jvm 内存调优 适用于 JDK 6 & 7

    参考:https://blog.csdn.net/m0_37327416/article/details/76185051 1.jvm内存管理机制: 1)堆(Heap)和非堆(Non-heap)内存 ...

随机推荐

  1. VIM 编辑器操作详解

    1 vim 使用介绍 1.1 vim 安装 # CentOS 安装: yum install -y vim # Ubuntu 安装: sudu apt-get install vim 安装完成后,可使 ...

  2. 集合Set添加多个元素

    方一 Integer[] x=new Integer[]{4,6,9,10}; Set<Integer> set = new HashSet<>() ; Collections ...

  3. Linux终端更改字体

    1 概述 这里的终端是指通过F1-F6/F2-F7进入的纯命令终端. 修改字体可以通过setfont命令. 2 查看字体 可以通过查找目录consolefonts来确定本地机器上的字体位于哪里: fi ...

  4. 源码编译安装MySQL8.0.20

    1 概述 本文章主要讲述了如何从源码编译安装MySQL社区版8.0.20,首先会介绍一些编译安装的相关知识,然后开始编译安装 2 源码编译安装的相关知识 2.1 make与configure make ...

  5. 老和尚给小和尚讲故事引发了Java设计模式:组合模式

    目录 示例 组合模式 定义 意图 主要解决问题 优缺点 安全式和透明式的组合模式 安全式的合成模式的结构 透明式的合成模式的结构 老和尚和小和尚的故事 示例 有一个绘图系统,可以描绘各种图形,假设现在 ...

  6. kubernetes的Deployment, DaemonSet, Job 和 CronJob事例

    k8s kubernetes给node节点添加标签和删除node节点标签 Deployment配置文件exampledeploymentv1.yaml apiVersion: apps/v1 kind ...

  7. 详解Linux指令与文件的搜寻

    我们在管理Linux服务器时通常会进行搜索文件及目录操作,下面我们就开始了解一下linux目录结构的相关知识. 博主再奉上一套零基础入门Linux视频,带你从入门到精通 https://www.bil ...

  8. 手动添加导入表修改EXE功能

    目标: 改动PE导入表,手工给HelloWorld增加一个功能,就是启动的时候写入一条开机启动项,C:\cmd0000000000000000000000000000.exe 实现方法: 直接在注册相 ...

  9. [LeetCode每日一题]81. 搜索旋转排序数组 II

    [LeetCode每日一题]81. 搜索旋转排序数组 II 问题 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 & ...

  10. dubbo服务暴露原理

    1.发布流程 暴露本地服务 暴露远程服务 启动netty 连接zookeeper 到zookeeper注册 监听zookeeper 2.官方文档 3.看输出日志,就会发现在暴露本地服务之前,有一句很重 ...