前言
由于想看一下spring cloud相关内容,因此翻译了一下 spring cloud文档,未完成部分会逐渐补上 转载请注明出处 http://blog.csdn.net/maozi_bsz。
Spring Cloud
Spring cloud 提供了一些工具给开发者在分布式系统(例如 配置管理,服务发现,断路器,智能路由,微代理,控制总线)中来快速构建一些有着相同的工作模块。分布式系统衍生出一些模块,而使用 Spring cloud 的开发者可以快速的建立服务和应用,来实现这些模块。他们会在任何分布式环境中运行良好,包括开发者自己的笔记本电脑,数据中心和如 Cloud Foundry 的管理平台。
版本:Finchley.M2
Features
Spring Cloud 关注于为经典用例提供一个好的框架,并用扩展性覆盖其他用例。
- 分布式的/版本控制的 配置
- 服务的注册与发现
- 路由
- 服务到服务的调用
- 负载均衡
- 断路器
- 分布式消息
Cloud Native Applications
Cloud Native 是一种开发模式它鼓励采用在连续和价值驱动开发中最好的实践。相关的学科是构建 12-factor Apps,它的开发实践由交付和操作目标来统一,例如使用声明式编程、管理和监控。Spring Cloud用具体几种方法推进这种开发方式,其起点就是一个功能集,包含了分布式系统的所有要么需要要么在需要时容易获取的组件。
大部分功能是由 Spring Boot 提供的,我们的 Spring Cloud 建立在其之上。一些是实现在 Spring Cloud 比如两个库:Spring Cloud Context 和 Spring Cloud Commons。Spring Cloud Context 提供一些工具和特殊的服务给 一个 Spring Cloud 应用的 ApplicationContext
(bootstrap context, encryption, refresh scope and environment endpoints)。Spring Cloud Commons 是抽象和公共类的集合,它们被用在不同的 Spring Cloud 实现中(例如,Spring Cloud Netflix 和 Spring Cloud Consul)。
如果你遇到一个错误是由“Illegal key size”引起的,并且你在使用 Sun 公司的 JDK。那么你需要安装 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。查看下列链接获取更多信息:
提取文件到 JDK/jre/lib/security 文件夹 (whichever version of JRE/JDK x64/x86 you are using).
Note,Spring Cloud 在无限制的 Apache 2.0 下发布。如果你想要贡献文档章节,或发现了一个错误,请在项目的 github 中查找源码或问题跟踪。
Spring Cloud Context: Application Context Services
Spring Boot有一个页面来展示如何用 Spring 构建项目:例如,他有常规配置文件的常规目录,以及用于常见管理和监视任务的端点。Spring Cloud 是建立在其之上的,并添加了一些所有组件在系统中可能或偶尔用到的功能。
The Bootstrap Application Context
一个 Spring Cloud 应用,通过创建一个 “bootstrap” 上下文来操作,它是 main application 的父上下文。其主要负责从外部源加载配置属性,也解码本地外部源的配置。这两个上下文共享 Environment
,它是每个 Spring 应用外部属性的源。Bootstrap 属性有着高优先级,因此默认情况下,他们不会被本地配置覆盖。
Bootstrap 上下文使用不同于主应用上下文的外部配置地址。因此,我们使用 bootstrap.yml
而不是 application.yml
(or .properties
)。来保证 bootstrap 和 主应用 很好的分离。
例如:
bootstrap.yml
spring:
application:
name: foo
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果你的应用需要特别的配置,那么设置 spring.application.name
(在 bootstrap.yml
或 application.yml
) 是个好办法。
你可以通过设置spring.cloud.bootstrap.enabled=false
(例如在系统变量中)来禁止 bootstrap 进程完成
Application Context Hierarchies(层次结构)
如果你通过 SpringApplication
或 SpringApplicationBuilder
来创建应用上下文,那么 Bootstrap 上下文会被作为其父上下文添加。这是 Spring 的一个特性,子上下文会继承父上下文的属性与值,因此 “main” application的上下文会包含额外的属性,对比未使用 Spring Cloud Config的应用。额外的属性源如下:
“bootstrap”: 一个
CompositePropertySource
选项有较高的出现优先级,如果任何PropertySourceLocators
属性在 Bootstrap context 中被找到并且他们有非空的属性。 一个使用 Spring Cloud Config Server 配置的例子。查看下文获取如何自定义 property source 内容的介绍。“applicationConfig: [classpath:bootstrap.yml]” (and friends if Spring profiles are active). 如果你有一个
bootstrap.yml
(或 properties) 那么这些属性会被用来配置 Bootstrap context ,当其父上下文被设置时,它们会被作为子上下文添加进去。它们比application.yml
(or properties) 和其他任何作为正常部分添加到 application 上下文的子上下文的优先级低。查看 下文 获取如何自定义这些 property sources 的介绍。
由于属性源的顺序,“bootstrap”是有优先级的。但是注意是不包括bootstrap.yml
中的所有的数据,有一些有着很低的优先级,但是可以作为默认值设置。
你可以简单的设置父上下文为你创建的任何 ApplicationContext
来扩展层级结构,例如,使用其本身的接口,或使用 SpringApplicationBuilder
的快捷方法(parent(), child() and sibling())。bootstrap context 会是你创建上下文的最高级的父上下文。每个在层级中的上下文,会有它们自己的 “bootstrap” 属性源(也可能是空的)来避免不经意地将值传给后代。每个在层级中的上下文也(原则上)有一个不同的 spring.application.name
,并且如果有 Config Server 会使用不同的远端属性源。常规的 Spring 上下文特性:来自子上下午的属性会覆盖父上下文的,通过名称和属性源名称(如果子上下文有一个属性源名称和父上下文相同,那么父上下文中的属性源,不会被包含到子上下文中)
注意,SpringApplicationBuilder
允许你在整个结构中分享 Environment
,但这不是默认的。因此,特别是兄弟关系上下文不需要具有相同的配置文件或属性源,即使它们将与父类共享共同的东西。
Changing the Location of Bootstrap Properties
bootstrap.yml
(or .properties
)的位置可以用 spring.cloud.bootstrap.name
(默认 “bootstrap”)或 spring.cloud.bootstrap.location
(默认为空)来指定。例如,在系统属性中。这些属性的行为类似于 spring.config.*
的变种。事实上,它们通常用来设置启动 ApplicationContext
通过在 Environment
中设置。如果激活 profile (通过 spring.profiles.active
,或在你正在构建的context中使用 Environment
API),profile中的属性就会被加载,就像正常的 spring 应用。例如 bootstrap-development.properties
用来给“开发” 配置。
Overriding the Values of Remote Properties
通过 bootstrap context 添加到你应用中的属性源,通常是远程的(例如 来自一个 Config Server),并且默认的,它们不会被本地的配置覆盖,除了在命令行中。如果你希望你的应用使用自己的系统属性或配置文件来重写远端属性,远端属性需要授予其权限通过 spring.cloud.config.allowOverride=true
(在本地设置是无效的)。有一些细粒度的控制属性:
spring.cloud.config.overrideNone=true
可以被任何本地属性覆盖,和
spring.cloud.config.overrideSystemProperties=false
只有系统属性和环境变量应该可以覆盖,而不是本地文件。
Customizing the Bootstrap Configuration
Bootstrap 上下文可以被设置来做任何事,通过在 /META-INF/spring.factories
中的 org.springframework.cloud.bootstrap.BootstrapConfiguration
键下添加条目。这里有一个逗号分隔的 Spring @Configuration
类,将被用来创建上下文。任何你希望在 main application 上下文中出现可以自动注入的 bean,都可以写在这里,同样有一个特殊的 @Beans
的定义在类型 ApplicationContextInitializer
。类可以标记 @Order
如果你希望控制它们启动的顺序(默认是 “last”)。
警告:请注意,你添加在 BootstrapConfiguration
的类没有用注解 @ComponentScanned
导入主应用上下文。对没用被 @ComponentScan
和 @SpringBootApplication
声明覆盖的类,使用 boot 配置。
Bootstrap 过程,通过注入 initializers 到主 SpringApplication
实例(即,常规的 Spring Boot 启动序列,不管它是否独立运行或部署在应用服务)。首先 bootstrap 上下文从 spring.factories
找到的类中创建,然后所有 @Beans
注解的 ApplicationContextInitializer
类型会被添加到主 SpringApplication
在其启动前。
Customizing the Bootstrap Property Sources
默认的外部配置属性源,被 bootstrap 过程添加,其是 Config Server,但是你可以添加额外的源,通过添加 bean PropertySourceLocator
到 Bootstrap 上下文(通过 spring.factories
)。你可以使用这些来添加额外的属性,来自一个不同的 Server,或 来自一个数据库,或来自一个实例。
自定义 locator 片段的示例:
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
@Override
public PropertySource<?> locate(Environment environment) {
return new MapPropertySource("customProperty",
Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
}
}
传进来的 Environment
是有关将要被创建的 ApplicationContext
的,就是,我们将要提供额外属性源的上下文。它早就有正常的 Spring Boot 属性源,因此你可以通过 Environment
来使用和定位一个属性(例如,通过 key spring.application.name
,来获取默认 Config Server 中的值)。
如果你构建了一个jar,包含该类,并且将下面的配置添加到 META-INF/spring.factories
中:
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
然后 “customProperty” PropertySource
会在每个包含该 jar 的应用中出现。
Environment Changes
应用会监听 EnvironmentChangeEvent
,并且通过几个标准方式起作用(额外 ApplicationListeners
可以被作为 @Bean
添加)。当 EnvironmentChangeEvent
被观察到时,有一系列的 key 值被改变,然后应用会如下应用:
- 重现绑定任何在上下文中 @ConfigurationProperties 注解的bean。
- 设置新的 logger level 根据
logging.level.*
注意,默认情况下 Config Client 不会拉取 Environment
中的变化,并且一般情况下我们也不推荐监听变化(尽管你可以用 @Scheduled
注解开启)。如果你有横向的应用,那么最好广播 EnvironmentChangeEvent
到所有的实例,而不是它们各自去拉去(例如使用 Spring Cloud Bus)。
EnvironmentChangeEvent
包含了大量的类和刷新用例,只要你确实改变了 Environment
并发布事件(这些接口是公共的,并且是 Spring 核心的一部分)。 你可以通过 /configprops
端点来确认被 ConfigurationProperties
绑定的bean(常规的 Spring Boot Actuator 特性)。例如,被 DataSource
会有一个 maxPoolSize
属性在运行中改变(被 Spring Boot 创建的 DataSource
默认是一个 @ConfigurationProperties
bean)并且容量是动态增长的。重新绑定 @ConfigurationProperties
不包含用例的另一个大类,类你需要更多的刷新控制和类你需要在整个 ApplicationContext
中原子化的改变。为了到达这个目的我们有 @RefreshScope
。
Refresh Scope
一个 Spring @Bean
被 @RefreshScope
标记,在配置改变时,会被特殊对待。这解决了状态 bean,只有在初始化时才注入配置的问题。例如一个 DataSource
开启了一个链接当数据库 RUL 通过 Environment
变化时,我们可能希望这些连接的持有者能够完成他们正在做的事情。然后,下次有人从池中借用连接时,他会得到一个新URL的连接。
Refresh scope bean 是懒代理的,只当被使用时初始化(即,当一个方法被调用),目标行为作为缓存的初始值。要强制bean在下一个方法调用中重新初始化,只需使其缓存条目无效。
RefreshScope
是作为一个 bean 存在上下文中的,它有一个公共的方法 refreshAll()
来刷新所有目标 bean 通过清除它们的缓存。它也有一个方法 refresh(String)
来刷新单独的 bean ,通过名字。这些函数暴露在 /refresh
端点(通过 HTTP 或 JMX 访问)。
注意,@RefreshScope
在一个 @Configuration
类上有效(技术上),但是它可能导致意外的行为:例如,它不意味着定义在类里的所有 @Beans
有它们自己的 @RefreshScope
。具体来说,依赖于这些bean的任何东西都不能依赖于刷新启动时更新它们,除非它们自己在 @RefreshScope
(这样他们会在刷新时重建并重新注入依赖,在这一点上,它们会用刷新过的 @Configuration
来重新初始化)。
Encryption and Decryption
Spring Cloud 有一个 Environment
预处理,来在本地解码属性值。它与 Config Server 使用相同的规则,并有相同的外部配置通过 encrypt.*
。因此你可以用 {cipher}*
格式来编码值,然后直到有一个合理的key,然后它们会被解码病写入应用上下文的 Environment
。为了在应用中使用编码特性,你需要包含 Spring Security RSA 到 classPath (Maven co-ordinates “org.springframework.security:spring-security-rsa”)并且你也需要添加全部的JCE到JVM。
如果你遇到一个错误是由“Illegal key size”引起的,并且你在使用 Sun 公司的 JDK。那么你需要安装 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。查看下列链接获取更多信息:
提取文件到 JDK/jre/lib/security 文件夹 (whichever version of JRE/JDK x64/x86 you are using).
Endpoints
对于 Spring Boot Actuator 应用,这里有一些额外的管理端点:
- POST 到
/env
来更新Environment
并且重新绑定@ConfigurationProperties
和日志等级 /refresh
来重新加载启动上下文并刷新@RefreshScope
bean/restart
来关闭ApplicationContext
并重启它(默认是禁用的)/pause
和/resume
来调用Lifecycle
方法(stop()
和start()
在ApplicationContext
)
Spring Cloud Commons: Common Abstractions
模式比如,服务发现,负载均衡,断路器都有相同的抽象层,可以被所有的 Spring Cloud 客户端使用,而不依赖于具体实现(例如 服务发现通过 Eureka 或 Consul).
@EnableDiscoveryClient
Commons 提供 @EnableDiscoveryClient
注解。这会寻找在 META-INF/spring.factories
中寻找 DiscoveryClient
的实现。Discovery Client 的实现会添加配置类到 spring.factories
在 org.springframework.cloud.client.discovery.EnableDiscoveryClient
键下。DiscoveryClient
的实现例子:是 Spring Cloud Netflix Eureka, Spring Cloud Consul Discovery 和 Spring Cloud Zookeeper Discovery。
默认情况下,DiscoveryClient
的实现会自动注册本地 Spring Boot 服务器到远程发现服务器。这可以通过设置 autoRegister=false
在 @EnableDiscoveryClient
来禁止。
Health Indicator
Commons 创建一个 Spring Boot HealthIndicator
,DiscoveryClient
可以参与,通过实现 DiscoveryHealthIndicator
接口。通过 HealthIndicator set spring.cloud.discovery.client.composite-indicator.enabled=false
可以禁止混用。一个基于 DiscoveryClient
通常的 HealthIndicator
是自动配置(DiscoveryClientHealthIndicator
)。为了禁用它,可以设置 spring.cloud.discovery.client.health-indicator.enabled=false.
。为了禁用 DiscoveryClientHealthIndicator
的描述域可以设置 spring.cloud.discovery.client.health-indicator.include-description=false
,不然 it can bubble up as the description of the rolled up HealthIndicator。
ServiceRegistry
Common 现在提供一个 ServiceRegistry
接口,来提供方法类似 register(Registration)
和 deregister(Registration)
允许你提供自定义的注册服务。Registration
是一个标记接口。
@Configuration
@EnableDiscoveryClient(autoRegister=false)
public class MyConfiguration {
private ServiceRegistry registry;
public MyConfiguration(ServiceRegistry registry) {
this.registry = registry;
}
// called via some external process, such as an event or a custom actuator endpoint
public void register() {
Registration registration = constructRegistration();
this.registry.register(registration);
}
}
每个 ServiceRegistry
实现,有它自己的 Registry
实现。
ServiceRegistry Auto-Registration
默认的,ServiceRegistry
的实现会自动注册运行的 service。有两种方法禁止自动注册。你可以设置 @EnableDiscoveryClient(autoRegister=false)
来永久的禁用自动注册。你可以设置 spring.cloud.service-registry.auto-registration.enabled=false
来通过配置禁止自动注册行为。
Service Registry Actuator Endpoint
一个 /service-registry
actuator 端点被 Commons 提供。这个 endpoint 依托于一个 Registration
bean 在 Spring Application Context。调用 /service-registry/instance-status
通过 GET 方法会返回 Registration
的状态。用 POST 方法调用相同的端点,并包含一个 String
的请求体 会改变当前的 Registration
的状态到新的值。请看 ServiceRegistry
文档,来查看可用的状态值和返回状态。
Spring RestTemplate as a Load Balancer Client
RestTemplate
可以自动的配置来使用 ribbon。为了创建一个负载均衡 RestTemplate
创建一个 RestTemplate
@Bean
并且使用 @LoadBalanced
qualifier()。
警告 一个
RestTemplate
不再通过自动配置创建。它必须被独立的应用创建。
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private RestTemplate restTemplate;
public String doOtherStuff() {
String results = restTemplate.getForObject("http://stores/stores", String.class);
return results;
}
}
其中 URI 需要使用虚拟主机名(即,service 名称,而不是一个主机名)。Ribbon 客户端被用来创建完整的物理地址。查看 RibbonAutoConfiguration 获取更多如何配置 RestTemplate
的细节。
Retrying Failed Requests
一个负载均衡 RestTemplate
可以被配置失败请求重试。默认的该逻辑是禁止的,你可以开启它通过添加 Spring Retry 到你应用的 classpath。关于失败请求重试,负载均衡 RestTemplate
会尊重一些 Ribbon 的配置值。如果你希望在 Spring Retry
存在于 classpath 时,禁用其逻辑你可以设置 spring.cloud.loadbalancer.retry.enabled=false
。还有一些属性你可以使用 client.ribbon.MaxAutoRetries
,client.ribbon.MaxAutoRetriesNextServer
和 client.ribbon.OkToRetryOnAllOperations
。查看 Ribbon documentation 来获取更多的关于属性的描述。
注意,
client
在下面例子中,应该替换为你自己的 Ribbon 客户端名称。
Multiple RestTemplate objects
如果你希望一个 RestTemplate
不是负载均衡的,创建一个 RestTemplate
bean 并像常规 bean 一样注入。为了使用父在均衡,你需要在创建 RestTemplate
bean 时使用 @LoadBalanced
。
重要,注意下面例子中常规
RestTemplate
上@Primary
注解,用来消除不合格的@Autowired
注入。
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate loadBalanced() {
return new RestTemplate();
}
@Primary
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private RestTemplate restTemplate;
@Autowired
@LoadBalanced
private RestTemplate loadBalanced;
public String doOtherStuff() {
return loadBalanced.getForObject("http://stores/stores", String.class);
}
public String doStuff() {
return restTemplate.getForObject("http://example.com", String.class);
}
}
提示,如果你遇到像这样的错误
java.lang.IllegalArgumentException: Can not set org.springframework.web.client.RestTemplate field com.my.app.Foo.restTemplate to com.sun.proxy.$Proxy89
尝试注入RestOperations
替代或设置spring.aop.proxyTargetClass=true
。
Spring WebFlux WebClient as a Load Balancer Client
WebClient
可以通过配置使用 LoadBalancerClient
。一个 LoadBalancerExchangeFilterFunction
会被自动配置,如果 spring-webflux 在 classpath 中。
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private LoadBalancerExchangeFilterFunction lbFunction;
public Mono<String> doOtherStuff() {
return WebClient.builder().baseUrl("http://stores")
.filter(lbFunction)
.build()
.get()
.uri("/stores")
.retrieve()
.bodyToMono(String.class);
}
}
其中 URI 需要使用虚拟主机名(即,service 名称,而不是一个主机名)。LoadBalancerClient
被用来创建完整的物理地址。
Ignore Network Interfaces
在某些时候,忽略确定的网络接口名字是有用的,这样他们可以被从 Service Discovery 的注册中被排除(例如,运行在一个 Docker 容器中)。可以设置正则表达式的列表,这样所需的网络接口会被忽略。下述的配置会忽略 “docker0” 接口,和所有以 “veth” 开头的接口。
application.yml
spring:
cloud:
inetutils:
ignoredInterfaces:
- docker0
- veth.*
你也可以强制只使用特定的网络地址使用正则表达式列表:
application.yml
spring:
cloud:
inetutils:
preferredNetworks:
- 192.168
- 10.0
你也可以强制只使用本地地址。查看 Inet4Address.html.isSiteLocalAddress() 查看网站本地地址的细节。
application.yml
spring:
cloud:
inetutils:
useOnlySiteLocalInterfaces: true
HTTP Client Factories
Spring Cloud Commons 提供 bean 来创建 Apache HTTP 客户端 (ApacheHttpClientFactory)
和 OK HTTP 客户端 (OkHttpClientFactory
)。OkHttpClientFactory
只在 OK HTTP jar 存在于 classpath 时,才会创建。此外,Spring Cloud Commons 提供 bean 来创建 两种客户端的链接管理,ApacheHttpClientConnectionManagerFactory
为 Apache HTTP 客户端创建管理,OkHttpClientConnectionPoolFactory
为 OK HTTP 客户端创建管理。你可以为这些 bean 提供你自己的实现,如果你希望自定义 HTTP 客户端在下游项目中如何被创建。你也可以禁用这些 bean 创造,通过设置 spring.cloud.httpclientfactories.apache.enabled
或 spring.cloud.httpclientfactories.ok.enabled
为 false
。
Spring Cloud Config
Finchley.M2
Spring Cloud Config 提供了服务器和客户端的支持,来在分布式系统中外化配置。使用 Config Server 你有一个中心位置来管理在所有环境中应用的外部属性。客户度和服务端的 Spring Environment
和 PropertySource
的抽象概念相同,因此他们很适应 Spring 应用,但是可以用来创建任何语言的任何应用。当应用程序通过部署管道从开发到测试并进入生产时,您可以管理这些环境之间的配置,并确保应用在迁移时有他们运行所需的所有东西。默认的服务储存端实现使用 git,因此它很容易的来支持配置环境的标签版本,配置内容也可以被很多的工具访问管理。添加替代的实现是容易的,使用 Spring configuration 接入他们。
Quick Start
开启服务器:
$ cd spring-cloud-config-server
$ ../mvnw spring-boot:run
该服务是一个 Spring Boot 应用你可以在 IDE 中运行来代替,如果你喜欢(main class 是 ConfigServerApplication
)。然后试运行一个客户端:
$ curl localhost:8888/foo/development
{"name":"foo","label":"master","propertySources":[
{"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
{"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
]}
默认的定位属性源的策略是克隆一个 git 仓库(在 spring.cloud.config.server.git.uri)并使用它来初始化一个小的 SpringApplication
。mini-application的 Environment
被用来枚举属性源然后通过 JSON 端点发布他们。
HTTP 服务有下表的资源:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
上述 “application” 会被作为 spring.config.name
注入到 SpringApplication
(即,常规 Spring Boot app 的 “application”),“profile” 是一个激活简介(或一个逗号分隔的属性列表),“label” 是一个可选的 git 标签 (默认为 “master”)。
Spring Cloud Config Server 为远程客户端从 git 仓库(必须被提供的)拉取配置:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
Client Side Usage
为了在应用中使用这些特性,只需要构建一个 Spring Boot 应用并依赖 spring-cloud-config-client (例如,查看 config-client 的测试用例,或例子应用)。最方便的方式来添加依赖是通过 Spring Boot starter 的 org.springframework.cloud:spring-cloud-starter-config
。There is also a parent pom and BOM (spring-cloud-starter-parent) for Maven users and a Spring IO version management properties file for Gradle and Spring CLI users. Example Maven configuration:
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- repositories also needed for snapshots and milestones -->
然后你可以创建一个标准的 Spring Boot 应用,就像这个简单的 HTTP 服务器:
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
当其运行时,它会从默认的8888端口本地配置服务拉取外部配置。为了更改启动行为,你可以改变配置服务器的位置使用 bootstrap.properties
(像 application.properties
但是处于应用上下文的 bootstrap 阶段),例如:
spring.cloud.config.uri: http://myconfigserver.com
bootstrap的属性,会显示在 /env
端点,作为一个高优先级的属性源,例如。
$ curl localhost:8080/env
{
"profiles":[],
"configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
"servletContextInitParams":{},
"systemProperties":{...},
...
}
(一个叫做 “configService:/” 的属性源,包含属性 “foo” 有值 “bar” 并且是最高优先级)。
注意,属性源的 URL 是 git 仓库的 URL 不是配置服务器的 URL。
Spring Cloud Config Server
该服务提供了一个 HTTP的,基于资源的 API 给外部配置(名值对,或相等的YAML内容)。该服务器很容易嵌入 Spring Boot 应用通过使用 @EnableConfigServer
注解。因此下面这个应用是配置服务器:
ConfigServer.java
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
像所有的 Spring Boot 应用,它默认运行在8080端口,但是你可以通过多种方法,将它转到传统的8888端口。最简单的是,也设置一个默认的配置库,但是使用 spring.config.name=configserver
(有一个 configserver.yml
在 Config Server jar中)加载。另一个方法是使用你自己的 application.properties
,例如:
application.properties
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo
${user.home}/config-repo
是一个 git 仓库包含 YAML 和 属性文件。
注意,在 Windows 中,你需要额外的 “/” 在文件的 URL 中,如果他是绝对路径并有驱动前缀 例如:
file:///${user.home}/config-repo
。
提示,创建 git 仓库的示例:
$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"
警告,只应该在测试用,使用本地的文件系统,作为 git 仓库。在生产环境中,使用一个服务器来作为 git 仓库放置配置属性。
警告,如果只保留文本文件,配置存储库的初始克隆将快速高效。如果您开始存储二进制文件,尤其是大型文件,您可能会遇到第一个配置请求的延迟和/或内存溢出错误。
Environment Repository
你希望在哪里为 Config Server 储存配置数据?控制这种行为的策略是 EnvironmentRepository
,提供 Environment
对象。该 Environment
是来自 Spring Environment
的域的浅拷贝(包括 propertySources
作为主要特性)。Environment
被三个变量参数化:
{application}
映射到 “spring.application.name” 在客户端{profile}
映射到 “spring.profiles.active” 在客户端(逗号分隔的列表){label}
是一个服务器端的特性,标记一个配置文件的 “versioned” 集合
仓库就像一个 Spring Boot 应用那样,实现了一般行为,加载配置文件,“spring.config.name” 等于 {application}
参数,“spring.profiles.active” 等于 {profiles}
参数。配置文件的优先级规则也与常规的 Boot 应用程序相同:主动配置文件优先于默认值,如果有多个配置文件,最后一个将获胜(就像往一个 Map
中添加条目)。
例如:一个客户端应用,有这样的 bootstrap 配置:
bootstrap.yml
spring:
application:
name: foo
profiles:
active: dev,mysql
(就像通常的 Spring Boot 应用,这些属性可以被设置为环境变量或命令行参数)。
如果配置是基于文件的,服务器会从 application.yml
(被所有客户端共享) 和 foo.yml
(有foo.yml
优先考虑) 中创建一个 Environment
。如果YAML文件有内部有文档指向 Spring profies,这些会作为较高的优先级来提供(在 profiles 列表中的顺序),并且如果有 prfile-specific YAML(或 properties)文件,它们也会以更高的优先级提供,比默认优先级。高优先级更早的传输一个 PropertySource
列表给 Environment
。(独立的 Spring Boot 应用中,也有类似的规则)
Git Backend
默认的 EnvironmentRepository
实现,使用 git 后台,git 后台对管理升级和物理环境非常方便,对审计更改也非常方便。为了改变仓库的位置,你可以在 Config Server 的配置属性中设置 “spring.cloud.config.server.git.uri”(例如,在 application.yml
中)。如果你设置了 file:
前缀,他应该作为一个本地仓库工作因此你可以快速开始而不需要服务器,但是这种情况下,服务器会直接在本地库操作,而不克隆他(如果它不是空的,这并不重要,因为 Config Server 从不更改“远程”库)。为了放大 Config Server 使其有高可用性,您需要使服务器的所有实例指向同一个存储库,因此只有一个共享文件系统才行。甚至在这种情况下最好使用 ssh
:共享文件系统存储库的协议,以便服务器能够克隆它并使用本地工作副本作为缓存。
这个库实现映射 {label}
参数到 HTTP 资源,它是一个 git label (commit id,branch name 或 tag)。如果 git branch 或 tag name 包含了斜线(”/”)那么 label 在 HTTP URL 中应该使用 “(_)”代替(来避免与其它 URL 产生歧义)。例如,一个 label 是 foo/bar
,替换斜杠后应该像这样 foo(_)bar
。在 URL 中使用括号是要小心,如果你使用一个命令行客户端像 curl (例如,使用引号 ” 将它们转义)。
Placeholders in Git URI
Spring Cloud Config Server 支持一个 git 仓库地址有占位符 {application}
和 profile
(和 label
如果你需要它,但是记住它是 git 标签)。因此你可以简单的支持 “每个应用一个仓库” 的策略(例如):
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/{application}
或者一个 “每个 profile 一个仓库”的策略,有相同的模式但是使用 {profile}
。
Pattern Matching and Multiple Repositories
其也支持更复杂的需求,通过模式匹配在 application 和 profile 名称。这正则格式是逗号分隔的关于 {application}/{profile}
名称和通配符(以通配符开头的正则可能需要将其用引号包起来)的列表。例子:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
simple: https://github.com/simple/config-repo
special:
pattern: special*/dev*,*special*/dev*
uri: https://github.com/special/config-repo
local:
pattern: local*
uri: file:/home/configsvc/config-repo
如果 {application}/{profile}
没找到任何匹配,它会使用默认 URI 定义在 “spring.cloud.config.server.git.uri”。在上面的例子中,“simple” 仓库的正则是 simple/*
(即,他只匹配应用名称“simple”,不管 profiles)。 “local” 仓库匹配所有的以“local”开头的应用名称和所有的 profiles(/*
后缀是自动添加的,如果正则中没有 profile 的匹配)。
注意,在上面例子中 “simple” 的 “一行”简写,只能被用在 URI 只有其属性设置时。如果需要设置其它东西(证书,正则等)你需要使用全格式。
pattern
属性在 repo 中,其实是一个列表,因此你可以使用 YAML 数组(或 0,1,等后缀在 properties 文件中)来绑定多个正则。你需要这样做,如果你将要运行一个有多个 profiles 的应用。例子:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
repos:
development:
pattern:
- '*/development'
- '*/staging'
uri: https://github.com/development/config-repo
staging:
pattern:
- '*/qa'
- '*/production'
uri: https://github.com/staging/config-repo
注意,Spring Cloud 将会猜测一个正则包含 profile 不以
*
结尾,暗示你真正想匹配的是一个系列profiles,以正则开头(因此*/staging
是一个简写对于["*/staging", "*/staging,*"]
)。例如,如果你需要一个应用本地在运行 “development” profile 但是 远程使用 “cloud” profile,是相同的。
每个库还可以选择存储配置文件的子目录,并正则搜索这些目录可以被指定为 searchpaths
。例如:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: foo,bar*
在该例子中,服务器在顶层目录和 “foo/” 子目录和所有 “bar” 开头的子目录中搜索配置文件。
当配置被第一次请求,服务器会克隆远程仓库。服务器可以被配置为启动克隆。例如:
spring:
cloud:
config:
server:
git:
uri: https://git/common/config-repo.git
repos:
team-a:
pattern: team-a-*
cloneOnStart: true
uri: http://git/team-a/config-repo.git
team-b:
pattern: team-b-*
cloneOnStart: false
uri: http://git/team-b/config-repo.git
team-c:
pattern: team-c-*
uri: http://git/team-a/config-repo.git
在该例子中,服务器克隆 team-a 的 config-repo 仓库在启动时,在所有请求之前。其他的仓库在进行配置请求之前,不会被克隆。
注意,设置存储库进行克隆在 Config Server 启动时可以在 Config Server 启动时很快帮助确定一个错误配置的源(例如,一个无效的库URI)。对一个配置源禁用
cloneOnStart
,Config Server 可能成功启动在存在配置错误或无效配置源的时候,直到应用从这些配置源中请求配置时,才会发现错误。
Authentication
为了使用基于 HTTP 的仓库权鉴,分别添加 “username” 和 “password” 到配置文件(不是 URL 中)。例如:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
username: trolley
password: strongpassword
转载请注明出处 http://blog.csdn.net/maozi_bsz