【问题标题】:Using Consul for dynamic configuration management使用 Consul 进行动态配置管理
【发布时间】:2020-11-02 01:49:58
【问题描述】:

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

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

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

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

现在我对剩余步骤应该如何工作感到困惑。

  • 应用应如何将这些配置文件加载到内存中,然后同时切换所有文件?
  • 我是否需要将leadership election 与 consul 或其他任何东西一起使用才能实现这些目标?
  • 这方面的逻辑是什么,因为所有 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 的节点,它可以包含有关每台机器配置、下载时间、切换时间和其他详细信息的详细信息?

【问题讨论】:

    标签: configuration distributed-system consul system-design consul-kv


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2011-01-16
      • 2021-09-21
      • 1970-01-01
      • 2020-10-29
      • 1970-01-01
      • 2018-09-15
      • 2016-12-15
      • 2017-04-11
      • 2018-08-10
      相关资源
      最近更新 更多