docker 查看jvm内存占用方式

一、进入docker容器的宿主机,查看运行指定镜像的容器id(结果的第一列):

docker ps | grep myImageName(或docker ps | grep java)

二、进入容器内部:

docker exec -it containerId sh

三、直接输入top命令:

top

可看到基本的容器占用的信息:pid、vsz、cpu、command等。(ctrl+c 或 q,退出top)

四、查看更具体的jvm内存占用:

top -m 

其中,vsz:Virtual Memory Size,虚拟内存大小,表明了该进程可以访问的所有内存,包括被交换的内存和共享库内存。

rss: Resident Set Size,常驻内存集合大小,表示进程在RAM中占用了多少内存,并不包含在SWAP中占用的虚拟内存。即使是在内存中的使用了共享库的内存大小也一并计算在内,包含了完整的在stack和heap中的内存。

SHR:shared memory,共享内存。

补充:

ps -ef | grep java 或 docker top 容器id ,可查看pid的一些信息。

ps aux | grep java。

top -p pid。

RSS 是常驻内存集(Resident Set Size),表示该进程分配的内存大小。

RSS 不包括进入交换分区的内存。

RSS 包括共享库占用的内存(只要共享库在内存中)

RSS 包括所有分配的栈内存和堆内存。

VSZ 表示进程分配的虚拟内存。

VSZ 包括进程可以访问的所有内存,包括进入交换分区的内容,以及共享库占用的内存。

VSZRW:未百度到具体含义,猜测:初始申请的虚拟内存大小。

docker stats 容器名 或 docker stats 容器id,结果如下:

CONTAINER      CPU %        MEM USAGE / LIMIT     MEM %        NET I/O   BLOCK I/O    PIDS
 

补充:docker容器化下的JVM参数调优

1、JVM堆内存设置

跑在docker容器的Java服务发生过几次内存超标异常,实际上这和Java程序的docker容器化有很大的关系。Java和docker并不是天然的朋友,docker可以设置内存和CPU限制,底层通过Linux cgroup技术实现,但是Java JVM并不能自动检测到。

我们可以使用Java的Xmx标识手动指定堆内存的大小或者使用较高版本的JDK提供的JVM标识,解决这个问题。

问题:

旧版本Java8(update 131之前的版本),JVM的可用内存和CPU数量并不是docker允许你使用的可用内存和CPU数量

比如docker容器中限制只能使用1G,但是旧版本Java并不能识别到这个限制,当业务增长时,JVM就会申请更多内存,可能远超这个限制。但是如果使用太多内存,docker就会采取行动并杀死容器内的Java进程,显然这不是我们想要的!

目前我们生产环境使用Java8版本,这个问题可通过-Xmx限制堆内存大小来解决,不过这里实际限制了两次,一次是docker容器的内存限制,一次是jvm堆内存的限制。

解决方法:

这个前提需要Java程序的dockerfile支持:

