Spring Cloud

目录

Spring Cloud Context

Bootstrap Context

Application Context 层级

改变本地Bootstrap属性

覆盖远程属性值

自定义boostrap配置

自定义boostrap PropertySource

 Environment 改变

Refresh Scope

Endpoints

Spring Cloud Commons

@EnableDiscoveryClient

健康指示器

服务发现实例排序

服务注册

自动注册

Actuator Endpoint

负载均衡

失败请求重试

Multiple RestTemplate objects


spring cloud 中的许多特性都已经被spring boot实现,其他一些特性主要是通过spring cloud contextspring cloud commons来实现的。spring cloud context提供了一些常用的公共类以及spring cloud 特有的服务(bootstrap context, encryption, refresh scope, and environment endpoints);spring cloud commons提供了一系列的抽象类和公共类,供spring cloud不同的实现组件去使用(such as Spring Cloud Netflix and Spring Cloud Consul).。

Spring Cloud Context

通过spring boot 构建 spring application已经很方便了,她还提供了一些监控、管理相关的endpoint; 由于 spring cloud 是建立在spring boot基础之上的,所以spring boot 的功能spring cloud都满足,此外还提供了一些特有的特性,这些特性可能在所有的spring cloud组件中都会(或者偶尔)使用到。

Bootstrap Context

spring cloud 应用中创建一个 bootstrap context,她是作为了主应用的 parent context ;主要负责从外部资源(主要指配置中心)加载配置以及再解码本地的配置文件。appliction context 和 bootstrap context 共享了相同Environment. 默认情况下,bootstrap properties(从配置中心加载的属性) 有更高的优先级,所以它们不能被本地的配置所覆盖。

bootstrap context使用了和主应用的 context 不同的配置方式,使用的是 bootstrap.yml 而不是 application.yml,这主要是为了保证两个context的配置可以很好的分离。如果需要禁用 bootstrap context ,我们可以设置环境变量spring.cloud.bootstrap.enabled=false

Application Context 层级

如果你通过SpringApplication 或者 SpringApplicationBuilder来构建你的应用,那么Bootstrap context 将会作为application context 的 parent context。子容器会继承从父容器中的属性,新增的属性有:

  • bootstrap

如果在Bootstrap context有任何非空的属性,那么这些属性的优先级都更高,比如说从 spring cloud config 加载的配置,默认优先级就比本地配置高。

  • applicationConfig

如果你配置bootstrap.yml, 那么bootstrap.yml中的属性会用来配置 Bootstrap context;当Bootstrap context配置完成后就会把这些属性添加到application context 中,这些属性的优先级会比配置在application.yml 中的低
由于bootstrap.yml 的优先级比较低,所以可以用来设置一些属性的默认值。

spring cloud 允许你扩展ApplicationContext ,例如可以使用 ApplicationContext已有的接口或者使用SpringApplicationBuilder提供的方法(parent(), child() and sibling());这个bootstrap context是所有容器的父容器。

改变本地Bootstrap属性

能够通过设置环境变量spring.cloud.bootstrap.name(默认是bootstrap)配置引导文件(bootstrap.yml)的名字,通过 spring.cloud.bootstrap.location(默认是空)配置路径。
例如在环境变量中配置:

spring.cloud.bootstrap.name=start
spring.cloud.bootstrap.location=classpath:/test/

覆盖远程属性值

通过bootstrap context从远程添加的属性默认情况下是不能被本地配置所覆盖的。如果你想要使用系统变量或者配置文件来覆盖远程的属性,在远程配置中设置属性spring.cloud.config.allowOverride=true(注意:在本地文件中设置是无效的)来授权,同时需要配置哪些可以覆盖:

spring.cloud.config.overrideNone=true                            #  本地任何属性都可以覆盖
spring.cloud.config.overrideSystemProperties=false       #环境变量,命令行参数可以覆盖,本地配置文件除外
 

自定义boostrap配置

bootstrap context通过/META-INF/spring.factories配置的类初始化的所有的Bean都会在SpingApplicatin启动前加入到它的上下文里去。spring.factories中key 使用 org.springframework.cloud.bootstrap.BootstrapConfiguration, 所有需要用来配置bootstrap context的配置类用逗号分隔;可以通过@Order来更改初始化序列,默认是”last

首先使用spring.factories中配置的类来创建bootstrap context,然后所有使用@Bean注解的ApplicationContextInitializer将会被添加 main application context。

自定义boostrap PropertySource

默认情况下外部化配置都是从配置中心获取属性,但是也可以通过实现PropertySourceLocator来实现添加属性到bootstrap context(需要把实现类添加到spring.factories);比如可以从不同的数据库或者服务器获取配置。

 Environment 改变

应用可以监听EnvironmentChangeEvent来响应环境变量被改变的事件。一旦EnvironmentChangeEvent事件被触发,应用程序将会做这些事情:

  • 重新绑定使用了@ConfigurationProperties的类
  • 根据logging.level.*来设置应用的日志级别

默认情况下,Config Client不轮询Environment的改变。一般情况,不建议使用这种方式来监测变化(虽然你可以通过@Scheduled注解来设置)。对于可扩展的应用程序,使用广播EnvironmentChangeEvent到所有实例的方式,好过轮询的方式。(比如使用Spring Cloud Bus项目)。

Refresh Scope

当有配置发生变化的时候,使用了@RefreshScope的类将会被处理;这个特性解决了有状态bean只能在初始化注入配置的问题。例如:比如,在使用DataSource获得一个数据库连接的是时候,当通过Environment修改数据库连接字符串的时候,我们可以通过执行@RefreshScope来根据修改的配置获取一个新的URL的连接。

