Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么docker java应用程序会因为内存而被杀死?_Java_Amazon Web Services_Docker_Memory_Amazon Ecs - Fatal编程技术网

为什么docker java应用程序会因为内存而被杀死?

为什么docker java应用程序会因为内存而被杀死?,java,amazon-web-services,docker,memory,amazon-ecs,Java,Amazon Web Services,Docker,Memory,Amazon Ecs,问题:由于内存使用,应用程序被终止 Status reason OutOfMemoryError: Container killed due to memory usage Exit Code 137 环境:AWS ECS实例上docker容器中的Spring Boot应用程序,配置: AWS硬盘内存限制/总RAM-384 MB -Xmx134m -Xms134m -XX:MaxMetaspaceSize=110m 根据java max内存公式(我在几周的研究中发现了这个公式,并且

问题:由于内存使用,应用程序被终止

  Status reason OutOfMemoryError: Container killed due to memory usage
  Exit Code 137
环境:AWS ECS实例上docker容器中的Spring Boot应用程序,配置:

  • AWS硬盘内存限制/总RAM-384 MB
  • -Xmx134m
  • -Xms134m
  • -XX:MaxMetaspaceSize=110m
根据java max内存公式(我在几周的研究中发现了这个公式,并且有了一些改进):

最大内存=xmx+非堆内存+线程数*xss

非堆内存=元空间+(压缩的类空间+代码堆方法+代码堆方法+非方法+代码堆方法)

考虑到非堆内存的第二部分总共占用了近40mb的内存

所以在我的例子中
max_memory=134(xmx)+110(元空间)+40(非堆-非元空间)+9(线程)*1(默认Xss)=293

但是,在加载heapUsedMemory=~105-120mb和非heapUsedMemory(metaspace+JVM stuff)=~140mb的情况下,这意味着必须有384-120-140=124MB的可用内存。 所以问题是有大量的可用内存,所有java工具都在展示(jstat-gc、grafana上的Spring、不同的JavaAPI等等)。 以下是我在研究过程中开发和使用的API的代码片段:

    @GetMapping("/memory/info")
public Map<String, String> getMmUsage() {
    Map<String, Long> info = new HashMap<>();
    List<MemoryPoolMXBean> memPool = ManagementFactory.getMemoryPoolMXBeans();
    for (MemoryPoolMXBean p : memPool) {
        if ("Metaspace".equals(p.getName())) {
            info.put("metaspaceMax", p.getUsage().getMax());
            info.put("metaspaceCommitted", p.getUsage().getCommitted());
            info.put("metaspaceUsed", p.getUsage().getUsed());
        }
    }

    info.put("heapMax", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax());
    info.put("heapCommitted", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getCommitted());
    info.put("heapUsed", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed());
    info.put("non-heapMax", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax());
    info.put("non-heapCommitted", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getCommitted());
    info.put("non-heapUsed", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed());

    Map<String, String> memoryData = info.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> {
        long kb = e.getValue() / 1024;
        return (kb / 1024) + " Mb (" + kb + " Kb)";
    }, (v1, v2) -> v1, TreeMap::new));

    Set<Thread> threads = Thread.getAllStackTraces().keySet();
    memoryData.put("threadsCount", Integer.toString(threads.size()));
    memoryData.put("threadsCountRunning",
            Long.toString(threads.stream().filter(t -> t.getState() == Thread.State.RUNNABLE).count()));

    return memoryData;
}
@GetMapping(“/memory/info”)
公共映射getMmUsage(){
Map info=newhashmap();
List memPool=ManagementFactory.getMemoryPoolMXBeans();
for(MemoryPoolMXBean p:memPool){
if(“Metaspace”.equals(p.getName())){
info.put(“metaspaceMax”,p.getUsage().getMax());
info.put(“metaspaceCommitted”,p.getUsage().getCommitted());
info.put(“metaspaceUsed”,p.getUsage().getUsed());
}
}
info.put(“heapMax”,ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax());
info.put(“heapCommitted”,ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getCommitted());
info.put(“heapUsed”,ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed());
info.put(“non-heapMax”,ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax());
info.put(“non-heapCommitted”,ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getCommitted());
info.put(“非heapUsed”,ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed());
Map memoryData=info.entrySet().stream().collect(Collectors.toMap)(条目::getKey,e->{
长kb=e.getValue()/1024;
返回值(kb/1024)+“Mb”(+kb+“kb”);
},(v1,v2)->v1,TreeMap::new);
Set threads=Thread.getAllStackTraces().keySet();
memoryData.put(“threadscont”,Integer.toString(threads.size());
memoryData.put(“threadscontrunning”,
Long.toString(threads.stream().filter(t->t.getState()==Thread.State.RUNNABLE.count());
返回内存数据;
}
因此,我的应用程序应该是稳定的,因为它有很多内存要处理。但事实并非如此。如上所述,由于内存使用,容器被杀死

正如我上面所描述的,java工具显示有大量内存,并且内存(堆)正在被释放。另一方面,AWS cloudwatch度量内存利用率显示内存不断增长(非常小的部分):

有趣的探索:在无休止的测试中,我发现了下一个问题:当我设置xmx=134MB时,应用程序的寿命更长,能够经受5轮性能测试,当我设置xmx/xms=200mb时,它经受住了1轮性能测试。这怎么可能呢

我的观点:似乎有东西在使用内存,但没有正确释放内存


我很想听听您的意见,为什么我的应用程序在有50+mb的可用内存时会不断消亡,为什么AWS指标显示出与java工具不同的结果

java应用程序也可以分配本机内存,而本机内存不是任何堆、堆栈空间的一部分,例如
ByteBuffer.allocateDirect
或从Java使用的本机库、Java本身的内存等@markrottevel我知道这一点。但我们处理的不是缓冲区,也不是文件。对于任何本机库来说,100MB似乎也足够处理etc@NyamiouTheGaleanthropeGC配置是默认的(规范:openjdk 8,debian OS)您是否能够理解我遇到的这个问题nodejs@Liran不完全是,我们发现,自从最新的Java8发行版或Java9+以来,docker中就有了自动处理内存的标志,从那时起,它变得更好了