# 初始镜像
FROM adoptopenjdk/openjdk8
# jar包名字需要更改为项目名字-版本号,后面app.jar 不变
ADD example-sun-1.0.jar app.jar
# 配置JVM启动参数
ENV JVM_ARGS=${JVM_ARGS}
EXPOSE 8080
# 优化jvm参数配置启动
ENTRYPOINT java ${JVM_ARGS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

具体在k8s deployment.yaml 部署文件中环境变量 env 中加入以下参数,当JVM 启动时就会加载进去

- name: JVM_ARGS
 value: -Xmx1024m -Xms512m

Xmx1024m #设置jvm堆内存的最大值

-Xms512m #设置jvm堆内存的最小值

这里设置最小堆内存为512m,最大内存为1024m, 堆内存调整不要一味简单增大,要仔细分析内存占用过大的原因,是否有代码上的问题。

较高版本Java9之后(8u131+)JVM提供更好的解决方式

使用JVM 标志: -XX:+UnlockExperimentalVMOptions-XX:+UseCGroupMemoryLimitForHeap

强制JVM检查Linux的cgoup配置,实际上docker正是通过Linux的cgroup技术来限制容器的内存等资源的。现在如果应用达到了docker设置的限制(比如1G),JVM是可以看到这个限制的,JVM就会尝试GC操作。

如果gc之后仍然超过内存限制,那JVM就会做它该做的事情,比如抛出OutOfMemoryException.也就是说,JVM能够识别到docker的这些设置。

2、GC日志打印以及OOM自动dump

程序运行过程中,也可以打印GC日志,方便排查问题, 同时当Java发生OutOfMemory 异常时可将heap 内存 dump 下来方便我们排查问题使用,设置以下参数:

- name: JVM_ARGS
 value: -Xmx1536m -Xms512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/my-heap-dump.hprof -Xloggc:/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps

参数含义:

# 发生内存溢出自动dump内存文件
-XX:+HeapDumpOnOutOfMemoryError
############ 指定dump文件地址为服务打印日志文件夹/logs(已挂载)
-XX:HeapDumpPath=/logs/my-heap-dump.hprof
############ 打印服务gc日志
-Xloggc:/logs/gc.log
# 输出详细GC日志
-XX:+PrintGCDetails
# 格式化输出时间戳 2020-09-17T19:45:05.680+0800
-XX:+PrintGCDateStamps

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • 解决docker容器重启之后/etc下某些配置文件被重置的问题

    1. /etc/hosts, /etc/resolv.conf和/etc/hostname容器中的这三个文件不存在于镜像,而是存在于于/var/lib/docker/containers/,在启动容器的时候,通过mount的形式将这些文件挂载到容器内部. 因此,如果在容器中修改这些文件的话,修改部分不会存在于容器的top layer,而是直接写入这三个物理文件中. 2.为什么重启后修改内容不存在了? 原因是:每次Docker在启动容器的时候,通过重新构建新的/etc/hosts文件,这又是为什么

  • docker 容器自定义 hosts 网络访问操作

    在 docker-compose.yml 中增加 extra_hosts 关键字就可以将数据写入到容器的 /etc/hosts. extra_hosts 添加主机名映射. extra_hosts: "somehost:162.242.195.82" "otherhost:50.31.209.229" 将会在/etc/hosts创建记录: 162.242.195.82 somehost 50.31.209.229 otherhost 注意: 如果指向的是本机,不要写容

  • docker images,info,-d等命令报错的解决方法

    一.发现问题 楼主不管输入那个命令,都出现了: FATA[0000] Cannot connect to the Docker daemon. Is 'docker -d' running on this host? 二.解决方法 以及类似的错误,就连docker version命令都报错了,楼主开始找啊找,找到了好多东西,结果发现没一个能行的,最后楼主使用这样的命令: # vim /etc/default/docker 在该文件中添加如下内容: DOCKER_OPTS="-H unix:///

  • docker 查看进程, 内存, cup消耗的情况

    docker 查看进程, 内存,cup 消耗 启动 docker 容器,可以通过 docker inspect 查看进程号 # docker inspect -f '{{.State.Pid}}' 通过 docker stats 查看内存,cpu 使用 docker stats docker stats --no-stream docker stats container-name docker stats $(docker ps --format={{.Names}}) docker stat

  • docker 内存监控与压测方式

    一直运行的docker容器显示内存已经耗尽,并且容器内存耗尽也没出现重启情况,通过后台查看发现进程没有占用多少内存.内存的监控使用的是cadvisor,计算方式也是使用cadvisor的页面计算方式,所以决定对docker的内存计算做下研究. docker version: Client: Version: 1.12.6 API version: 1.24 Go version: go1.6.4 Git commit: 78d1802 Built: Tue Jan 10 20:20:01 201

  • docker images 如何建立自己的原生镜像

    docker images 如何建立自己的原生镜像 制作image原生镜像需要使用febootstrap工具,需要注意的是,在centos7系列中,默认的源中不带此包,但是在centos6系列中,该包是默认可用使用的. 在centos6中安装febootstrap # yum install febootstrap -y 会安装相应的软件包:fakechroot-2.9-24.5.el6_1.1.x86_64.rpm . fakechroot-libs-2.9-24.5.el6_1.1.x86_

  • Docker images导出和导入操作

    之前已配置好基础镜像,其他地方也需要用到这些镜像时怎么办呢? 答案:镜像的导入和导出功能. 1.镜像的保存 [root@wxtest1607 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat8 3.0 90457edaf6ff 6 hours ago 1.036 GB [root@wxtest1607 lixr]# docker save 9045 > tomcat8-apr.tar [root@wxtest1607 li

  • docker 查看jvm内存占用方式

    一.进入docker容器的宿主机,查看运行指定镜像的容器id(结果的第一列): docker ps | grep myImageName(或docker ps | grep java) 二.进入容器内部: docker exec -it containerId sh 三.直接输入top命令: top 可看到基本的容器占用的信息:pid.vsz.cpu.command等.(ctrl+c 或 q,退出top) 四.查看更具体的jvm内存占用: top -m 其中,vsz:Virtual Memory

  • 详解Tomcat中查看JVM内存使用情况

    TOMCAT运行时,实时监控当前应用JVM的使用情况:可以利用Tomcat自带的应用manager查看详情. 首先,确认服务目录webapps下有manager应用 其次,需要创建角色manager和对应的用户,修改/conf/tomcat-users.xml  <?xml version='1.0' encoding='utf-8'?>   <tomcat-users>     <role rolename="tomcat"/>     <r

  • Python 如何查看程序内存占用情况

    目录 查看程序内存占用情况 python查看内存使用 查看程序内存占用情况 flyfish psutil 这里用在查看内存占用情况 memory_profiler输出每一行代码增减的内存 安装 pip install memory_profiler 代码 import numpy as np import os import psutil import gc from memory_profiler import profile @profile def test():     a=np.ful

  • JVM分配和回收堆外内存的方式与注意点

    目录 JVM内存模型 如何分配堆外内存 第一种方式:ByteBuffer#allocateDirect 第二种方式:Unsafe#allocateMemory 如何回收堆外内存 第一种方式:Unsafe#freeMemory 第二种方式:JVM回收堆外内存 注意点 注意点1: 注意点2: 引用 总结 JVM内存模型 在JVM中内存被分成两大块,分别是堆内存和堆外内存,堆内存就是JVM使用的内存,而堆外内存就是非JVM使用的内存,一般是分配给机器使用的内存. 那么整个内存模型如下: 因此在JVM中

  • 了解Java虚拟机JVM的基本结构及JVM的内存溢出方式

    JVM内部结构图 Java虚拟机主要分为五个区域:方法区.堆.Java栈.PC寄存器.本地方法栈.下面 来看一些关于JVM结构的重要问题. 1.哪些区域是共享的?哪些是私有的? Java栈.本地方法栈.程序计数器是随用户线程的启动和结束而建立和销毁的, 每个线程都有独立的这些区域.而方法区.堆是被整个JVM进程中的所有线程共享的. 2.方法区保存什么?会被回收吗? 方法区不是只保存的方法信息和代码,同时在一块叫做运行时常量池的子区域还 保存了Class文件中常量表中的各种符号引用,以及翻译出来的

  • 如何查看进程实际的内存占用情况详解

    top命令可以查看进程内存的使用,但是不够详细.还有一些命令可以进行更加详细的查看. [root@localhost ~]# cat /proc/5606/statusName:   switch4State:  S (sleeping)Tgid:   5606Pid:    5606PPid:   1TracerPid:      0Uid:    0       0       0       0Gid:    0       0       0       0Utrace: 0FDSize

  • python中使用psutil查看内存占用的情况

    有的时候需要对python程序内存占用进行监控,这个时候可以用到psutil库,Anaconda中是自带的,如果import出错,可以用pip install psutil(安装在python中)或conda install psutil(安装在Anaconda中) #常用的: import psutil import os info = psutil.virtual_memory() print u'内存使用:',psutil.Process(os.getpid()).memory_info(

  • Python利用memory_profiler查看内存占用情况

    目录 简介 安装 使用方法 1.通过装饰器运行 2.通过命令行运行 补充 简介 memory_profiler是第三方模块,用于监视进程的内存消耗以及python程序内存消耗的逐行分析.它是一个纯python模块,依赖于psutil模块. 安装 pip install memory_profiler 使用方法 1.通过装饰器运行 @profile def func1(): 2.通过命令行运行 python -m memory_profiler test_code.py 案例源码: # -*- c

  • SpringDataRedis入门和序列化方式解决内存占用问题小结

    目录 spring-data-redis简介 spring-data-redis的特性 基本介绍 实例Demo 自定义RedisTemplate序列化 自定义的RestTemplate的内存占用问题 StringRedisTemplate解决内存占用问题 总结 spring-data-redis简介 spring-data-redis是spring-data模块的一部分,专门用来支持在spring管理项目对redis的操作,使用java操作redis最常用的是使用jedis,但并不是只有jedi

随机推荐