微服务。 统一及其为何如此重要。 第1部分-配置



引言


祝大家有美好的一天。 我是一家公司的Python开发人员,该公司处理用于自动化业务流程的复杂解决方案,为解决单个任务,分析和咨询而开发。 我的职责包括开发和维护微服务架构。 今天,我想说一说我们如何在微服务上苦苦挣扎,为什么统一对它们如此重要。

毫无疑问,这种产品开发方法正在日益占领市场。 而且,我们对它们的投入越多,就越需要避免忘记与它们合作的基本规则。 为了构建我们在编写微服务产品方面的经验,决定撰写一系列文章,介绍如何将开发的某些方面推广到所有服务。

这样的规则之一就是统一。 在我们公司中,大多数产品都包含多种杂色语言和技术。 在所有这些展位中,您必须考虑如何将基本原理推广到所有微服务,以便于它们的轻松支持,配置和便捷开发。 这些文章的系列将对此进行讨论。

我问每个对猫有兴趣的人。

问题


也许在开发服务时遇到的第一件事就是它的配置方法。 在微服务架构中,这个问题变得更加严重。

想象一下,您有两个服务,而每个服务都需要更改一个参数。 例如,禁用CORS。 由于系统是多组件且基于微服务构建,因此为了方便管理,最好使用统一的方法来配置所有模块。 因此,在设置每个模块时,您需要使用相同的方法。

您可以说每个服务的开发人员都应该这样做,但是如果您的所有配置都存储在同一Kubernetes中,又不能在哪里给所有开发人员呢? 糟糕的DevOps将被迫花费大量时间来学习服务及其配置方法。 并且,随着服务的更新,将重复执行此过程,尤其是当某人想尝试服务设置中的新内容时。 使用这种方法,团队将不断花费一部分时间来进行配置,而不是开发新功能,修复错误等。

仅在这种情况下,需要一种通用的配置方法,该方法不会与特定的语言或技术相关联,并且允许您以最小的配置常规配置来配置所有服务。 为此,我们开发了一个系统,该系统使用yaml文件配置“模块”(服务),能够存储不同阶段(dev / prod / local等)的配置,并将整个组件划分为与某些组件相关的不同块。

规格书


您可以谈论很多在哪里以及如何使用它,但是我建议直接参考此配置方法的规范。 正如他们所说,理论是好的,实践甚至更好。

系统要求


让我们从定义系统及其要求开始。
  • 每个模块都是容器中的独立组件
  • 我们可以将环境变量传递给容器
  • 如果不重新启动服务(创建新容器),我们将无法即时更改配置。
  • 所有后备操作(例如切换到备份数据库)都在组件外部执行,并且对它是透明的。


配置方法要求


现在,让我们决定要从我们的配置方法中看到什么,以满足所有要求。

  1. 配置文件的类型是指定结构的YAML。 我们选择YAML的原因有几个:
    • 能够编写注释和方便的结构,与JSON不同
    • 与ENV相比,能够描述阵列
    • 开箱即用,可用于值中的values.yaml掌舵(Kubernetes)

  2. 配置文件应合并到配置树中
  3. 该配置必须是特定于阶段的。 每个阶段都有自己的完整集合。 在此有必要保留一些意见以进行澄清:
    • 不能重用其他阶段的变量值, 默认阶段除外,该阶段保留用于默认值。
    • 加载配置时,您需要在默认值之上使用指定阶段的层优先级从指定阶段以递归方式合并配置层 值(数组等)不应合并。
    • 如果一个阶段有多个配置文件,则它们中的键必须合并,因此, 彼此之间必须是唯一的。

  4. 当前使用的阶段必须由环境变量“ STAGE”的值确定。 不打算在正在运行的服务实例中更改变量。
  5. 配置目录的绝对路径应由环境变量“ CONFIG_PATH”的值确定。 为了方便起见,如果某个默认路径中没有变量,则可能会进行回退,这应该在模块的文档中指出。 在这种情况下,指定的路径必须相对于应用程序目录的根目录。


配置实例


假设我们有一项服务,该服务需要存储用于连接到Postgres的设置以及一些关于我们自己的信息

首先,您需要为STAGE = defaults定义一个配置。 在其中,我们将描述总体结构,并使数据与阶段无关。

默认值


# configuration/defaults/service.yaml defaults: version: 1.0.0 name: "config-example" # configuration/defaults/redis.yaml defaults: redis: host: "host" db: 0 port: 6379 password: "password" 


开发者


 # configuration/dev/redis.yaml dev: redis: host: "localhost" password: "hard_pwd" 


结果配置


 version: 1.0.0 name: "config-example" redis: host: "localhost" db: 0 port: 6379 password: "hard_pwd" 


结论



通过这种狡猾的方式,我们解决了在我们的动物园中配置服务的问题,并使所有问题都成为共识。 这个例子只是一个起点,可以修改为您的项目的细节。

对于那些以“裸露的形式”对这种配置方法感兴趣的人:
我们针对不同编程语言的软件包


对于写作方面的帮助,我们特别感谢RoqueSMGladkovskiy)

Source: https://habr.com/ru/post/zh-CN436630/


All Articles