查看原文
其他

译:Spring Cloud Config (第二部分): Git 后端

Emma SpringForAll社区 2020-10-17


原文链接

https://dzone.com/articles/spring-cloud-config-series-part-2-git-backend?fromrel=tru

作者:Enrique Recarte

译者:Emma

现在您已经开始使用Spring Cloud Config,让我们看看如何将Git后端绑定到您的应用程序以及所涉及的架构考虑因素。

在本系列的第一部分中,我们看了一下Spring Cloud Config的介绍,在这篇文章中,我们将看到Git后端的具体实现以及使用此后端提供的不同选项。

简介

正如我们之前看到的,Twelve Factor App Manifesto中的一个因素是将配置移出我们的应用程序。有很多不同的方法可以做到这一点,但是在选择管理配置的工具时需要考虑的其他一些问题:

  • Auditing changes:应该很容易看出由谁和他们应用时做了哪些改变的历史。

  • Approval of changes:错误的配置导致了很多产品问题理想情况下,在改变配置之前,都应该再次查看。

  • Resiliency:如果配置工具不可用会发生什么?

  • Synchronization:应用程序如何知道配置发生了变化?

看到上面的要点,其中大多数都描述了版本控制系统(Version Control System, ),这是我们用来存储应用程序源代码的。您有时想知道谁更改了Java类中的某些代码以及为什么,您应该能够找出谁更改了一些超时配置以及原因,那么为什么不为您的配置使用VCS呢?

这正是使用Git作为Spring Cloud Config后端的原因。配置更改控制的第一堂课。如果你将Git的功能与Pull Requests之类的东西混合在一起,你会获得很棒的工作流程,可以更好地了解应用于环境的配置更改,以及更好的工具,以确定环境中的某些事物是否已经发生变化,谁做了变更,以及对变更原因的描述。

使用Git作为后端

使用Git作为Spring Cloud Config后端时,我们需要讨论三个主要的库:

  • spring-cloud-context:正如我们在上一篇文章中所看到的,Spring Cloud引入了引导程序应用程序上下文(bootstrap application context)的概念,该概念使用PropertySourceLocator来加载远程配置。这个接口是不同的后端实现的入口点,而且存在这个库中,该库被任何一个spring cloud应用包含。它也包含RefreshEndpoint,它允许我们调用POST /refresh来触发应用程序上下文的刷新。

  • spring-cloud-config-server:Spring Cloud Config的默认后端实现。它增加PropertySourceLocator,它将使用一个或多个与不同系统通信的EnvironmentRepository。这些存储库负责解析适用于特定应用程序,配置文件和标签的环境。 EnvironmentRepository有一些不同的实现可以连接到Git,SVN或Vault。

  • spring-cloud-config-client:当你部署 Spring Cloud Config Server在自己的应用中,将会使用这个库。当这个服务是独立的,你需要一个可以通过http连接到服务的客户端。这就是这个库恰好做的,它添加一个PropertySourceLocator,它将调用服务器来加载适用的配置。

Git配置存储库的结构

如果你以前已经使用过Spring Boot,那么你可能熟悉它如何加载配置。通常管理配置的主要方式是添加一些application- {profile} .properties或application- {profile} .yml,在不同的配置文件中添加特定于环境的属性。例如,如果您有UAT环境和PROD环境,则可以使用下面的树,其中特定于配置文件的文件包含该特定环境的配置,application.properties文件包含适用于所有环境的配置属性。

  1. $ tree

  2. .

  3. ├── application-PROD.properties

  4. ├── application-UAT.properties

  5. └── application.properties

使用Spring Cloud Config,此属性结构略有不同。由于您很可能使用Git配置存储库来存储多个应用程序的配置,因此命名结构需要支持它。支持它的方法是在应用程序名称后命名文件,因此如果在前面的示例中,您的应用程序已命名(使用spring.application.name)作为StandaloneGitFirstClient,并且您还有另一个名为StandaloneGitSecondClient的应用程序,则您的属性文件在您的配置存储库看起来像这样:

  1. $ tree

  2. .

  3. ├── StandaloneGitFirstClient-PROD.properties

  4. ├── StandaloneGitFirstClient-UAT.properties

  5. ├── StandaloneGitFirstClient.properties

  6. ├── StandaloneGitSecondClient-PROD.properties

  7. ├── StandaloneGitSecondClient-UAT.properties

  8. ├── StandaloneGitSecondClient.properties

  9. └── application.properties

看这棵树,我们现在非常类似地对.properties进行分组,但是我们使用应用程序的名字代替一般使用的application-前缀。

你可能注意到这儿仍有一个application.properties文件。如果这个文件存在,它的属性能应用到所有环境的所有应用程序。你也可以有一个application-UAT.properties,它可以应用到UAT 环境中的所有应用程序等。

Spring Cloud Config还可以让你选择为每个应用程序,甚至不同的存储库建立不同目录。如果你想了解有关不同选项的更多信息,请查看参考文档。

架构选择

