AWS ECS Fargate 和多线程

10

背景:我刚接触"无服务器(serverless)"的概念。 我正在创建一个拾取和放置应用程序。 基本上,该应用程序将从40个队列中消耗/选择消息,并将这些消息发送/放置在单个传出FIFO队列中(以维护顺序)。 该逻辑需要大约10个工作线程/线程并行运行,处理不同的队列。

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

我计划使用AWS ECS + fargate创建此应用程序。 我想知道当我在Java应用程序中使用fargate创建这些10个线程时是否会有任何问题。

在使用fargate(它是一种无服务器概念)时,是否会存在多线程问题?

4个回答

46
在物理机上,你有一定数量的CPU(例如:笔记本电脑上的1个CPU或服务器上的4个CPU),每个CPU有 Y 个内核(例如:6个内核),每个内核都可以进行超线程(通常是每个内核2个线程)。把CPU内核线程想象成通向内核的传送带:当一个传送带为空时,内核可以处理来自另一个传送带的任务进行处理。在大多数结构中(如Intel),每个CPU内核有两个线程(传送带)。当然,如果你的传送带已经装满了(如果你正在运行非常密集的任务),那么就会有切换成本。我相信亚马逊的新CPU Graviton 每个内核只有1个线程(没有超线程)。因此,你需要具体查看每个服务器实例以了解每个内核有多少个线程。
现在不要混淆CPU线程(例如:每个CPU核心2个线程)和应用程序线程!它们是完全不同的东西!你需要了解每个操作系统如何使用CPU/核心/线程,并创建进程、线程并在这些CPU/核心/线程上使用时间片。例如,在你的笔记本电脑上,你可能只有一个CPU,具有2到6个核心(对于Intel处理器,取决于i3、i5、i7),或者最新的Apple M1可能更多一些。实际上,在你的笔记本电脑上运行浏览器、IDE、Web服务器、应用服务器、Docker、Excel等等。这些是大量的进程和应用程序线程,远远超过CPU/核心/线程的数量。操作系统(OS)将工作切分并将其放入传送带中。在Linux中,你可以通过调整进程“nice”来让出其他进程,也可以让它们从处理器中“尽其所能”。切分工作的方法有很多种,因此你还需要研究操作系统(OS)。
另一个例子是:当我在我的开发笔记本电脑上安装Apache Tomcat时,Tomcat在JVM上运行并启动线程池,其中可能包含数十个线程。然后我会在那个Tomcat服务器上安装一个应用程序,该应用程序可能有一个包含20个线程的数据库连接池。如你所见,仅我的Tomcat服务器可能正在运行30-40个Java线程,而我的Intel i7笔记本电脑只有1个CPU,6个核心,并支持HyperThreading= 1x6x2 = 12个线程。在AWS中,一切都是虚拟化的,所以1个vCPU并不等同于1个物理CPU!1个vCPU实际上对应着一个CPU核心线程。这会让人感到困惑,因为AWS并不在所有服务器上使用相同的CPU。您需要查看文档,以了解哪种服务器类别对应于哪个线程数等等。例如,在英特尔Xeon处理器上,我相信1个vCPU=1个超线程(因此,两个传送带中的一个通向一个核心)。但对于使用新Graviton CPU的服务器(我认为每个CPU核心只有一个线程),您将获得一个核心。 最后,在AWS Fargate中,您需要指定CPU单位。其中1024个单位=1个vCPU。这很难理解,但请考虑操作系统如何切片进程以及您的笔记本电脑当前运行着很多(也许是数百个)进程和线程,但只有1个CPU和几个核心。将CPU单位视为同样的方式:您获得CPU的一部分。或者将它看作如果您获得了通向核心的那些传送带之一的访问权限:如果将CPU单位设置为1024,则可以获得“1个核心”的等效物。请注意,实际上情况比这更好,因为AWS正在将这些传送带打包,所以我的示例有些“不准确”(但我想您可以理解这个概念)。

如果您将docker容器/任务仅设置为使用256或512个CPU单位(一个传送带的四分之一或一半),那么在Fargate上的ECS容器中可以运行多少线程?这很难说,因为它取决于您要做什么。如果您正在解决使用CPU线程最大化的数学密集型问题,则可能无法运行太多的应用程序线程。但是,如果您运行一个等待很长时间的应用程序服务器(等待来自数据库的响应,等待用户请求等),则可以增加线程数。

最终,您可能需要对应用程序进行负载测试。如果您设置了太多的线程,您的应用程序将花费大量时间从一个线程切换到另一个线程(以使所有线程公平),并且您的应用程序将变得缓慢。如果设置得太低,则会浪费容量。唯一确定的方法是进行测试并找到最佳点。

不应犯的错误:

  • 认为1个物理CPU=1个vCPU(完全不是这种情况,更可能是1个CPU线程)
  • 认为1个核心=2个线程(不总是如此,取决于CPU体系结构和其他因素,但很可能是1个或2个线程,需要在AWS文档中查找确切值)
  • 认为1个应用程序线程=1个CPU线程(这些是完全不同的东西)
  • 认为如果你只有1个CPU线程,就只能运行单线程应用程序(这完全不是事实)。

请记住,1个虚拟CPU(~ 1-2个CPU线程)可以运行许多应用程序线程。只有您才能确定哪个数量过低,哪个过高,并找到最佳的性能点。希望这会对您有所帮助。如果我在文章中犯了错误或者逻辑上存在问题,请随时纠正(我自己也曾遇到这样的困境,所以很乐意接受更正)。


3

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

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 设置下(假设运行长时间、需要大量 CPU 的线程),也可能会很困难。

尽管如此,一旦您运行应用程序,这是相对容易测试的内容。


感谢您的快速回复。如果不使用Fargate,AWS中是否有其他方法可以实现此功能?还是必须老派地直接使用EC2实例? - learning_to_write_good_code
@learning_to_write_good_code 您可以在实例上运行ECS任务。您可以选择适合您需要的任何实例。但我仍然建议进行快速检查。根据您的线程性质(长时间运行,非常CPU密集型?),单个fargate任务可能不适合10个线程。对于短时间的线程,不应该有问题。或者每个任务运行3-4个线程,并同时运行几个任务?有几种选择。 - Marcin
1
IO密集型任务怎么办? - xpmatteo
1
@xpmatteo Fargate 任务的最大 vCPU 现在是 16 个 vCPU(16384),这样更容易运行 IO 密集型任务。 - undefined

0

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


-1

AWS Fargate 是一个容器编排系统。

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

  • 定义 Fargate 集群
  • 定义 Fargate 服务
  • 使用您的 Java Docker 容器定义 Fargate 任务
  • 配置您的服务在集群中启动 3 个 Fargate 任务

原因

由于您需要 10 个线程,每个任务(容器)最多可以有 4 个超线程,如 @marcin 所述。因此,3 个任务应该就足够了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接