1

我正在设计一个小项目,我需要使用Consul以动态方式管理应用程序配置,以便我的所有应用程序机器可以同时获取配置,而不会出现任何不一致问题。我们Consul已经将其用于服务发现目的,所以我正在阅读更多关于它的信息,看起来他们有一个Key/Value商店,我可以用它来管理我的配置。

我们所有的配置都是 json 文件,因此我们制作了一个包含所有 json 配置文件的 zip 文件,并将参考存储在其中,您可以从该位置下载此 zip 文件到Consul Key/Value存储中的特定密钥中。我们所有的应用程序机器都需要从该引用(在 Consul 中的密钥中提到)下载此 zip 文件并将其存储在每个应用程序机器的磁盘上。现在我需要所有应用程序机器同时切换到这个新配置,以避免任何不一致问题。

假设我有 10 台应用程序机器,所有这 10 台机器都需要下载包含我所有配置的 zip 文件,然后原子地同时切换到新配置以避免任何不一致(因为它们正在占用流量)。以下是我提出的步骤,但我对如何在内存中加载新文件以及切换到新配置的工作方式感到困惑:

  1. 到目前为止,所有 10 台机器都已启动并使用默认配置文件运行,这些文件也在磁盘上。
  2. 一些外部进程将使用最新的 zip 文件参考更新我的领事键/值存储中的键。
  3. 所有 10 台机器都有手表,key因此一旦有人更新value,key手表就会被触发,然后所有这 10 台机器都会将 zip 文件下载到磁盘上并解压缩以获取所有配置文件。
  4. (..)
  5. (..)
  6. (..)

现在这是我对剩余步骤应该如何工作感到困惑的地方。

  • 应用程序应该如何将这些配置文件加载到内存中,然后同时切换?
  • 我是否需要使用leadership election领事或其他任何东西来实现这些事情?
  • 由于所有 10 个应用程序都已经在内存中使用默认配置(也存储在磁盘上)运行,这将是什么逻辑。我们是否需要两个单独的目录,一个是默认目录,另一个是新配置,然后使用这两个目录?

假设这是否是我在Consul随机设计中拥有的节点(这里可能是错误的) -

{"path":"path-to-new-config", "machines":"ip1:ip2:ip3:ip4:ip5:ip6:ip7:ip8:ip9:ip10", ...}

哪里path会有新的 zip 文件参考,并且machines可能是这里的一个密钥,我可以在其中列出所有机器,所以现在我可以在每台机器成功下载文件后立即将每台机器的 IP 地址放入该密钥中?一旦machines密钥列表的大小为 10,那么我可以说我们准备好切换了吗?如果是,那么我如何以原子方式更新该节点中的机器密钥?也许这个逻辑在这里是错误的,但我只是想扔掉一些东西。并且还需要在切换后清理所有这些机器列表,因为对于下一次配置更新我需要做类似的练习。

有人可以概述有关如何有效地动态管理所有应用程序机器上的配置并同时避免不一致问题的逻辑吗?也许我还需要一个节点,因为status它可以包含有关每台机器配置、下载时间、切换时间和其他详细信息的详细信息?

4

1 回答 1

3

根据您的情况,我可以想到几种可能的解决方案。

最简单的解决方案是根本不将配置存储在内存和文件中,直接将配置存储在 consul kv 存储中。而且我不是在谈论映射到整个 json 的单个键(我假设你的 json 很大,否则你不会压缩它),而是从 json 中提取更小的键/值集(这样你就赢了每次向领事查询时都不需要拉整个东西)。如果您直接从 consul 获取配置,则您的一致性保证匹配 consul 一致性保证。我猜如果您丢失了内存配置,您会担心性能,这是您需要衡量的。但是,如果您可以容忍性能损失,这将为您节省很多痛苦。

如果这里的性能是一个问题,那么可能会使用fsconsul。有了这个,您仍然可以将您的 json 提取到 consul 中的多个键/值集中,然后 fsconsul 会将其映射到您的应用程序的文件。

如果这不在讨论范围内,那么问题是您愿意容忍多少不一致。如果您可以忍受几秒钟的不一致,那么最好的选择可能是在您的内存配置中放置一个TTL(生存时间) 。您仍然可以在 consul 上使用手表,但您可以将其与每隔几秒清除一次内存缓存相结合,以防手表因某种原因出现故障(或停止)。这应该会给您带来最坏的几秒钟不一致的情况(取决于您为 TTL 设置的值),但正常情况下(我认为)应该很快。

如果这是不可接受的(下载 zip 是否需要很多时间,也许?),您可以按照您提到的路线进行。要以原子方式更新值,您可以使用它们的cas(检查和设置)操作。如果在您发送请求和领事试图应用它的时间之间发生了更新,它将给您一个错误。然后您需要拉出机器列表,再次应用您的更改并重试(直到成功)。

我不明白你为什么需要 2 个目录,但也许我误解了这个问题:当你的应用程序启动时,在你做任何其他事情之前,你检查是否有一个新的配置,如果有你下载它并将其加载到记忆。所以如果你想保持一致,你不应该有一个“默认配置”。在启动时下载配置后,你就醒了。当您的手表发出关键更改信号时,您可以下载配置以直接覆盖您的旧配置。这是假设您在单个线程上运行监视触发代码,因此您不会并行下载文件多次。如果下载失败,您不会将损坏的文件加载到内存中。如果你在下载过程中崩溃了,那么你会在启动时再次下载,所以应该没问题。

于 2020-07-23T05:19:56.307 回答