正如我们之前所描述的,Spring Cloud Config Server是与Git通信的库, 一旦存储库被克隆,它就能依据不同的参数确定应用哪些配置属性。

该库可以以两种不同的方式使用 - 具有将使用此库的中央应用程序,并使所有客户端应用程序与此服务器应用程序通信,或将库包含到所有客户端应用程序中。让我们更详细地看一下这些选项。

独立配置服务器设置

我们要看的第一个选项是比较传统的,即我们部署一个单独的应用程序来管理我们的配置。我们看到的将如下图所示:

如您所见,Spring Cloud Config Server位于自己的应用程序中。所有这个应用程序都是克隆Git存储库,监听客户端应用程序要求配置发出的请求,并返回这些请求的适用配置。

客户端应用程序本身只包括我们之前描述的RefreshEndpoint,以及将在引导阶段运行的Spring Cloud Config Client,调用服务器以获取传递名称,配置文件和标签的适用配置。最后一个参数可以是特定的Git分支或提交。

实现细节

为了使用此设置,假设您的应用程序已经是Spring Boot应用程序,您至少应该做以下操作:

1.您的客户端应用程序将需要导入Spring Cloud Config Client maven依赖项。

  1.    <dependency>

  2.       <groupId>org.springframework.cloud</groupId>

  3.       <artifactId>spring-cloud-starter-config</artifactId>

  4.    </dependency>

2.在类路径的根目录中定义名为bootstrap.properties的文件,该文件需要包含以下属性:

  1.       # The name of the application

  2.       spring.application.name: StandaloneGitFirstClient

  3.       # The URI of your Spring Cloud Config Server

  4.       spring.cloud.config.uri: http://localhost:8888

此bootstrap.properties文件定义应用程序启动的引导阶段中使用的配置。由于远程配置是在主应用程序上下文启动之前加载的,因此我们需要一个不同的文件来定义适用于该过程的特定部分的配置。通常,此文件仅包含Spring Cloud Config关注的属性。

3.在您的服务器应用程序中,导入Spring Cloud Config Server Maven依赖项:

  1.       <dependency>

  2.          <groupId>org.springframework.cloud</groupId>

  3.          <artifactId>spring-cloud-config-server</artifactId>

  4.       </dependency>

4.通过编辑application.properties,使用合适的Git存储库配置服务器应用程序。

  1.       # The URI of the Git Repository where the configuration is stored

  2.       spring.cloud.config.server.git.uri: https://github.com/erecarte/blog-spring-cloud-config-configuration.git

  3.       # The port on which this application runs

  4.       server.port: 8888

应用程序更新application.properties 而不是 bootstrap.properties 的原因是因为服务器本身不需要使用Git配置,它只是使用它将其返回到其他应用程序,因此不需要引导程序配置。

5.在服务器中使用@EnableConfigServer注释主应用程序类:

  1.    @SpringBootApplication

  2.    @EnableConfigServer

  3.    public class StandaloneGitServerApplication {

  4.       public static void main(String[] args) {

  5.          SpringApplication.run(StandaloneGitServerApplication.class);

  6.       }

  7.    }

按照步骤操作后,应首先启动服务器应用程序,然后启动客户端。当客户端启动时,您将看到的第一个日志条目如下所示:

  1. 2017-08-03 14:07:57.708  INFO 74429 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4f6ee6e4: startup date [Thu Aug 03 14:07:57 BST 2017]; root of context hierarchy

  2. 2017-08-03 14:07:57.904  INFO 74429 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$EnhancerBySpringCGLIB$ed33cade] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

  3.  .   ____          _            __ _ _

  4. /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \

  5. ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \

  6. \\/  ___)| |_)| | | | | || (_| |  ) ) ) )

  7.  '  |____| .__|_| |_|_| |_\__, | / / / /

  8. =========|_|==============|___/=/_/_/_/

  9. :: Spring Boot ::        (v1.5.2.RELEASE)

  10. 2017-08-03 14:07:58.142  INFO 74429 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888

  11. 2017-08-03 14:08:01.631  INFO 74429 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=StandaloneGitFirstClient, profiles=[default], label=null, version=null, state=null

如果您查看代码段的最后两行,在执行任何操作之前,它首先从Spring Cloud Config Server获取远程配置,然后才开始加载应用程序上下文。

如果你想看更详细的独立设置示例,可以在github获取代码。此示例存储库包含两个客户端应用程序和服务器。它们的配置位于其他存储库中。

优势

  • 只有一个应用程序与git通信,这取决于您的架构,可能是一个安全优势。

  • 您的应用程序只需要包含一个通过HTTP进行通信的瘦客户端(thin client)。

劣势

  • 没有那么灵活。如果您的服务器应用程序出现故障,客户端应用程序将无法启动,或者将在没有配置的情况下启动,不得不依赖于默认值。您可以使用属性spring.cloud.config.fail-fast来配置应用程序是否应该在此故障后启动,默认为false。

  • 服务器成为另一个要部署和维护的应用程序。

