TLDR - 估计集群的预期容量既是艺术又是科学。您可能会获得一个很好的下限,您可以将其推得更高,但在大多数情况下,在您的工作负载条件下部署、运行它们并收集数据是回答这个问题的最佳方式。
1) 通常,给定机器上的集合受可用内存量或节点上可用磁盘空间量的限制,以较低者为准。今天,我们将集合中的所有数据保存在内存中,并将其保存到磁盘。因此,集群中的集合可以容纳的最大数量通常是(集群中的可用内存量)/(目标副本集大小)。
请注意,“可用内存”是机器上运行的其他代码(包括操作系统)留下的任何内容。在上面的示例中,尽管您没有在所有节点上运行 - 您只能获得其中的 3 个。因此,(不切实际地)假设这些其他因素的开销为 0,您可以期望能够在运行它的节点上的内存不足之前将大约 3.5 GB 的数据放入该有状态服务副本中。集群中仍有 2 个节点为空。
让我们再举一个例子。假设它与上面的示例大致相同,除了在这种情况下您将有状态服务设置为分区。假设您选择的分区计数为 5。所以现在在每个节点上,您都有一个主副本和来自其他分区的 2 个辅助副本。在这种情况下,每个分区最多只能保存大约 1.16 GB 的状态,但现在总体上可以将 5.83 GB 的状态打包到集群中(因为现在可以充分利用所有节点)。顺便说一句,只是为了证明数学有效,即(每个节点 3.5 GB 内存 * 集群中的 5 个节点)[17.5] /(目标副本集大小为 3)= 5.83。
在所有这些示例中,我们还假设所有分区和所有副本的内存消耗相同。很多时候事实证明并非如此(至少暂时如此) - 某些分区最终可能会有更多或更少的工作要做,因此资源消耗不均衡。我们还假设次要始终与主要相同。在状态量的情况下,可以公平地假设这些将相当均匀地跟踪,尽管对于其他资源消耗可能不会(请记住一些事情)。在消耗不均的情况下,这确实是 Service Fabric 的群集资源管理的其余部分将提供帮助的地方,因为我们可以了解不同副本的消耗并将它们有效地打包到群集中以利用可用空间。与集合中的状态相关的资源消耗的自动报告在我们的雷达上,也是我们想做的事情,所以在未来,这将是自动的,但今天你必须自己报告这个消耗。
2) 默认情况下,我们会根据默认指标来平衡服务(更多关于指标的信息是here)。因此,默认情况下,这两个不同服务的不同副本可能最终会出现在机器上,但在您的示例中,您最终会得到 4 个节点,其中一个服务的 1 个副本,然后是 1 个节点,两个节点的两个副本不同的服务。这意味着每个服务(根据您的示例,每个服务都有 1 个分区)只能在每个服务中消耗 1.75 GB 的内存,在集群中总共消耗 3.5 GB。这再次小于集群的总可用内存,因为您没有使用某些节点部分。
请注意,这是最大可能的消耗,并假设在服务本身之外没有消耗。不建议将此作为您的最大值。您希望减少它有几个原因,但最实际的原因是确保在存在升级和故障时集群中有足够的可用容量。例如,假设您有 5 个升级域和 5 个故障域。现在假设当您在升级域中进行升级时,故障域的节点价值发生故障。这意味着(略少于)40% 的集群容量可能随时消失,并且您可能希望在剩余节点上留下足够的空间以继续。这意味着,如果您的集群以前可以保存 5.83 GB 的状态(根据我们之前的计算),实际上您可能不想在其中放置超过 3.5 GB 的状态,因为服务可能无法容纳更多的状态恢复到 100% 的健康状态(另请注意,我们不会立即构建替换副本,因此在您遇到这种情况之前,节点必须为您的 ReplicaRestartWaitDuration 关闭)。 this article 涵盖了有关指标、容量、缓冲容量(可用于确保节点上为故障情况留出空间)以及故障和升级域的更多信息。
实际上还有其他一些因素会限制您可以存储的状态数量。您需要做几件事:
- 估计数据的大小。您可以通过计算对象包含的每个字段的大小来合理估计数据的大小。请务必考虑 64 位引用。这将为您提供一个较低的起点。
- 存储开销。您存储在集合中的每个对象都会带来一些存储该对象的开销。在依赖于集合和当前运行中的操作(复制、枚举、更新等)的可靠集合中,此开销可以在集合中存储的每个项目(行)100 到大约 700 个字节之间。也知道我们一直在寻找减少我们引入的开销的方法。
我们还强烈建议您在一段时间内运行您的服务并通过性能计数器测量实际资源消耗。模拟某种真实的工作负载,然后测量您关心的指标的实际使用情况,将为您提供很好的服务。我们特别推荐这样做的原因是,您将能够从诸如您的对象最终放置在哪个 CLR 对象堆中、GC 运行的频率、是否存在泄漏或其他类似的事情中看到消耗量您实际可以使用的内存。
我知道这是一个很长的答案,但我希望它对您有所帮助且完整。