Spring Cloud Confg 是用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分。其中服务端也称为分布式配置中心,它是一个独立的微服务应用,用来链接配置仓库并为客户端提供获取配置信息、加密/解密信息等访问接口;而客户端则是微服务架构中的各个微服务应用或基础设施,它们经过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。html
搭建一个 Config Server,首先须要一个仓库,做为分布式配置中心的存储。这里咱们选择了 Github 做为咱们的仓库:https://github.com/JMCuixy/cloud-config-server/tree/master/config-repo
java
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <!--启动 security 保护,不须要可不添加--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
server: port: 7001 spring: application: name: cloud-config-server # 配置完成后可访问的 url 以下,好比:http://localhost:7001/env/default # /{application}/{profile} [/{label}] # /{application}-{profile}.yml # /{label}/{application}-{profile}.yml # /{application}-{profile}.properties # /{label}/{application}-{profile}.properties cloud: config: # 为配置中心提供安全保护 username: user password: password server: git: # 仓库地址 uri: https://github.com/JMCuixy/cloud-config-server.git # 搜索路径 search-paths: config-repo # 访问 http://localhost:7001/actuator/health 能够获取配置中心健康指标 health: repositories: env: name: env profiles: default label: master env-dev: name: env-dev profiles: dev label: master env-test: name: env-test profiles: test label: master env-prod: name: env-prod profiles: prod label: master # 提供 security 保护 security: user: name: user password: password management: endpoint: health: enabled: true show-details: always eureka: client: service-url: defaultZone: http://user:password@localhost:1111/eureka/
这里我没有配置 Github 的 username 和 password,用的是 SSH key 的方式。git
// 开启 Spring Cloud Config 的 Server 功能 @EnableConfigServer @EnableDiscoveryClient @SpringBootApplication public class ConfigApplication { public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); } }
至此,一个 Spring Cloud Config Server 就搭建完成了。上面的配置中,咱们将 Config Server 注册到 Eureka Server 中,看成整个系统服务的一部分,因此Config Client 只要利用 Eureka 的服务发现维持与 Config Server 通讯就能够了。github
在Config Server 的文件系统中,每次客户端请求获取配置信息时,Confg Server 从 Git 仓库中获取最新配置到本地,而后在本地 Git 仓库中读取并返回。当远程仓库没法获取时,直接将本地内容返回。web
Spring Cloud Confg 的客户端在启动的时候,默认会从工程的 classpath 中加载配置信息并启动应用。只有当咱们配置 spring.cloud.config.uri(或者spring.cloud.config.discovery) 的时候,客户端应用才会尝试链接 Spring Cloud Confg 的服务端来获取远程配置信息并初始化 Spring 环境配置。同时,咱们必须将该参数配置在bootstrap.yml、环境变量或是其余优先级高于应用 Jar 包内的配置信息中,才能正确加载到远程配置。spring
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- 当链接 config-server 失败的时候,可增长重试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <!--配置动态刷新--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
spring: application: # 对应配置文件规则中的 {application} 部分 name: env cloud: config: name: env # uri: http://localhost:7001 discovery: enabled: true service-id: cloud-config-server # 环境变量 profile: default # 分支 label: master # config Server 配置的安全信息 username: user password: password # 快速失败响应(当发现 config-server 链接失败时,就不作链接的准备工做,直接返回失败) fail-fast: true # 失败重试 retry: # 初始重试间隔时间,毫秒 initial-interval: 1000 # 下一间隔的乘数 multiplier: 1.1 # 最大间隔时间 max-interval: 2000 # 最多重试次数 max-attempts: 6
bootstrap 配置会系统会优先加载,加载优先级比 application 高。bootstrap
server: port: 7002 spring: application: name: cloud-config-client eureka: client: service-url: defaultZone: http://user:password@localhost:1111/eureka/ management: endpoints: web: exposure: # 开启指定端点 # 配置刷新地址:POST http://127.0.0.1:7002/actuator/refresh include: 'refresh'
@EnableDiscoveryClient @SpringBootApplication public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } }
接下来瞅瞅客户端要怎么读到服务器的配置项呢?安全
@RefreshScope @RestController public class ConfigClientAdmin { @Value("${from:default}") private String from; @Autowired private Environment environment; @RequestMapping("/from") public String from() { String fromEnv = environment.getProperty("from"); return from + "_" + fromEnv; } }
如上,咱们可使用 @Value 注解注入配置信息,或者使用 Environment Bean 来获取配置项。服务器
须要注意的是,当服务端的配置项更新的时候,客户端并不会同步得到更新,须要 Post 方法执行 "/actuator/refresh" 来刷新配置项。架构
@RefreshScope 注解使配置的内容动态化,当使用 http://127.0.0.1:7002/actuator/refresh 刷新配置的时候,会刷新带有 @RefreshScope 的 Bean。
上一篇文章 咱们尝试用 Spring Cloud Zuul 搭建了网关服务,可是咱们发现路由信息都配置在 application.yml 中,这对网关的高可用是个不小的打击,由于网关做为系统流量的路口,总不能由于改个路由信息每天重启网关吧?因此动态路由的实现,就变得火烧眉毛了,好在咱们如今有了 Spring Cloud Config。
首先,咱们将 Spring Cloud Zuul 的路由信息,配置在 Config Server 的 env.yml 中:
zuul: routes: client-1: # ?:匹配任意单个数量字符;*:匹配任意多个数量字符;**:匹配任意多个数量字符,支持多级目录 # 使用 url 的配置没有线程隔离和断路器的自我保护功能,不推荐使用 path: /client-1/** url: http://localhost:2222/ # 敏感头信息设置为空,表示不过滤敏感头信息,容许敏感头信息渗透到下游服务器 sensitiveHeaders: "" customSensitiveHeaders: true client-2: path: /client-2/** serviceId: cloud-eureka-client # zuul.routes.<serviceid> = <path> cloud-eureka-client: /client-3/** client-4: path: /client-4/** # 请求转发 —— 仅限转发到本地接口 url: forward:/local # Zuul 将对全部的服务都不自动建立路由规则 ignored-services: "*" # 对某些 url 设置不通过路由选择 ignored-patterns: {"/**/world/**","/**/zuul/**"} # Spring Cloud Zuul在请求路由时,会过滤掉 HTTP 请求头(Cookie、Set-Cookie、Authorization)信息中的一些敏感信息, sensitive-headers: {"Cookie", "Set-Cookie", "Authorization"} # 网关在进行路由转发时为请求设置 Host 头信息(保持在路由转发过程当中 host 头信息不变) add-host-header: true # 请求转发时加上 X-Forwarded-*头域 add-proxy-headers: true # 是否开启重试,默认关闭 retryable: true # 经过 /zuul 路径访问的请求会绕过 dispatcherServlet, 被 Zuu1Servlet 处理,主要用来应对处理大文件上传的状况。 servlet-path: /zuul # 禁用某个过滤器 zuul.<SimpleClassName>.<filterTye>.disable=true TokenFilter: pre: disable: true
而后,咱们将网关服务注册为 Config Client(配置项与上面相似,就不赘述了),从 Config Server 获取路由信息:
@EnableZuulProxy @EnableDiscoveryClient @SpringBootApplication public class DynamicRouteApplication { public static void main(String[] args) { SpringApplication.run(DynamicRouteApplication.class, args); } /** * 刷新地址:POST http://127.0.0.1:5006/actuator/refresh * 路由查看地址:GET http://127.0.0.1:5006/actuator/routes * * @return */ @Bean @Primary //该注解来使 zuul 的配置内容动态化 @RefreshScope @ConfigurationProperties(prefix = "zuul") public ZuulProperties zuulProperties() { return new ZuulProperties(); } }
这样,就把咱们的路由信息交给 Config Server 去管理了~~