我正在设计一个小项目,在这个项目中我需要使用领事动态地管理应用程序配置,这样我的所有应用程序机器都可以同时获得配置,而不会出现任何不一致的问题。我们已经将Consul用于服务发现目的,因此我阅读了更多关于它的文章,看起来它们有一个Key/Value存储,我可以使用它来管理配置。
我们的所有配置都是json文件,因此我们使用json文件创建一个zip文件,并将引用存储在Consul Key/Value存储中的一个特定密钥中。我们所有的应用程序机器都需要从引用中下载这个压缩文件(在领事中的一个键中提到),并将它存储在每台应用程序机器上的磁盘上。现在,我需要所有的应用程序机器切换到这个新的配置,大约在同一时间,以避免任何不一致的问题。
假设我有10台应用程序机器,所有这10台机器都需要下载zip文件,其中有我所有的信任,然后原子地切换到新的信任,以避免任何不一致(因为他们正在占用流量)。下面是我想出的步骤,但我对如何在内存中加载新文件以及切换到新的信任将如何工作感到困惑:
key上的手表,因此一旦有人更新了key的value,就会触发手表,然后所有10台机器都会将zip文件下载到磁盘上,并将其解压缩以获取所有配置文件。现在,我对剩下的步骤应该如何工作感到困惑。
leadership election与领事或其他任何东西来实现这些事情?假设这是我在Consul中的节点,只是一个随机设计(这里可能是错的)-
{"path":"path-to-new-config", "machines":"ip1:ip2:ip3:ip4:ip5:ip6:ip7:ip8:ip9:ip10", ...}在哪里,path将有新的zip文件引用,而machines可能是这里的一个密钥,在这里,我可以有所有机器的列表,所以现在,只要他们成功地下载了文件,我就可以把每台机器的ip地址放在那个键中了?一旦machines密钥列表的大小为10,那么我可以说我们准备好切换了吗?如果是,那么我如何原子地更新该节点中的机器密钥?也许这个逻辑是错误的,但我只是想抛出一些东西。还需要清理所有这些机器列表,然后切换,因为对于下一个配置更新,我需要做类似的练习。
有人能概述一下我如何能够动态地管理所有应用程序机器上的配置,同时避免不一致的问题吗?也许我还需要一个节点作为status,它可以提供关于每台机器配置的详细信息,何时下载,何时切换以及其他细节?
发布于 2020-07-23 05:19:56
根据您的场景,我可以想出几种可能的解决方案。
最简单的解决方案是根本不将配置存储在内存和文件中,只需将配置直接存储在consul存储中即可。我说的不是一个映射到整个json的键(我假设您的json很大,否则您就不会压缩它),而是从json中提取更小的键/值集(这样您就不必每次向领事查询时都要提取整件东西)。如果您直接从领事获得配置,您的一致性保证了匹配领事一致性保证。我猜你担心的是如果你失去内存配置的性能,这是你需要衡量的东西。不过,如果你能忍受性能损失,这会给你带来很大的痛苦。
如果这里的性能是一个问题,那么对此的一个变化可能是使用执政官。这样,您仍然可以将json提取到领事中的多个键/值集中,然后fsconsul会将其映射到应用程序的文件中。
如果这不是问题,那么问题是你愿意容忍多少不一致之处。如果您可以忍受几秒钟的不一致,您最好的选择可能是在内存配置中放置一个现场直播( TTL )。你仍然会拥有执政官的手表,但是你把它和每隔几秒钟驱逐你的内存缓存结合起来,作为一个后盾,以防手表因为某种原因而失败(或停滞)。这应该会给你一个最坏的情况--几秒钟的不一致(取决于你为你的TTL设置的值),但是正常情况(我认为)应该是快速的。
如果这是不可接受的(下载压缩可能需要很长时间吗?),您可以沿着您提到的路线走。要自动更新值,可以使用它们的cas (检查和设置)操作。如果在发送请求的时间和领事试图应用请求的时间之间发生了更新,它将给您一个错误。然后,您需要拉出机器列表,并再次应用您的更改并重试(直到它成功)。
我不明白为什么你需要2个目录,但也许我误解了这个问题:当你的应用程序启动时,在你做任何其他事情之前,你检查是否有一个新的配置,如果有你下载它并将它加载到内存中。因此,如果您想保持一致性,就不应该有“默认配置”。在启动时下载配置之后,您就可以正常工作了。当手表发出更改键的信号时,您可以下载配置以直接覆盖旧配置。这是假设您在单个线程上运行手表触发的代码,所以不会并行多次下载该文件。如果下载失败,就不会将损坏的文件加载到内存中。如果您在下载过程中崩溃,那么您将在启动时再次下载,所以应该是好的。
https://stackoverflow.com/questions/62866155
复制相似问题