原文档链接:https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/multi/multi_spring-cloud.html
特性
Spring Cloud专注于为典型用例提供良好的开箱即用的经验,并为其他用例提供可扩展机制。
- Distributed/versioned configuration 分布式/版本化配置
- Service registration and discovery 服务注册与发现
- Routing 路由
- Service-to-service calls 服务之间的调用
- Load balancing 负载均衡
- Circuit Breakers 断路器
- Distributed messaging 分布式消息
第一部分. 云原生应用程序(Cloud Native Applications)
1. 云原生应用程序(Cloud Native Application)
Cloud Native是一种应用程序开发风格,鼓励在持续交付和价值驱动开发领域,更容易地采用最佳实践。 一个相关的训练是,建立12因素应用程序。它主张将开发实践与交付和运营目标保持一致 - 例如,将编码和管理与监控同时进行。 Spring Cloud以多种特定的方式促进这些风格的开发。 它的出发点是提供一组分布式系统中的所有组件都能轻松访问到的功能。
Spring Cloud建立在Spring Boot包含的诸多功能之上。 Spring Cloud将功能划分为两个库:Spring Cloud Context和Spring Cloud Commons。 Spring Cloud Context为Spring Cloud应用程序的ApplicationContext(引导上下文,加密,刷新范围和环境端点)提供工具和特殊服务。 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。 更多信息,请参阅以下链接:
无论您使用哪种版本的JRE / JDK x64 / x86,将文件解压缩到JDK/jre/lib/security文件夹中。
注意:Spring Cloud是在非限制性Apache 2.0许可下发布的。 如果您想为文档的这一部分做出贡献,或者如果发现错误,您可以在github上找到项目的源代码和问题跟踪器。
2. Spring Cloud Context:应用程序上下文服务
Spring Boot有一个关于如何使用Spring构建应用程序的观点。 例如,它为通用配置文件指定了假定的位置,并具有用于常见管理和监视任务的端点。 Spring Cloud构建于此之上,并添加了一些功能,这些是系统中的所有组件都可能使用或偶尔需要的功能。
2.1 引导程序上下文(Bootstrap Application Context)
Spring Cloud应用程序通过创建一个Bootstrap Context来运行,该上下文是主应用程序的父上下文。 它负责从外部源加载配置属性以及解密本地外部配置文件中的属性。 这两个上下文共享一个Environment,它是任何Spring应用程序的外部属性的来源。 默认情况下,引导属性(不是bootstrap.properties,而是在引导阶段加载的属性)以高优先级添加,因此本地配置无法覆盖它们。
Bootstrap Context使用特殊的约定来定位外部配置文件,而不采用主应用程序的上下文。 您可以使用bootstrap.yml代替application.yml(或.properties),使引导程序的外部配置和主应用程序的上下文保持完全分离。 以下清单举了一个示例:
bootstrap.yml.
spring:
application:
name: foo
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果您的应用程序需要来自服务器的任何特定于应用程序的配置,则最好设置spring.application.name(在bootstrap.yml或application.yml中)。 为了将属性spring.application.name用作应用程序的上下文ID,必须在bootstrap中设置它[.properties | .yml]。
您可以通过设置spring.cloud.bootstrap.enabled = false来完全禁用引导过程(例如,在system properties中)。
2.2 应用程序上下文层级(Application Context Hierarchies)
如果您从SpringApplication或SpringApplicationBuilder构建应用程序上下文,那么Bootstrap上下文就会被添加为该上下文的父级。 Spring的一个特性是子上下文从其父级继承属性源和配置文件,因此与构建没有Spring Cloud Config的上下文相比,“主”应用程序上下文包含其他属性源。其他属性来源是:
- “bootstrap”: 如果在Bootstrap上下文中找到任何PropertySourceLocators,并且它们具有非空属性,则会出现具有高优先级的可选CompositePropertySource。一个例子是来源于Spring Cloud Config Server的属性。有关如何自定义此属性源内容的说明,请参见“第2.6节”,“自定义Bootstrap属性源”。
- “applicationConfig: [classpath:bootstrap.yml]”(以及相关文件,如果Spring profiles处于活动状态):如果您有bootstrap.yml(或.properties),则这些属性用于配置Bootstrap上下文。然后,如果设置了父级时,它们将被添加到子上下文中。它们的优先级低于application.yml(或.properties)以及作为创建Spring Boot应用程序过程的正常部分添加到子级的任何其他属性源。有关如何自定义这些属性源的内容的说明,请参见“2.3节”,“更改Bootstrap属性的位置”。
由于属性源的排序规则,“bootstrap”条目优先。但请注意,这些数据不包含来自bootstrap.yml的任何数据,它具有非常低的优先级,但可用于设置默认值。
您可以通过设置您创建的任何ApplicationContext的父上下文来扩展上下文层次结构 - 例如,通过使用自己的接口或SpringApplicationBuilder便捷方法(parent(),child()和sibling())。引导上下文是您自己创建的最高级祖先的父级。层次结构中的每个上下文都有自己的“引导程序”(可能是空的)属性源,这可以避免从父级到其后代无意中提升某些值。如果存在Config Server,则层次结构中的每个上下文(原则上)也可以具有不同的spring.application.name,因此具有不同的远程属性源。普通的Spring应用程序上下文行为规则适用于属性解析:来自子上下文的属性按名称和属性源名称覆盖父级中的属性。 (如果子项具有与父项具有相同名称的属性源,则父项中的值不包含在子项中)。
请注意,SpringApplicationBuilder允许您在整个层次结构中共享Environment(
但这不是默认设置)。因此,同级上下文,不需要再添加相同的配置文件或属性来源,即使他们可能与父上下文有同样的值。
2.3更改Bootstrap属性的位置
可以通过在System properties中设置spring.cloud.bootstrap.name
(默认值:bootstrap
)或spring.cloud.bootstrap.location
(默认值:空)来指定bootstrap.yml
(或.properties
)位置。
这些属性的行为类似于具有相同名称的spring.config.*
变量。实际上,可以在Environment中设置这些属性来设置引导程序
ApplicationContext
。如果有一个活动的配置文件(来源于spring.profiles.active
或通过你创建的上下文中的Environment
API),则在加载配置文件属性的同时,SpringBoot应用程序也加载了这些属性。例如,从bootstrap-development.properties
加载一个development profile
。
2.4 覆盖远程属性的值
引导上下文添加到应用程序的属性源通常是“ 远程 ”(例如,来自Spring Cloud Config Server)。默认情况下,它们无法在本地覆被盖。如果要让应用程序使用自己的系统属性或配置文件覆盖远程属性,则远程属性源必须通过设置授予它权限spring.cloud.config.allowOverride=true
(在本地设置它将不起作用)。设置该标志后,两个更细粒度的设置将控制远程属性相对于系统属性和应用程序本地配置的位置:
spring.cloud.config.overrideNone=true
:允许任何本地属性源覆盖。spring.cloud.config.overrideSystemProperties=false
:只有系统属性,命令行参数和环境变量(但不是本地配置文件)可以覆盖远程设置。
2.5 自定义Bootstrap配置
通过在/META-INF/spring.factories
中名为org.springframework.cloud.bootstrap.BootstrapConfiguration
的key下添加条目,可以让引导上下文执行任何操作。
它包含以逗号分隔的Spring @Configuration
类的列表,这些类用于创建上下文。您可以在此处创建任意可以在主应用程序上下文自动装配的Bean。对于ApplicationContextInitializer类型的
@Beans
有一种特殊的约定。如果要控制启动顺序,可以使用@Order注解
标记类(默认顺序为last
)。
添加自定义BootstrapConfiguration时
,请注意不要让这些类通过@ComponentScanned
错误地进入您的“ 主 ”应用程序上下文。请给引导配置类使用单独的程序包名称,并确保您的@ComponentScan不包含这个包,或者不要用给这些类添加
@SpringBootApplication
注解。
引导过程在将初始化程序注入主SpringApplication
实例时结束(这是正常的Spring Boot启动顺序,无论是作为独立应用程序运行还是部署在应用程序服务器中)。首先,从spring.factories
中找到的类来创建引导上下文。然后,在启动之前将所有ApplicationContextInitializer类型的@Beans
添加到main SpringApplication
。
2.6 自定义Bootstrap属性源
引导过程添加的外部配置的默认属性源是Spring Cloud Config Server,但您可以通过给引导上下文增加PropertySourceLocator类型的bean
来添加其他配置源(通过spring.factories)。例如,您可以从其他服务器或数据库插入其他属性。
例如,请考虑以下自定义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
(例如,通过键入它spring.application.name
,就像在默认的Spring Cloud Config Server属性源定位器中所做的那样)。
如果您在其中创建一个包含此类的jar,然后添加一个META-INF/spring.factories
包含
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
,那么customProperty
PropertySource将
会出现在任何其类路径中包含该jar的应用程序中。
2.7 记录配置
如果要使用Spring Boot配置日志设置,并且想让它应用于所有event,则应将此配置放在bootstrap.[yml | properties]中。
要使Spring Cloud正确初始化日志记录配置,您不能使用自定义前缀。例如, |
2.8环境变化
应用程序监听EnvironmentChangeEvent事件,并且
以几种标准方式响应变化(可以给自定义ApplicationListeners以正常的方式添加
@Beans注解
)。当一个EnvironmentChangeEvent事件被
观察到时,它有一个已变化的键值列表,应用程序使用它们:
- 在上下文中重新绑定任何
@ConfigurationProperties注解的
bean - 在
logging.level.*中
设置任何属性的logger级别
请注意,默认情况下,Config Client不会轮询Environment中的变化
。通常,我们不建议使用这种方法来检测被变化(尽管您可以使用 @Scheduled
注释进行设置)。如果您有一个可扩展的客户端应用程序,最好广播EnvironmentChangeEvent
到所有实例,而不是让它们轮询变化(例如,使用Spring Cloud Bus)。
EnvironmentChangeEvent事件
涵盖一大类刷新用例,只要你确实对Environment做了改变并
发布的事件。(请注意,这些API是公共的,并且是核心Spring的一部分)。您可以通过访问/configprops
端点(一个正常的Spring Boot Actuator功能)来验证更改是否绑定到@ConfigurationProperties注解的
bean 。例如,一个DataSource可能
有个maxPoolSize属性
在运行时更改(Spring Boot创建的默认DataSource
是@ConfigurationProperties注解的
bean)并动态增加容量。重新绑定@ConfigurationProperties
不包括另一大类用例,在这些用例中,您需要更多地控制刷新并且需要将更改变为对于整体ApplicationContext是
原子的。为了解决这些问题,我们有@RefreshScope
。
2.9 刷新范围
当配置发生变化时,@RefreshScope注解的
@Bean
将获得特殊处理。此功能解决了有状态bean的问题,只有在初始化时才会注入其配置。例如,如果一个DataSource用几个open的连接,这时
数据库URL通过Environment变化了
,您可能希望这些连接的持有者能够完成他们正在执行的操作。然后,下次从池中借用连接时,它会获得一个带有新URL的连接。
有时,甚至可能必须应用@RefreshScope
注解在一些只能初始化一次的bean上。如果bean是“不可变的”,则必须使用@RefreshScope
在bean上注释或在属性spring.cloud.refresh.extra-refreshable下
指定该类名 。
重要 | |
---|---|
如果您 |
刷新范围bean采用lazy模式(即,使用它们时才初始化),并且范围充当初始化值的缓存。要强制bean在下一个方法调用时重新初始化,必须使其缓存条目无效。
RefreshScope
是上下文中的一个bean,它有一个公共refreshAll()
方法,通过清除目标缓存来刷新scope中的所有bean。/refresh
端点暴露该功能(通过HTTP或JMX)。要按名称刷新单个bean,还有一个refresh(String)
方法。
要公开/refresh
端点,您需要将以下配置添加到您的应用程序:
management:
endpoints:
web:
exposure:
include: refresh
|
2.10 加密和解密
Spring Cloud有一个Environment
预处理器,用于在本地解密属性值。它遵循与Config Server相同的规则,并具有相同的外部配置encrypt.*
。因此,您可以用{cipher}*
的形式使用加密值,只要有有效密钥,它们就会在主应用程序上下文获取Environment
设置之前被解密。要在应用程序中使用加密功能,您需要在类路径中包含Spring Security RSA(Maven座标:“org.springframework.security:spring-security-rsa”),并且还需要全面的JCE扩展在你的JVM中。
如果遇到“Illegal key size”异常并且您使用Sun的JDK,则需要安装Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files。有关更多信息,请参阅以下链接:
无论您使用哪种版本的JRE / JDK x64 / x86,都要将文件解压缩到JDK / jre / lib / security文件夹中。
2.11端点
对于Spring Boot Actuator应用程序,可以使用一些其他管理端点。您可以使用:
POST到
/actuator/env去
更新Environment
并重新绑定@ConfigurationProperties和log levels
。/actuator/refresh
重新加载引导上下文并刷新@RefreshScope
bean。/actuator/restart
关闭ApplicationContext
并重新启动它(默认情况下禁用)。/actuator/pause
和/actuator/resume
调用Lifecycle
方法(在ApplicationContext上的
stop()
和start()
)。
如果禁用 |