Refresh scope beans是延迟初始化的,在第一次使用的时候才初始化,这个scope充当了初始值的缓存;为了在下一次调用时强制初始化,必须使缓存无效。

RefreshScope在容器中是一个bean, 提供了一个public方法refreshAll(),通过清理当前的缓存来刷新,可以通过访问/refresh来触发刷新;也可以使用bean的名字来刷新refresh(String),要使用还需要暴露出这个endpoint

Endpoints

相对于Spring Boot Actuator的应用,添加了一些管理端点:

  • POST /actuator/env :更新Environment重新加载@ConfigurationProperties和日志级别
  • /actuator/refresh: 重新初始化添加了@RefreshScope 的bean
  • /actuator/restart: 重启初始化ApplicationContext,重启 (默认是禁用的)
  • /actuator/pause: 调用ApplicationContext生命周期的方法stop()和start()

如果禁用了/actuator/restart,那么/actuator/pause和/actuator/resume都会被禁用
 

Spring Cloud Commons

服务发现、负载平衡和断路器等通用的模型,本身是一个抽象层,可以被所有Spring Cloud组件独立的实现,例如服务发现有具体的实现Eureka、Consul。

@EnableDiscoveryClient

Spring Cloud Commons 提供了@EnableDiscoveryClient这个注解,主要的作用是在META-INF/spring.factories寻找DiscoveryClient的实现类;实现了DiscoveryClient的类都会配置在spring.factories中,添加key为 org.springframework.cloud.client.discovery.EnableDiscoveryClient

@EnableDiscoveryClient现在已经不是必须的了,只要DiscoveryClient的实现类在classpath就OK

健康指示器

springboot 中提供了一个检查检查的接口HealthIndicator, DiscoveryClient能够通过实现DiscoveryHealthIndicator来做健康检查。设置spring.cloud.discovery.client.composite-indicator.enabled=false来禁用这种混和的健康检查;DiscoveryClientHealthIndicator通常是自动配置的,设置spring.cloud.discovery.client.health-indicator.enabled=false来禁用;设置spring.cloud.discovery.client.health-indicator.include-description=false来禁用description字段,如果没有禁用,就会一直向上层传递。

服务发现实例排序

DiscoveryClient继承了Ordered; 当你使用多个服务发现的时候这个会很有用,可以定义通过这种方式来按照指定的顺序来从注册中心加载bean。DiscoveryClient默认的order设置的是 0 ;如果想要为你自己实现的DiscoveryClient设置不同的order,仅仅需要覆盖getOrder()。除此之外Spring Cloud提供了配置spring.cloud.{clientIdentifier}.discovery.order来设置order,这其中主要是ConsulDiscoveryClient, EurekaDiscoveryClient, ZookeeperDiscoveryClient;

服务注册

ServiceRegistry接口提供了注册服务register(Registration) 和 取消注册deregister(Registration)的方法。

@Configuration
@EnableDiscoveryClient(autoRegister=false)
public class MyConfiguration {
    private ServiceRegistry registry;

    public MyConfiguration(ServiceRegistry registry) {
        this.registry = registry;
    }

    // called through some external process, such as an event or a custom actuator endpoint
    public void register() {
        Registration registration = constructRegistration();
        this.registry.register(registration);
    }
}

每个ServiceRegistry实现类都会提供一个对应Registry

  • ZookeeperRegistration 使用的 ZookeeperServiceRegistry
  • EurekaRegistration 使用的 EurekaServiceRegistry
  • ConsulRegistration 使用的 ConsulServiceRegistry

自动注册

默认情况下ServiceRegistry的实现类在运行的时候会自动注册服务,两种方式来禁用自动注册服务

@EnableDiscoveryClient(autoRegister=false)
spring.cloud.service-registry.auto-registration.enabled=false

当一个服务自动注册的时会触发两个事件,第一个是InstancePreRegisteredEvent,在注册之前触发;第二个是InstanceRegisteredEvent 在注册完成之后触发;可以使用ApplicationListener来监听这两个事件。

spring.cloud.service-registry.auto-registration.enabled=false的时候就不会触发这两个事件

Actuator Endpoint

Spring Cloud Commons 提供了一个/service-registry 端点,这个endpoint依赖于容器中的Registration。GET请求这个地址将会返回Registration的状态;POST请求这个地址可以修改Registration,这个json格式的body中必须要包含一个status;查询ServiceRegistry的实现类文档来确定status的值;比如Eureka的状态值:UP, DOWN, OUT_OF_SERVICE, UNKNOWN.

负载均衡

创建一个支持负载均衡的RestTemplate,使用@LoadBalanced@Bean注解,像下面的例子:

@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;
    }
}

失败请求重试

RestTemplate可以配置请求失败后的重试策略;默认这个逻辑是禁止的,如果需要可以开启,只需要添加 Spring Retry到classpath; 如果spring retry已经在classpath,你想要禁用这个retry的功能,那么可以配置spring.cloud.loadbalancer.retry.enabled=false

如果想要自定义一个BackOffPolicy,需要创建一个LoadBalancedRetryFactory并覆写方法createBackOffPolicy ; eg:
 

@Configuration
public class MyConfiguration {
    @Bean
    LoadBalancedRetryFactory retryFactory() {
        return new LoadBalancedRetryFactory() {
            @Override
            public BackOffPolicy createBackOffPolicy(String service) {
                return new ExponentialBackOffPolicy();
            }
        };
    }
}

Multiple RestTemplate objects

如何创建一个支持负载均衡的RestTemplate和不支持负载均衡的RestTemplate以及注入的方式?看下面的列子:

@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);
    }
}

@Primary的作用是在使用@Autowired注入时,如果发现了多个类型的bean, 就选择使用了@Primary 的bean

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值