嵌入式配置服务器设置

现在我们看看其他设置。我们可以将服务器嵌入到客户端应用程序中,而不是运行服务器的不同应用程序。下图说明了这种情况: 您可以看到图表稍微简单一些.客户端应用程序不再使用Spring Cloud Config Client因为他们需要通过HTTP与服务器通信,而是在应用程序内部有服务器。

实现细节

以下是嵌入服务器时需要遵循的步骤:

1.您的客户端应用程序需要导入Spring Cloud Config Server Maven依赖项:

  1.    <dependency>

  2.       <groupId>org.springframework.cloud</groupId>

  3.       <artifactId>spring-cloud-config-server</artifactId>

  4.     </dependency>

2.使用bootstrap.properties中相应的Git存储库配置客户端应用程序:

  1. # The name of the application

  2. spring.application.name: StandaloneGitFirstClient

  3. # The URI of the Git Repository where the configuration is stored

  4. spring.cloud.config.server.git.uri: https://github.com/erecarte/blog-spring-cloud-config-configuration.git

  5. # Whether the Spring Cloud Config Server should configure iteslf with the loaded configuration.

  6. spring.cloud.config.server.bootstrap: true

再次注意,现在这个配置如何进入 bootstrap.properties 而不是 

application.properties。另外请注意我们定义属性 spring.cloud.config.server.bootstrap = true以强制库自举。这是因为现在我们需要嵌入式 Spring Cloud Config Server 在引导阶段从加载的配置中进行自我配置。

3.使用@EnableConfigServer注解主应用程序类:

  1.    @SpringBootApplication

  2.    @EnableConfigServer

  3.    public class EmbeddedGitFirstClientApplication {

  4.       public static void main(String[] args) {

  5.          SpringApplication.run(EmbeddedGitFirstClientApplication.class);

  6.       }

  7.    }

优势

  • 简化基础配置

  • 应用程序更灵活。你可以不依赖于中间服务器,而且服务器库也可以将存储库克隆到磁盘上,这也意味着如果启动时拉取失败,可以使用本地版本。如果Git服务器宕机,应用程序将使用最后一次拉取的配置进行启动,从而减少配置错误的可能性并且必须使用默认值。

劣势

  • 应用程序第一次启动将会变慢,因为它需要检查完整的Git存储库。如果整个公司只有一个配置存储库,同时拥有数百或数千个服务,那么这变得很重要。出于这个原因,我可能建议在组织中为每个团队或区域配置存储库。

  • 所有的应用程序都与Git服务器通信。如果应用程序代码和配置代码都使用相同的Git服务器,这尤其成为问题,因为它会扩大安全威胁。

检测配置改变

我们在上一篇文章已经看过如何刷新应用程序上下文的快速概述,但在本节中,我们将看一个如何完成实现的真实示例。 Spring Cloud提供了一种解决方案,可以根据几个库检测应用程序中的配置更改:

  • spring-cloud-config-monitor: 该库为您的应用程序添加了一个端点(endpoint),该端点了解来自不同Git服务器提供程序(如GitHub或Bitbucket)的webhook。 如果包含此依赖项,则会添加/monitor端点。然后,您只需要在Git存储库中配置webhook,以指向部署此端点的位置。调用此端点后,它将解析有效负载以了解已更改的内容,然后它将使用下一个库告知客户端应用程序配置发生更改,因此刷新应用程序上下文。您可以在此博客文章中找到有关此库的更多信息。

  • spring-cloud-bus: 这是一个简单的库,Spring提供了通过一些消息代理将全局事件传递给其他应用程序。它主要用于此用例,您需要向所有/某些应用程序发送RefreshRemoteApplicationEvent事件,告知它们应刷新其应用程序上下文。它与RabbitMQ或Kafka集成为消息代理。

让我们来看看解决方案的架构概述: 

这我们之前看到的图表有一些变化:

  • Server Application现在具有Spring Cloud Config Monitor组件,该组件将监听POST / monitor的请求。

  • 现在有一个RabbitMQ代理。

  • 客户端应用程序还与Spring Cloud Bus集成,后者添加了一个Refresh Listener,它将监听Refresh Remote ApplicationEvent。如果发生此事件,它将以与RefreshEndpoint相同的方式触发上下文刷新。 在这个例子中,我只考虑了之前讨论的独立设置。对于嵌入式设置,您必须拥有自定义解决方案,因为没有集中式服务器可以管理添加/monitor端点的所有配置。

结束语

在这篇文章中,我们深入了解了如何使用Git存储应用程序的配置,并使用Spring Cloud Config连接到Git并为您管理配置。

从基础架构的角度设计解决方案时,我们也看到了一些不同的选项,以及在配置发生变化时自动更新应用程序的一种实现。

通过Git后,下一篇文章将介绍我们可以管理您的配置的不同后端:Zookeeper。

推荐:译:微服务架构10条最佳实践

上一篇:(译)Spring Cloud Config(第一部分)

社区内推:请点击阅读原文

关注公众号


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存