0

我有 2 个服务结构应用程序 (sln) 和 3 个服务(3 个代码包)。我想将它们分配在最大 CPU 百分比的 40% 20% 20% 中,而与内核无关,即对 CPU 内核的数量没有限制(当前机器是 4 核逻辑)。根据上面的内容/博客,如果我指定 CpuShares = 512 、 CpuShares = 256 和 CpuShares = 256 ,那么它应该占用 40%、20%、20% 的最大 CPU。但是,情况并非如此,它只允许相应服务的最大 CPU 使用率分别为 5%、2% 和 2%。通过阅读这篇文章(https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-resource-governance)我认为 1024 是 CpuShares 的默认值(最大值),经过大量尝试和错误后,如果我们应用任何大于此值的值,我最终得出 CpuShares 的值 10,000,我们会在服务资源管理器中出现错误,提示 CpuShare 的 Arg 无效。所以考虑到 10,000 = 100% CPU 使用率是允许的。我已将以上 CPU 份额值修改为 CpuShares = 4000、CpuShares = 2000 和 CpuShares = 2000 在测试中我可以看到最大 CPU 百分比使用率,其中 40% 20% 20% (不精确的 5% 方差)。所以问题是我在任何文档中都找不到 10,000 = 100% CPU 使用率值。因此,我想确认这是否正确,如果不正确,那么如何将服务或代码包限制为特定百分比。请对此提供帮助

4

1 回答 1

1

关于 SF 中服务的资源治理的一个常见误解是,它是为您的服务保留和隔离的资源容量,就像它在 docker 容器上一样,这是不正确的。

这些指标只是保持集群中服务平衡的软限制,并不意味着它们专门为您的服务保留,如果没有设置限制,其他服务可以并且将消耗这些资源。

要使资源限制强制起作用,服务包中的所有代码包都应指定内存限制。

指标是在集群中找到适当的服务平衡并将服务放置在具有可用资源的节点中的措施,因此假设您有服务 A、B 和 C,并且每个服务都有特定数量的资源需求,比如说内存,那是一个容易理解的值,A=1000MB,B=512MB,C=512MB,a节点有2GB内存,这些可以放在同一个节点,假设服务C需要1000MB,当服务C需要被激活,它会避开激活 A 和 B 的同一个节点,因为它没有能力在那里运行,即使这些服务没有消耗所有请求的资源,并且会选举另一个节点。

文档

Service Fabric 运行时当前不提供资源预留。打开进程或容器时,运行时会将资源限制设置为在创建时定义的负载。此外,运行时拒绝打开超出资源时可用的新服务包。

关于您关于股票的主要问题:

相同的文档描述了共享是保留给服务包的保留 CPU 核心的一部分,在该节点上激活的所有代码包之间拆分,如果您为每个代码包定义共享,则它们的总和将是总数,并且每个人都将获得这些股份的一部分。

这些股份是如何控制的?

请记住,以下内容在任何地方都没有正式记录,我可能在某些方面是错误的,我从源代码中获得了这些信息,我可能错过了一些细节

假设激活了包含代码包 A 和 B 的服务包,具有以下共享拆分:

  • 代码包 A (CP.A) = 1500 股
  • 代码包 B (CP.B) = 500 股

顺丰将:

  • 确定为服务包预留的 CPU 内核容量:
    • 容量将是 CPU 核心保留容量 (%) / 可用总量
    • 在 4 核 cpu 上:1 个 cpu 核心保留 = 25%
  • 从代码包中获取所有份额并将它们的值相加,以确定有多少份额应代表 100% 的保留 (25%) 容量
    • 1500 + 500 = 2000 总股数
    • CP.A 应该收到 4 的 3 个分数
    • CP.B 应该收到 4 的一小部分
  • 将份额分数转换为 CPU 作业周期(请参阅下面的原因)
    • CP.A 应该接受 3/4 of 10,000 -> 7500 个周期
    • CP.B 应该接收 10,000 -> 2500 个周期的 1/4
  • 将保留的周期数乘以保留的 cpu 核心数量
    • CP.A 应获得 7500 个周期的 25%
    • CP.B 应该收到 2500 个周期的 25%

这些限制受Job Objects的约束,当一个进程(代码包)被激活时,它被分配给一个设置了这些限制的 Job,每当进程消耗的周期超过作业中设置的限制时,线程就会被抢占另一个进程线程被安排在核心中。在代码中,他们建议10000 represents all available cores但正确的是number of processor cycles that the threads in a job object can use during each scheduling interval. 在一个 Job 中,10000 个周期是每个 Job 调度的间隔,一个线程在这个 Job 中调度,会消耗这个调度的 x 个周期,如果你预留 4 个核心,你只会消耗 10000 个周期。

确切的逻辑在这段代码中:

    double shares = fractionOfSp * Constants::JobObjectCpuCyclesNumber;
    shares = shares * (numCoresAllocated / max(numAvailableCores_, systemCpuCores_));
    rg.CpuShares = static_cast<uint>(shares);

    //fractionOfSp -> Fraction of a Service Package
    //   - A service package represents 100% (Like a Pizza) of reserved core capacity
    //   - Each Code Package will have one or more fraction (A slice of the pizza)
    //Constants::JobObjectCpuCyclesNumber -> is a constant for 10000 cycles
    //numCoresAllocated -> How many cores you assigned to a service package

一些技巧:

  • 保留核心的数量也会影响结果,您必须保留至少 0.01% 的核心才能生效。
  • 份额基于为服务包保留的 CPU 内核,而不是节点中所有可用的 CPU,如果您的节点有 4 个内核,则为服务包保留 1 个,这意味着您在每个代码包之间共享 25% 的节点容量。
  • 如果某些代码包的份额为零或没有份额,则所有代码包都将具有相同的分数,即使您指定了任何值。
  • 在 linux 上,它使用 CpuQuota
  • 一个作业的最大循环数为 10k

如果您需要更多信息,请在此处查看源代码

PS:计算这些数字我有点头晕,我可能稍后再复习!

于 2018-09-20T10:47:57.240 回答