【问题标题】:AWS ECS Fargate and multi threadingAWS ECS Fargate 和多线程
【发布时间】:2020-09-05 08:34:46
【问题描述】:

上下文:我是“无服务器”概念的新手。 我正在创建一个拾取和放置应用程序。基本上,应用程序将从 40 个队列中消费/挑选消息,并将这些消息发送/放置在单个传出 FIFO 队列中(以维护序列)。该逻辑需要大约 10 个工作线程/线程在不同队列上并行运行。

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

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

使用fargate(这是一个无服务器概念)时多线程有什么问题吗?

【问题讨论】:

    标签: multithreading amazon-web-services amazon-ecs aws-serverless aws-fargate


    【解决方案1】:

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

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

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

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

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

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

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

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

    最后,您可能希望对您的应用程序进行负载测试。如果你放置了太多线程,你的应用程序会花费大量时间,从一个线程切换到另一个线程(这样对所有线程都是公平的),你的应用程序就会爬取。如果你把它设置得太低,你就会把容量留在桌子上。唯一确定的方法是测试它并找到最佳位置。

    你不应该犯的错误:

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

    请记住,1 个 vCPU(约 1-2 个 cpu 线程)可以运行许多应用程序线程。只有你才能弄清楚什么太低,什么太高,以及甜蜜点在哪里。我希望这有帮助。如果/我犯了错误和/或如果我犯了太大的逻辑捷径,请随时更正这篇文章(我也为此苦苦挣扎,所以很高兴得到纠正)。

    【讨论】:

      【解决方案2】:

      使用 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 个超线程(基于此 answer),您可以轻松地运行应用程序的 4 个线程。

      使用 10 个线程,即使在最强大的 Farget 设置上,也可能很困难(假设日志运行、CPU 密集型线程)。

      尽管如此,一旦您的应用程序运行起来,就可以相对容易地进行测试。

      【讨论】:

      • 感谢您的快速回复。如果不是 Fargate,AWS 有没有办法实现这一点?还是我必须去老学校直接使用 EC2 实例?
      • @learning_to_write_good_code 您可以在实例上运行 ECS 任务。您可以选择适合您需要的任何实例。但我仍然建议您快速检查一下。根据线程的性质(长时间运行,CPU 密集型?),单个 fargate 任务可能不适合其中的 10 个。对于短的应该没有问题。或者每个任务可以运行 3-4 个线程并且同时运行的任务很少?可供选择的可能性很少。
      • IO密集型任务呢?
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        AWS Fargate 是容器编排系统。

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

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

        推理

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-06-15
          • 2020-03-15
          • 1970-01-01
          • 2019-09-10
          • 2020-03-21
          • 2022-11-10
          • 2021-01-24
          • 2019-09-25
          相关资源
          最近更新 更多