问题
SpringBoot在通过属性或YAML文件外部化配置属性方面提供了很大的灵活性。 我们还可以使用特定于配置文件的配置文件(例如application.properties , application-dev.properties , application-prod.properties等)分别为每个环境(dev,qa,prod等)配置属性。但是一旦应用程序启动,我们就无法在运行时更新属性。 如果更改属性,则需要重新启动应用程序以使用更新的配置属性。
另外,在大量基于MicroService的应用程序的上下文中,我们希望能够从一个集中的位置配置和管理所有MicroServices的配置属性。
解
我们可以使用Spring Cloud Config Server ( http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#_spring_cloud_config )集中所有应用程序配置,并使用应用程序中的Spring Cloud Config Client模块来使用配置配置服务器中的属性。 我们还可以在运行时更新配置属性,而无需重新启动应用程序。
即使您不打算将应用程序部署在任何云平台(例如AWS,Pivotal CloudFoundry等)中,许多Spring Cloud模块也可以在SpringBoot应用程序中使用。
Spring Cloud Config服务器
Spring Cloud Config Server只是具有配置的配置属性源的SpringBoot应用程序。 配置源可以是git存储库, svn存储库或Consul服务( https://www.consul.io/ )。
在本文中,我们将使用git存储库作为配置属性源。
Git配置库
创建一个git存储库来存储属性文件。 我已经在GitHub中创建了一个仓库config-repo ,即https://github.com/sivaprasadreddy/config-repo.git 。
假设我们将开发两个SpringBoot应用程序catalog-service和order-service 。 让我们分别为目录服务和订单服务创建配置文件catalogservice.properties和orderservice.properties 。
config-repo / catalogservice.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/catalog
spring.datasource.username=root
spring.datasource.password=admin
config-repo / orderservice.properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
我们还可以创建特定于配置文件的配置文件,例如catalogservice-dev.properties , catalogservice-prod.properties , orderservice-dev.properties , orderservice-prod.properties 。
config-repo / catalogservice-prod.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://appsrv1:3306/catalog
spring.datasource.username=appuser46
spring.datasource.password=T(iV&#)X84@1!
config-repo / orderservice-prod.properties
spring.rabbitmq.host=srv245.ind.com
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin23
spring.rabbitmq.password=uY7&%we@1!
现在,将所有配置属性文件提交到config-repo git存储库中。
Spring Cloud Config Server应用程序
让我们通过选择启动器Config Server和Actuator从http://start.spring.io或从您最喜欢的IDE创建SpringBoot应用程序spring-cloud-config-server 。
这将使用以下pom.xml生成maven项目。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.sivalabs</groupId><artifactId>spring-cloud-config-server</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>spring-cloud-config-server</name><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.6.RELEASE</version><relativePath/></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Dalston.SR2</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
为了使我们的SpringBoot应用程序成为SpringCloud Config Server,我们只需要在主入口点类中添加@EnableConfigServer批注并配置指向git存储库的spring.cloud.config.server.git.uri属性。
package com.sivalabs.configserver;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {public static void main(String[] args) {SpringApplication.run(ConfigServerApplication.class, args);}
}
spring-cloud-config-server / src / main / resources / application.properties
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/sivaprasadreddy/config-repo.git
management.security.enabled=false
除了配置git repo uri外,我们还将server.port配置为8888并禁用了执行器安全性 。 现在,您可以启动将在端口8888上启动的应用程序。
Spring Cloud Config Server公开以下REST端点以获取特定于应用程序的配置属性:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
这里{application}指的是spring.config.name属性的值, {profile}是活动的概要文件, {label}是可选的git标签(默认为“ master”)。
现在,如果您访问URL http:// localhost:8888 / catalogservice / default,那么您将获得以下响应以及catalogservice 默认配置详细信息:
{"name": "catalogservice","profiles": ["default"],"label": null,"version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d","state": null,"propertySources": [{"name": "https://github.com/sivaprasadreddy/config-repo.git/catalogservice.properties","source": {"spring.datasource.username": "root","spring.datasource.driver-class-name": "com.mysql.jdbc.Driver","spring.datasource.password": "admin","spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"}}]
}
如果访问URL http:// localhost:8888 / catalogservice / prod,则将收到以下响应,其中包含catalogservice prod配置详细信息。
{"name": "catalogservice","profiles": ["prod"],"label": null,"version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d","state": null,"propertySources": [{"name": "https://github.com/sivaprasadreddy/config-repo.git/catalogservice-prod.properties","source": {"spring.datasource.username": "appuser46","spring.datasource.driver-class-name": "com.mysql.jdbc.Driver","spring.datasource.password": "T(iV&#)X84@1!","spring.datasource.url": "jdbc:mysql://appsrv1:3306/catalog"}},{"name": "https://github.com/sivaprasadreddy/config-repo.git/catalogservice.properties","source": {"spring.datasource.username": "root","spring.datasource.driver-class-name": "com.mysql.jdbc.Driver","spring.datasource.password": "admin","spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"}}]
}
除了特定于应用程序的配置文件(如catalogservice.properties , orderservice.properties)之外 ,您还可以创建application.properties文件以包含所有应用程序的通用配置属性。 如您所料,您可以拥有特定于配置文件的文件,例如application-dev.properties,application-prod.properties 。
假设您在config-repo中有具有以下属性的application.properties文件:
message=helloworld
jdbc.datasource.url=jdbc:mysql://localhost:3306/defapp
现在,如果您访问http:// localhost:8888 / catalogservice / prod,则将收到以下响应:
{"name": "catalogservice","profiles": ["prod"],"label": null,"version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d","state": null,"propertySources": [{"name": "https://github.com/sivaprasadreddy/config-repo.git/catalogservice-prod.properties","source": {"spring.datasource.username": "appuser46","spring.datasource.driver-class-name": "com.mysql.jdbc.Driver","spring.datasource.password": "T(iV&#)X84@1!","spring.datasource.url": "jdbc:mysql://appsrv1:3306/catalog"}},{"name": "https://github.com/sivaprasadreddy/config-repo.git/catalogservice.properties","source": {"spring.datasource.username": "root","spring.datasource.driver-class-name": "com.mysql.jdbc.Driver","spring.datasource.password": "admin","spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"}},{"name": "https://github.com/sivaprasadreddy/config-repo.git/application.properties","source": {"message": "helloworld","jdbc.datasource.url": "jdbc:mysql://localhost:3306/defapp"}}]
}
同样,您可以访问http:// localhost:8888 / orderservice / default以获取orderservice配置详细信息。
{"name": "orderservice","profiles": ["default"],"label": null,"version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d","state": null,"propertySources": [{"name": "https://github.com/sivaprasadreddy/config-repo.git/orderservice.properties","source": {"spring.rabbitmq.host": "localhost""spring.rabbitmq.port": "5672""spring.rabbitmq.username": "guest""spring.rabbitmq.password": "guest"}},{"name": "https://github.com/sivaprasadreddy/config-repo.git/application.properties","source": {"message": "helloworld","jdbc.datasource.url": "jdbc:mysql://localhost:3306/defapp"}}]
}
现在,我们已经了解了如何使用Spring Cloud Config Server创建配置服务器,以及如何使用REST API获取应用程序特定的配置属性。
让我们看看如何创建SpringBoot应用程序并使用Config Server中的配置属性,而不是将其放入应用程序中。
Spring Cloud Config客户端(目录服务)
使用Config Client, Web和Actuator启动器创建SpringBoot应用程序目录服务 。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.sivalabs</groupId><artifactId>catalog-service</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>spring-cloud-config-client</name><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.6.RELEASE</version><relativePath/></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Dalston.SR2</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
通常在SpringBoot应用程序中,我们在application.properties中配置属性。 但是,在使用Spring Cloud Config Server时,我们使用bootstrap.properties或bootstrap.yml文件配置Config Server的URL,并且Spring Cloud Config Client模块将通过从Config Server中获取应用程序属性来启动应用程序。
在src / main / resources / bootstrap.properties中配置以下属性:
server.port=8181
spring.application.name=catalogservice
spring.cloud.config.uri=http://localhost:8888
management.security.enabled=false
我们已经使用spring.cloud.config.uri属性配置了配置服务器的URL。 我们还使用spring.application.name属性指定了应用程序名称。
请注意, spring.application.name属性的值应与config-repo中的基本文件名(catalogservice)匹配。
现在运行以下目录服务主入口点类:
package com.sivalabs.catalogservice;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class CatalogServiceApplication {public static void main(String[] args) {SpringApplication.run(CatalogServiceApplication.class, args);}
}
我们可以访问执行器端点http:// localhost:8181 / env以查看所有配置属性。
{"profiles": [],"server.ports": {"local.server.port": 8080},"configService:configClient": {"config.client.version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d"},"configService:https://github.com/sivaprasadreddy/config-repo.git/catalogservice.properties": {"spring.datasource.username": "root","spring.datasource.driver-class-name": "com.mysql.jdbc.Driver","spring.datasource.password": "******","spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"},"configService:https://github.com/sivaprasadreddy/config-repo.git/application.properties": {"message": "helloworld","jdbc.datasource.url": "jdbc:mysql://localhost:3306/defapp"},"servletContextInitParams": {},"systemProperties": {......},"systemEnvironment": {......},"springCloudClientHostInfo": {"spring.cloud.client.hostname": "192.168.0.101","spring.cloud.client.ipAddress": "192.168.0.101"},"applicationConfig: [classpath:/bootstrap.properties]": {"management.security.enabled": "false","spring.cloud.config.uri": "http://localhost:8888","spring.application.name": "catalogservice"},"defaultProperties": {}
}
您可以看到目录服务应用程序在引导期间从Config Server获取目录服务属性。 如果在应用程序内部定义了这些属性,则可以使用@Value或@EnableConfigurationProperties绑定这些属性。
属性优先
现在我们知道有很多方法可以在许多文件中提供配置属性,例如application src / main / resources和{application-name}-{profile} .properties中的 application.properties,bootstrap.properties及其配置文件变体, config-repo中的{profile} .properties 。
下图显示了来自各个属性位置的配置属性的优先级。
在运行时刷新属性
让我们看看如何在运行时更新目录服务的配置属性而无需重新启动应用程序。
在config-repo git存储库中更新catalogservice.properties并提交更改。 现在,如果您访问http:// localhost:8181 / env,您仍然会看到旧的属性。
为了重新加载配置属性,我们需要执行以下操作:
- 使用@RefreshScope标记要在配置更改时重新加载的Spring bean
- 使用POST方法发出http:// localhost:8181 / refresh请求
为了测试重载行为,让我们在config-repo / catalogservice.properties中添加属性name = Siva并提交。
创建一个简单的RestController来显示名称值,如下所示:
@RestController
@RefreshScope
class HomeController
{@Value("${name}")String name;@GetMapping("/name")public String name(){return name;}
}
现在访问http:// localhost:8181 / name,它将显示Siva 。 现在,在config-repo / catalogservice.properties中将属性值更改为name = Prasad并提交。
为了重新加载配置更改,请使用POST方法触发http:// localhost:8181 / refresh请求,然后再次访问应显示Prasad的 http:// localhost:8181 / name。
但是在大量应用程序和同一应用程序的多个实例的情况下,手动发出/刷新请求是乏味且不切实际的。 在下一篇文章中,我们将介绍如何使用Spring Cloud Bus处理此问题。
Spring Cloud教程–使用Spring Cloud Bus自动刷新配置( http://sivalabs.in/2017/08/spring-cloud-tutorials-auto-refresh-config-changes-using-spring-cloud-bus/ )。
本文的源代码位于https://github.com/sivaprasadreddy/spring-cloud-tutorial
翻译自: https://www.javacodegeeks.com/2017/08/spring-cloud-tutorials-introduction-spring-cloud-config-server.html