AWS ECS Fargate 和多线程

AWS ECS Fargate and multi threading

上下文:我是 "serverless" 概念的新手。 我正在创建一个取放应用程序。基本上,应用程序将从 40 个队列 consume/pick 消息和 send/place 单个传出 FIFO 队列中的这些消息(以保持顺序)。该逻辑需要大约 10 workers/threads 到 运行 在不同队列上并行工作。

请不要建议 lambda。它不适合我的用例。

我计划在 AWS ECS + Fargate 中创建此应用程序。 我想知道当我将 fargate 用于将创建这 10 个线程的 java 应用程序时会不会有任何问题。

使用fargate(是serverless的概念)多线程有没有问题??

Fargate 将支持多线程,只要任务定义和容器定义具有添加线程的资源

使用 fargate,您只能为每个任务创建以下 vCPU 和内存 configurations

512 (0.5 GB), 1024 (1 GB), 2048 (2 GB) - Available cpu values: 256 (.25 vCPU)

1024 (1 GB), 2048 (2 GB), 3072 (3 GB), 4096 (4 GB) - Available cpu values: 512 (.5 vCPU)

2048 (2 GB), 3072 (3 GB), 4096 (4 GB), 5120 (5 GB), 6144 (6 GB), 7168 (7 GB), 8192 (8 GB) - Available cpu values: 1024 (1 vCPU)

Between 4096 (4 GB) and 16384 (16 GB) in increments of 1024 (1 GB) - Available cpu values: 2048 (2 vCPU)

Between 8192 (8 GB) and 30720 (30 GB) in increments of 1024 (1 GB) - Available cpu values: 4096 (4 vCPU)

如您所见,最大 vCPU 计数为 4

假设 1 vCPU 是物理 CPU 核心上的 1 个超线程(基于此 ),您可以轻松地 运行 应用程序的 4 个线程.

使用 10 个线程,即使在最强大的 Farget 设置上,也可能很困难(假设 log-运行ning,非常 cpu 密集线程)。

尽管如此,一旦您收到申请,这就可以相对容易地进行测试 运行ning。

AWS Fargate 是容器编排系统。

假设您已经将 java 应用程序容器化。您可以执行以下操作

  • 定义一个 Fargate 集群
  • 定义 Fargate 服务
  • 使用您的 java docker 容器定义一个 fargate 任务
  • 将您的服务配置为在集群中启动 3 个 fargate 任务

推理

由于您需要 10 个线程,每个任务(容器)最多可以有 4 hyperthreads,如 @marcin 所述。所以 3 个任务应该可以解决问题。

在物理机上,你有一定数量的

  • CPUs(示例:笔记本电脑上 1 CPU 或服务器上 4 CPUs),
  • 每个CPU有Y个核心(例如:6个核心),
  • 每个核心都可以执行超线程(通常每个核心 2 个线程)。将 CPU 核心线程想象成通向核心的传送带:当一个传送带为空时,核心可以处理另一条传送带上的东西来处理。在大多数架构(如 Intel)中,每个 CPU 内核都有两个线程(传送带)。当然,如果您的传送带已满载(如果您 运行 正在执行一项非常密集的任务),那么就会产生转换成本。我相信 Amazon 的新 CPU,Graviton,每个核心有 1 个线程(没有超线程)。因此,您需要具体查看每个服务器实例以了解每个核心有多少个线程。

现在,不要混淆 CPU 线程(例如:每个 CPU 核心 2 个线程)和应用程序线程!这是两个完全不同的东西!

