2. spring cloud 环境:应用环境服务
spring boot 对使用spring 构建应用有个约束的看法。例如,它对常用的配置文件有约定的路径并且有常用的管理和监控任务。spring cloud 基于spring boot而构建,并新增了系统中所有组件可能会用到或偶尔用到的一些功能。
2.1 Bootstrap 应用环境
一个 spring cloud 应用程序通过创建一个 “bootstrap” 上下文来运行,所创建的上下文是主应用的父级上下文。它负责加载来自外部资源的配置属性并解码本地外部配置文件的属性。这两个上下文共享一个环境,这个环境是任意spring 应用外部属性的资源。默认的情况下, 引导属性(不是bootstrap.properties,而是引导阶段加载的属性) 以高优先级添加,所以不能同过本地配置来覆盖。
引导上下文使用不同约定来定位外部配置而不是主应用上下文。你可以使用 bootstrap.yml 替换 applicatio.yml (或.properties),使引导程序和主要上下文的外部配置保持良好的分离。以下清单显示了一个例子:
bootstrap.yml
spring:
application:
name: foo
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}
你可以通过设置spring.cloud.bootstrap.enabled = false来完全禁用引导过程(例如,在系统属性中)。
2.2 应用程序序上下文层次结构
如果从SpringApplication 或 SpringApplicationBuilder 来构建应用程序上下文,引导程序上下文会添加为父级上下文。spring的一个特性是子上下文从父级继承属性源和配置文件,因此与构建没有Spring Cloud Config 的相同上下文相比,“主”应用程序上下文包含其他属性源。其他属性源是:
·"bootstrap": 如果在Bootstrap上下文中找到任何PropertySourceLocators,并且他们具有非空属性,则会出现具有高优先级的可选CompositePropertySource。一个例子是Spring Cloud Config Server 的属性。有关如何自定义此属性源内容的说明,请参见“第2.6节 "自定义Bootstrap属性源"”。
·"applicationConfig:[classpath:bootstrap.yml]"(以及Spring激活配置下的相关文件):如果你有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允许你在整个层次结构中共享环境,但这不是默认的。因此,兄弟上下文尤其不必拥有相同的配置或属性源,即使他们与其父级共享同样的值。
2.3 更改引导程序属性的路径
bootstrap.yml(或 .properties) 的路径可以通过设置spring.cloud.bootstrap.name (默认:bootstrap) 或 spring.cloud.bootstrap.location(默认:空)来指定--例如,在系统属性中设置。这些属性行为类似具有相同名称的spring.config.* 变量。实际上,他们用于通过在其环境中设置这些属性来设置引导程序ApplicationContext。如果存在活动配置文件(来自sprin.profiles.active 或通过你正在构建的上下中的 Enviroment API),则该配置文件中的属性也会加载,与常规Spring Boot 应用程序中的属性相同-例如,bootstrap-development.properties 用于开发配置文件。
2.4 覆盖远程属性值
由引导上下文添加到应用程序的属性源通常是"远程的" (例如,来自 Spring Cloud Config Server)。默认情况下,它们无法本地覆盖。如果要让应用程序使用自己的系统属性或配置文件覆盖远程属性,则远程属性源必须通过设置spring.cloud.allowOverride=true来授权(在本地设置不起作用)。设置该标志后,两个更细粒度的设置控制与系统属性和应用程序的本地配置相关的远程属性的位置:
·spring.cloud.config.overrideNode=true:覆盖本地任何属性源。
·spring.cloud.config.ovverideSystemProperties=false: 只有系统属性,命令行参数,环境变量(本地配置文件除外)能够覆盖远程设置。
2.5 自定义引导配置
通过在名为org.springframework.cloud.bootstrap.BootstrapConfiguration的键下向/META-INF/spring.properties添加条目,可以将引导上下文设置为执行任何操作。它包含一个用于创建上下文以逗号分隔的String @Configuration 类列表。你可以在此创建你希望用于主应用程序上下文以进行自动装配的任何Bean。类型ApplicationContextializer的@Beans 有一个特殊的合约。如果要控制启动顺序,可以使用@Order注解来标记类(默认的顺序是last)。
当添加自定义BootstrapConfiguration时,请注意所添加类不是@CmponentScanned 错误加到应用程序上下文,这或许是不需要的。引导配置使用单独的包名,并且确保该包名不被@ComponentScan 或 @SpringApplication 注解配置类使用。
引导过程通过将初始化器注入主SpringApplication 实例(这是正常的Spring Boot启动程序,无论是作为独立应用程序运行还是部署在应用程序服务器中)来结束。首先,引导上下文是从spring.factories中的类创建的。 然后,类型ApplicationContextInitializer的所有@Beans会在启动前被添加到主SpringApplication。
2.6 自定义引导属性源
引导过程添加的外部配置的默认属性源是Spring Cloud Config Server,但可以通过将类型PropertySourceLocator的bean添加到引导上下文(通过spring.factories)来添加其他源。例如,你可以从其他服务器或数据库插入其他属性。
作为一个例子,请参考下面自定义的定位器:
@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提供的属性源,因此可以通过使用它们来查找特定于此环境的属性源(例如,通过在spring.application.name上键入它,就像在默认的Spring Cloud Config Server 属性源定位器所做的那样)。如果你在其中创建包含此类的jar,然后添加包含以下内容的META-INF/spring.factories,则customProperty、PropertySource将出现在其类路径中包含该jar的任何应用程序中:
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
2.7 日志配置
如果要使用Spring Boot 配置日志设置,则应该将此设置放在bootstrap.[yml|properties] 如果你希望它适用于所有事件。
要使Spring Cloud 正确初始化日志记录配置,你不能使用自定义前缀。例如,初始化日志记录系统时,Spring Cloud 将无法识别custom.loggin.logpath。
2.8 环境变化
应用程序侦听EnvironmentChangeEvent 并以几种标准方式对更改做出反应(用户可以正常的方式将其他ApplicationListener添加为@Beans)。当观察到EnvironmentChangeEvent时,它有一个已更改的键值列表,应用程序使用它们:
·在上下文中绑定任何@ConfigurationProperties bean
·为logging.level.* 中的任何属性设置日志级别。
请注意,默认情况下,Config Client 不会轮询环境中的改变。通常,我们不建议使用这种方法来检测更改(尽管你可以使用@Schedule注解进行设置)。如果你有一个扩展的可以端应用程序,最好将EnvironmentChangeEvent广播到所有实例,而不是让他们轮询更改(例如,通过使用Spring Cloud Bus)。
EnvironmentChangeEvent涵盖了一大类刷新用例,只要你可以实际更改环境并发布事件即可。请注意,这些API是共有的并且是Sping核心的一部分。你可以通过访问/configprops端点(一个正常的Spring Boot Actuator 功能)来验证更改是否绑定到@ConfigurationProperties bean。例如,DataSource可以在运行时更改其maxPoolSize(Spring Boot创建的默认DataSource是@ConfigurationProperties bean)并动态增加容量。重新绑定@ConfigurationProperties不包括另一大类需要你基于刷新的更多控制以及基于整个ApplicationContext的原子变更的用例。为了解决这些问题,我们有@RefreshScope。
2.9 刷新范围
当配置发生变化时,标记为@RefreshScope 的Spring @Bean 会得到特殊处理。此功能解决了只有在初始化时才会注入其配置的有状态bean的问题。例如,如果数据源在通过环境更改数据库URL时具有打开的链接,那么你可能希望这些链接的持有者能够完成它们正在执行的操作,然后,下次在池中借用某个链接时,它会获得一个带有新URL的连接。
有时,甚至可能必须在某些只能初始化一次的bean上应用@RefreshScope注解。如果bean是“不可变的”,则必须使用@RefreshScope注解bean,或者在属性键spring.cloud.refresh.extra-refreshable下指定classname。
刷新范围bean是在使用它们时初始化的惰性代理(即,在调用方法时),并且范围充当初始化值的缓存。要强制bean在下一个方法调用上重新初始化,必须使其缓存条目无效。
RefreshScope是上下文的一个bean,它有一个公有的refreshAll()方法通过清除目标缓存来刷新作用域中的所有bean。/refresh 端点暴露此功能(基于HTTP或JMX)。要按名称刷新单个bean,还有一个refresh(String) 方法。
要暴露/refresh端点,你需要将一下配置添加到你的应用程序:
management:
endpoints:
web:
exposure:
include: refresh
@RefreshScope(在技术上)在@Configuration类上工作,但他可能会导致令人惊讶的行为。例如,它并不意味着该类中所定义的所有@Beans本身都在@RefreshScope中。具体来说,依赖于那些bean的任何东西都不能依赖于在启动刷新是更新它们,除非它本身在@RefreshScope中。在这种情况下,它会在刷新是重建,并重新注入其依赖项。此时,它们将从刷新的@Configuration重新初始化。
2.10 加密解密
Spring Cloud 有一个Environment预处理器,用于在本地解密属性值。它遵循与Config Server相同的规则,并且通过加密有相同的外部配置。因此,你可以使用{cipher}*形式的加密值。并且只要有有效密钥,它们就会在主程序上下文获取环境设置之前被解密。要在应用程序中使用加密功能,你需要在此类路径中包含Spring Security RSA (Maven坐标:“org.springframework.security:spring-security-rsa”),并且你的JVM还需要全面的JCE扩展。
如果由于“非法密钥大小”而导致异常并且你使用Sun的JDK,则需要安装Java Cryptograpy Extension(JCE) Unlimited Strength Jurisdiction Policy Files。有关更多信息,请参阅一下链接:
·Java 6 JCE
·Java 7 JCE
·Java 8 JCE
无论你使用哪种版本的JRE/JDK x64/x86,都要将文件解压到JDK/jre/lib/security 文件夹中。
2.11 端点
对于Spring Boot Actuator 应用程序,可以使用一些 其他管理端点。你可以使用:
·POST 到 /actuator/env 以更新环境并重新绑定@ConfigurationProperties 和日志级别。
·/actuator/refresh 重新加载引导上下文并刷新@RefreshScope bean。
·/actuator/restart 关闭ApplicationContext 并重新启动它(默认情况下禁用)。
·/actuator/pause 和 /actuator/resume 用于调用Lifecycle方法(在ApplicationContext上的stop()和start())。