java - 即使ECS AWS上有许多可用内核,Runtime.getRuntime()。availableProcessors()仍返回1

标签 java docker amazon-ecs

我正在AWS的ECS上通过Docker运行任务。该任务执行一些受CPU限制的计算,我想并行运行这些计算。我使用Runtime.getRuntime().availableProcessors()中指定的线程数启动线程池,该线程池在我的PC上本地运行良好。出于某种原因,在AWS ECS上,即使有多个可用核心,该值始终返回1。因此,我的计算是按顺序进行的,并且没有利用多个核。

例如,现在,我有一个任务在“t3.medium”实例上运行,根据docs,该实例应具有2个内核。

当我执行以下代码时:

System.out.println("Java reports " + 
    Runtime.getRuntime().availableProcessors() + " cores");

然后在日志中显示以下内容:
Java reports 1 cores

我未在ECS的任务定义中指定cpu参数。我在ECS管理控制台中的任务列表中看到它的“CPU”列显示为0。我还注意到,在实例(= VM)列表中,它将“CPU可用”列为2048,这大概与VM具有2个核心这一事实有关。

我希望我的Java程序能够看到VM必须提供的所有内核。 (当Java程序在没有Docker的计算机上运行时,通常会发生这种情况)。

我该怎么做呢?

最佳答案

感谢@stdunbar在评论中为我指明了正确的方向。

编辑:感谢@Imran在评论中。如果您启动大量线程,则绝对会将它们调度到多个内核。这个答案只是关于让Runtime.getRuntime().availableProcessors()返回正确的值。许多“线程池”启动与该方法返回的线程一样多的线程:它应返回可用核的数量。

似乎有两个主要解决方案,但都不是理想的:

  • 在任务定义中设置cpu参数。例如,如果您有2个核心,并且要同时使用它们,则必须在任务的定义中设置"cpu":2048。这不是很方便,原因有两个:
  • 如果选择更大的实例,则必须确保更新此参数。
  • 如果您希望同时运行两个任务,而这两个任务都可以偶尔使用所有内核进行短期 Activity ,则AWS不会在带有"cpu":2048的2核系统上调度两个任务。从CPU的角度来看,VM表示“已满”。这违背了分时执行(Unix等)原则的每个任务都按需完成的任务(例如,想象一下在台式机上,如果您在双核计算机上运行Word和Excel,而Windows不允许您启动其他任何任务,因为Word可能需要一个核心,而Excel可能也需要,所以如果另一个程序可能同时需要所有核心,则将没有足够的核心。)
  • here所述,在JDK 10及更高版本中使用-XX:ActiveProcessorCount=xx JVM选项。这不方便,因为:
  • 如上所述,如果您更改实例类型,则必须更改该值。

  • 我在这里写了一篇更长的博客文章,描述了我的发现:https://www.databasesandlife.com/java-docker-aws-ecs-multicore/

    关于java - 即使ECS AWS上有许多可用内核,Runtime.getRuntime()。availableProcessors()仍返回1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55596774/

    相关文章:

    Java 简单单线程 IllegalMonitorStateException

    java日期格式化程序不会将正常小时格式更改为24小时格式

    java - JLayeredPane 格式问题

    docker - Docker内部的Docker中的卷?

    linux - 如何离线安装docker-compose?

    r - 使用 docker 多阶段构建进行 R 开发和部署设置

    amazon-web-services - 如何获取Cloudwatch中所有ECS实例的日志?

    java - 我是否必须防御性地保护 hql 查询中的空值?

    amazon-web-services - 运行时找不到 Codebuild aws 命令?

    amazon-web-services - 为什么任务定义没有被删除?