【前面的话】本文的某些知识依赖个人微服务系列文章,若是没有看过能够先移步去看一下。在前面的应用当中,咱们全部的配置都是写在yaml配置文件当中的,这样就会形成几个问题:安全、统一管理等等。而SpringCloud也是考虑到这一点,给出的方案就是Spring Cloud Config。java
Spring Cloud Config是Spring Cloud团队建立的一个全新项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分。其中服务端也称为分布式配置中心,它是一个独立的微服务应用,用来链接配置仓库并为客户端提供获取配置信息、加密/解密信息等访问接口;而客户端则是微服务架构中的各个微服务应用或基础设施,它们经过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。Spring Cloud Config实现了对服务端和客户端中环境变量和属性配置的抽象映射,因此它除了适用于Spring构建的应用程序以外,也能够在任何其余语言运行的应用程序中使用。因为Spring Cloud Config实现的配置中心默认采用Git来存储配置信息,因此使用Spring Cloud Config构建的配置服务器,自然就支持对微服务应用配置信息的版本管理,而且能够经过Git客户端工具来方便的管理和访问配置内容。固然它也提供了对其余存储方式的支持,好比:SVN仓库、本地化文件系统。git
<parent> <artifactId>lovincloud</artifactId> <groupId>com.eelve.lovincloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>lovin-config-server</artifactId> <packaging>jar</packaging> <name>lovinconfigserver</name> <version>0.0.1</version> <description>配置服务端</description> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> <version>2.1.6</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
server: port: 8886 # 服务端口号 spring: application: name: lovinconfigserver # 服务名称 security: basic: enabled: true user: name: lovin password: ${REGISTRY_SERVER_PASSWORD:lovin} cloud: config: server: git: uri: https://github.com/lovinstudio/lovincloud search-paths: lovin-config-repo label: master eureka: client: serviceUrl: defaultZone: http://lovin:lovin@localhost:8881/eureka/ # 注册到的eureka服务地址
spring: cloud: config: server: git: uri: https://github.com/lovinstudio/lovincloud search-paths: lovin-config-repo username: #若是是私人仓库,还须要配置用户名,公共仓库能够省略 password: #若是是私人仓库,还须要配置密码,公共仓库能够省略 label: master
spring: cloud: config: server: svn: uri: http://192.168.0.6/svn/repo/config-repo username: username password: password default-label: trunk profiles: active: subversion #这里须要显式声明为subversion
同时还须要引入相应的配置:github
<!--SVN--> <dependency> <groupId>org.tmatesoft.svnkit</groupId> <artifactId>svnkit</artifactId> </dependency>
spring: cloud: config: server: native: searchLocations: file:D:\\config #classpath:/config profiles: active: native #native
package com.eelve.lovin.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * @ClassName WebSecurityConfig * @Description TDO * @Author zhao.zhilue * @Date 2019/8/18 13:52 * @Version 1.0 **/ @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().permitAll() .and().csrf().disable(); } }
package com.eelve.lovin; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * @ClassName LovinEurekaClientApplication * @Description TDO * @Author zhao.zhilue * @Date 2019/8/15 16:37 * @Version 1.0 **/ @SpringBootApplication @EnableEurekaClient @EnableConfigServer public class LovinConfigServerApplication { public static void main(String[] args) { SpringApplication.run(LovinConfigServerApplication.class,args); } }
{"name":"lovin-config","profiles":["dev"],"label":null,"version":"f0aeca26887490e3bcb8be317d4dfb378313a76f","state":null,"propertySources":[{"name":"https://github.com/lovinstudio/lovincloud/lovin-config-repo/lovin-config-dev.properties","source":{"lovin.token":"lovin"}}]}
这时咱们经过浏览器、POSTMAN或CURL等工具直接来访问到咱们的配置内容了。访问配置信息的URL与配置文件的映射关系以下:web
/{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
上面的url会映射{application}-{profile}.properties对应的配置文件,其中{label}对应Git上不一样的分支,默认为master。咱们能够尝试构造不一样的url来访问不一样的配置内容,好比,要访问master分支,config-client应用的dev环境,就能够访问这个url:http://chirius:8806/lovin-config/dev,并得到以下返回:
这里有一点疑问,我经过http://localhost:8886/lovin-config/dev/去访问是一直不成功的,可是在换成其余github上面别人的配置仓库又是能够直接访问的spring
2019-08-19 12:55:54.686 INFO 9256 --- [nio-8886-exec-4] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/C:/Users/Chirius/AppData/Local/Temp/config-repo-8280352825025657146/lovin-config-repo/lovin-config-dev.properties 2019-08-19 12:55:57.560 INFO 9256 --- [nio-8886-exec-2] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname 2019-08-19 12:55:57.576 INFO 9256 --- [nio-8886-exec-2] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/C:/Users/Chirius/AppData/Local/Temp/config-repo-8280352825025657146/lovin-config-repo/lovin-config-dev.properties 2019-08-19 12:56:00.544 INFO 9256 --- [nio-8886-exec-1] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname 2019-08-19 12:56:00.559 INFO 9256 --- [nio-8886-exec-1] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/C:/Users/Chirius/AppData/Local/Temp/config-repo-8280352825025657146/lovin-config-repo/lovin-config-dev.properties 2019-08-19 12:56:07.136 INFO 9256 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration 2019-08-19 13:01:07.140 INFO 9256 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration 2019-08-19 13:06:07.142 INFO 9256 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
ps:经过日志咱们能够看到配置文件是被保存在咱们本地的,固然咱们也就能够经过配置,修改保存的路径,具体配置为:basedirbootstrap
新建一个config的服务端子工程lovin-config-client,用于后面的操做。下面是主要的pom依赖:浏览器
<parent> <artifactId>lovincloud</artifactId> <groupId>com.eelve.lovincloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>lovin-config-client</artifactId> <packaging>jar</packaging> <name>lovinconfigclient</name> <version>0.0.1</version> <description>配置消费端</description> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> <version>2.1.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> <version>2.1.3.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
ps:在这里为了监控配置变化咱们须要添加spring-boot-starter-actuator的依赖安全
spring: cloud: config: name: lovin-config profile: dev uri: http://localhost:8886/ label: master eureka: client: serviceUrl: defaultZone: http://lovin:lovin@localhost:8881/eureka/ # 注意在高可用的时候须要见注册中心配置移到该文件中,在application.yml中见会读取不到配置
server: port: 8807 # 服务端口号 spring: application: name: lovinconfigclient # 服务名称 security: basic: enabled: true user: name: lovin password: ${REGISTRY_SERVER_PASSWORD:lovin}
package com.eelve.lovin.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * @ClassName WebSecurityConfig * @Description TDO * @Author zhao.zhilue * @Date 2019/8/20 16:59 * @Version 1.0 **/ @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().permitAll() .and().csrf().disable(); } }
package com.eelve.lovin; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * @ClassName LovinEurekaClientApplication * @Description TDO * @Author zhao.zhilue * @Date 2019/8/15 16:37 * @Version 1.0 **/ @SpringBootApplication @EnableEurekaClient public class LovinConfigClientApplication { public static void main(String[] args) { SpringApplication.run(LovinConfigClientApplication.class,args); } }
package com.eelve.lovin.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @ClassName ConfigController * @Description TDO * @Author zhao.zhilue * @Date 2019/8/20 17:17 * @Version 1.0 **/ @RestController @RefreshScope // 使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。 public class ConfigController { @Value("${lovin.token}") private String token; @RequestMapping("/token") public String getToken() { return this.token; } }
PS:其中RefreshScope注解是为了刷新配置来添加的,这样让配置仓库中的配置发生改变的时候,咱们能够经过访问/refresh请求来刷新配置(由spring-boot-starter-actuator提供的监控功能)服务器
能够看到这是咱们已经获取到了最新的配置,当时这样就存在一个问题,每个配置客户端都须要刷新配置,会很是麻烦,也很容易出错。解决方案由webhook来刷新配置,可是这个不是最好的解决办法。可是咱们能够经过消息总线来解决,这里见会在下一篇文章中详细讲解,在这里就不做赘述了。架构