然后您需要了解每个 OS 使用上述 CPU/core/threads 的方式不同。它创建进程、线程,并在这些 CPUs/cores/threads 上使用时间片。例如,在您的笔记本电脑上,您可能只有一个 CPU 具有 2 到 6 个内核(对于 Intel 处理器,取决于 i3、i5、i7),或者在最新的 Apple M1 上更多一点。实际上,在您的笔记本电脑上,您 运行 您的浏览器,您可能 运行 一个 IDE,您可能 运行 一个网络服务器,一个应用程序服务器,docker , Excel, 别的什么。这些是很多进程和应用程序线程。远远超过 CPUs/cores/threads。是操作系统(OS)拼接工作并将其放在传送带上。在 Linux 中,您可以让一些进程“很好地”屈服于其他进程,或者您可以让它们从处理器中“尽其所能”。有很多方法可以分割工作。因此,您还需要查看 OS。

另一个示例:当我在我的开发笔记本电脑上安装 Apache Tomcat 时,Tomcat 运行 在 JVM 上运行并启动可能包含数十个线程的线程池。然后我会在 Tomcat 服务器上安装一个应用程序,该服务器可能有一个包含 20 个线程的数据库连接池。如您所见,仅我的 Tomcat 服务器可能 运行 宁 30-40 Java 线程,而我的英特尔 i7 笔记本电脑只有 1 CPU,6 个内核,并支持超线程= 1x6x2 = 12 个线程。

在 AWS 中,一切都是虚拟化的,因此 1 vCPU 不会映射到 1 CPU!一个vCPU实际上映射到一个核心线程。这会让人感到困惑,因为 AWS 不会在所有服务器上使用相同的 CPU。您需要查看文档以了解哪个服务器 class 映射到哪个线程数等。例如,我相信在 Intel Xeon 处理器上,1vCPU=1 HyperThread(因此,其中一个两条传送带通向一个核心)。但是对于使用新的 Graviton CPU 的服务器(我认为每个 CPU 核心有一个线程),你得到一个核心。

最后,在 AWS Fargate 中,您指定 CPU 个单位。其中 1024 个单位 = 1 vCPU。这很难在心理上处理,但想想 OS 时间片是如何处理的,以及你的笔记本电脑目前如何 运行 处理很多(也许数百个)进程和线程,但只有 1 个 CPU和几个核心。以与 CPU 单位相同的方式来思考它:你得到 CPU 的一部分。或者将其想象成您可以访问通向核心的传送带之一:如果将 cpu 单位设置为 1024,则相当于“1 个核心”。请注意,实际上,它实际上比那更好,因为 AWS 正在打包那些传送带,所以我的示例有点“不稳定”(但我猜你明白了)。

现在,如果您将 docker container/task 设置为仅使用 256 或 512 cpu 单位(通向核心的传送带的四分之一或一半)?这很难说,因为这取决于你在做什么。如果您要解决的数学密集型问题会充分利用 cpu 线程,那么您可能无法 运行 应用程序线程太多。但是,如果您 运行 正在等待大量等待(等待来自数据库的响应、等待来自用户的请求等)的应用程序服务器,那么您可以增加线程数。

最后,您可能想要对您的应用程序进行负载测试。如果你放置太多线程,你的应用程序会花费大量时间,从一个线程切换到另一个线程(这样对所有线程都是公平的)并且你的应用程序会爬行。如果将其设置得太低,则会在 table 上留下容量。唯一确定的方法是测试它并找到最佳点。

你不应该犯的错误:

  • 认为1物理CPU=1vCPU(完全不是这样,更有可能=1cpu线程),
  • 认为 1 个核心 = 2 个线程(不总是,取决于 cpu 体系结构和其他因素,但可能是 1 个或 2 个线程,需要查看 AWS 文档以查找准确的信息值),
  • 认为 1 个应用程序线程 = 1 个 CPU 线程(这些是完全不同的东西),
  • 认为如果您有 1 个 CPU 线程,那么您只能 运行 单线程应用程序(完全不是这样)。

记住,1 vCPU(~ 1-2 cpu 线程)可以 运行 许多应用程序线程。只有您能弄清楚什么太低,什么太高,以及甜蜜点在哪里。我希望这有帮助。随时纠正这个 post if/where 我犯了错误 and/or 如果我犯了太大的逻辑捷径(我也为此苦苦挣扎所以我很高兴被纠正)。