Spring Cloud技术指南--第一部分

第一部分 Cloud Native 应用

Cloud Native 是一种持续交付和价值驱动开发领域的最佳实践。
Spring Cloud基于Spring Boot,主要基于两个库:Spring Cloud Context和Spring Cloud Commons
Spring Cloud Context为ApplicationContext提供公共组件和特殊的服务,例如:bootstrap context启动上下文、encryption加密、refresh scope作用域刷新、environment endpoints环境定制等
Spring Cloud Commons是一组对相关组件的高度抽象类集合,例如:Spring Cloud Netiflix vs Spring Cloud Consul
如果你使用Sun‘s JDK时候’碰到了“Illegal key size”异常,你需要安装Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files.下载地址:

2.Spring Cloud Context:Application Context Services应用上下文服务

Spring Boot有通用的默认构建配置,比如:通用的配置文件、服务管理、监控任务管理等,Spring Cloud在这些基础之上又提供了一些有用的特性。

2.1 The Bootstrap Application Context 引用应用上下文

Spring Cloud通过创建一个bootstrap上下文来运行,这个上下文是应用程序的父上下文环境,它负责加载外部配置资源文件中的配置属性,且可以对配置属性进行解密。这个上下文是一个共享Environment,它是任何Spring应用程序的外部属性的来源。它有较高的优先级,因此默认情况下不能被本地配置重写覆盖。

它使用约定的配置文件,它的优先级高于主配置文件,主配置文件时application.yml(application.properties),而它的配置文件是bootstrap.yml(bootstrap.properties),下面是一个示例:
bootstrap.yml.

spring:
  application:
    name: foo
  cloud:
    config:
      uri: ${SPRING_CONFIG_URI:http://localhost:8888}

如果你的程序需要一些特殊的配置需要从配置服务器中读取,建议设置spring.application.name这个属性(在bootstrap.ymlapplication.yml)
可以通过设置spring.cloud.bootstrap.endabled=false来禁用引导的相关处理

2.2 Application Context Hierarchies 应用上下文层次结构

如果你是从SpringApplication或者SpringApplicationBuilder来构建应用上下文,则会将Bootstrap Context设置为顶层上下文。这是Spring的功能,即它会从父上下文环境继承属性源和配置文件,因此与不使用Spring Cloud Config构建相同上下文相比,main context将包含其他属性源,下面是这些属性源:

  • bootstrap:当在Bootstrap context中出现PropertySourceLocators,则可选CompositePropertySource显示为高优先级,并且具有非空属性。比如从Spring Cloud Config Server服务器的属性。参考"below"学习自定义属性源内容
  • applicationConfig:[classpath:bootstrap.yml],假如你有bootstrap.yml/bootstrap.properties,这个文件中的属性是用来配置引导上下文的,这个配置的优先级比application.yml/application.properties以及创建Spring Boot的其他属性源的优先级低,所以在它的属性会被覆盖。
    因为启动加载有先后顺序,但是需注意的是,因为bootstrap.yml,所以它的优先级比较低,使用的是默认的配置
    你可以通过简单的设置来扩展ApplicationContext,比如使用接口,或者使用SpringApplicationBuilder中的一些方便的方法(parent()child()sibling())。层次结构中的每个上下文都有自己的bootstrap属性源(可能为空),这样可以避免子级的值覆盖父级的值。层次结构中的每个上下文原则上也可以有自己的spring.application.name,因此如果有Config server上,则就有不同的远程属性源。普通的Spring 应用程序上下文行为规则适用于属性解析:子环境中的属性通过名称和属性源名称覆盖父环境中的属性。
    请注意:SpringApplicationBuilder允许您在整个层次结构中共享Environment,但是这个不是默认值。因此同层级的上下文环境不需要具有相同的配置文件或属性资源,他们将共享父上下文的
2.3 Changing the Location of Bootstrap Properties 更改引导位置

可以通过spring.cloud.bootstrap.name(默认是bootstrap)或spring.cloud.bootstrap.location(默认是空)来指定bootstrap.yml/bootstrap.properties文件的位置,例如,在系统属性中的spring.config.*,它们用来设置引导ApplicatoinContext,如果你通过spring.profiles.active或者EnvironmentAPI激活了"环境"配置,这些在指定的profile中的属性就会被加载,比如你可以自定义bootstrap-development.properties来激活developement环境

2.4 Overriding the Values of Remote Properties覆盖远程配置的值

默认情况下从远程配置服务器加载的属性值是不能被覆盖的,但是如果你想要使用本地的系统属性覆盖它们,需要使用spring.cloud.config.allowOverride=true来激活(在本地设置不起作用),一旦设置了该值,就可以更细化的控制远程和本地的属性值,spring.cloud.config.overrideNone=true设置覆盖本地属性源,spring.cloud.config.overrideSystemProperties=false则只覆盖系统属性和环境变量被远程设置覆盖,但是本地配置的属性不会被覆盖

2.5 Customizing the Bootstrap Configuration

通过添加/META-INF/spring.factories文件,在org.springframework.cloud.bootstrap.BootstrapConfiguration下设置加载在项目中自定义并添加了@Configuration类来指定加载到上下文中的配置。任何你想在系统启动时就自动注入到上下文中的bean都可以给它添加@Bean注解,类型是ApplicationContextInitializer,可以通过@Order注解来定制它们的加载顺序,默认的顺序是’last’
要注意不要将不需要的类添加到上下文中,如果必要建议单独定义包名
引导过程会将自定义的实例注入到SpringApplication,其中spring.factories会被bootstrap context创建,所有@Bean注解的会被ApplicationContextInitializer注入,它会早于spring.factories创建。

2.6 Customizing the Bootstrap Property Sources

默认是加载配置服务器上配置资源,你也可以通过PropertySourceLocator(在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"));
    }

}

EnvironmentApplicationContext自动创建的,它为我们提供外部配置来源。
如果你的jar文件中包含有/META-INF/spring.factories,里面包含有
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
那么customProperty的配置会在jar所在的classpath下共享

2.7 Environment Changes改变环境

程序通过ApplicationListeners下的多个方法监听EnvironmentChangeEvent事件,当监听到EnvironmentChangeEvent改变,就会触发以下动作:

  • 重新绑定有@ConfigurationProperties注解的beans
  • 设置日志级别
    注意:配置客户端默认不会轮询Environment的改变,而且我们不推荐使用轮询的方法检测改变(尽管你可以使用@Scheduled注解来实现),建议使用广播的方式来监听EnvironmentChangeEvent,这样所有的实例都可以获得最新的变更,例如使用Spring Cloud Bus组件
    环境变更会刷新大量的实例,可以通过测试来确保是否成功,如果你想改变其中一部分的属性,比如数据库的连接相关属性,就可以使用@RefreshScope注解
2.8 Refresh Scope刷新作用域

如果@Bean注解的类上有@RefreshScope注解,它就会在配置更改的时候被特殊对待。就是说它只会对影响的属性敏感。比如我们的数据库连接更新,只会重新加载对应的配置,不会影响其他的属性。

RefreshScop有一个公共方法refreshAll()来触发所有beans清空缓存,刷新配置。也有一个refresh(string)方法指定刷新bean的属性,它是通过HTTP或者JMX来触发/refresh实现的

2.9 Encryption and Decryption 加密解密

如果你在配置服务器上设置了encrypt.*,你就可以用{cipher}*来加密键的值,而且它们会在被客户端获取时候自动解密。
加密解密使用了Spring Secruity RSA,所以你需要把它们的依赖添加到classpath中,maven中需要添加spring-security依赖。而且需要完整的JCE支持,
如果你得到了Illegal key size,说明你的JCE不是Java Cryptography Extension(JCE) Unlimited Strength Jurisdiction Policy Files版,下面是下载地址

2.10 Endpoints端点

Spring Boot Actuator应用集成了很多的管理端点:

  • /env来重新绑定属性和日志级别
  • /refresh重新引导上下文和刷新beans的作用域
  • /restart重新启动ApplicationContext
  • /pause/resume调用生命周期中的(stop()start())方法来暂停和重启Application

3.Spring Cloud Commons:Common Abstractions 通用抽象

Spring Cloud Commons对像服务发现、负载均衡、断路器等做了通用抽象,这样方便Spring Cloud Clients来自定义使用的实现,比如服务发现可以使用Eureka或者Consul

3.1 @EnableDiscoveryClient服务发现客户端

你可以在/META-INF/spring.factories中自定义你的服务发现组件和配置信息,使用键org.springframework.cloud.client.discovery.EnableDiscoveryClient来配置,可以使用的服务发现实现有:Spring Cloud Netflix EurekaSpring Cloud Consul DiscoverySpring Cloud Zookeeper Discovery
默认情况下DiscoveryClient会被自动注册到远程的服务发现服务器端,你可以在@EnableDiscoveryClient中设置autoRegister=false来禁用它

3.2 ServiceRegistry 服务注册

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的实现都会有它自己的注册实现逻辑

3.2.1 ServiceRegistry Auto-Registration自动服务注册

默认情况下ServiceRegistry自动注册正在运行的服务,有两种方法禁止这种动作

  • @EnableDiscoveryClient(autoRegister=false)
  • spring.cloud.service-registry.auto-registration.enabled=false
3.2.2 Service Registry Actuator Endpoint 注册执行端点

/service-registry/service-registry/instance-statusGET请求会返回Registration的状态。POST请求会返回字符串对象类型

3.3 Spring RestTemplate as Load Balancer Client 负载均衡请求模板

RestTemplate由ribbon自动配置,使用@LoadBalanced注解来创建一个负载均衡的请求模板对象RestTemplate

这个版本的Spring Cloud中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;
    }
}
3.3.1 Retrying Failed Requests失败重试

负载均衡的RestTemplate可以配置失败请求,默认情况下是未配置的,你可以添加Spring Retry到你的classpath,使它有失败重试的能力。
如果你想禁止Spring Retry的重试机制就设置spring.cloud.loadbalancer.retry.enabled=false,这个属性可以用在client.ribbon.MaxAutoRetriesclient.ribbon.MaxAutoRetriesNextServerclient.ribbon.OkToRetryOnAllOperations,参考Ribbon文档

3.4 Multiple RestTemplate objects多重RestTemplate对象

如果你不想使用负载均衡,可以仅仅创建一个RestTemplate并注入就可以了,要使用负载均衡就在Bean上添加@LoadBalanced注解
注意@Primary,这个注解是指定接口的实现的,用来消除不合适的自动注入

@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

3.5 Ignore Network Interfaces忽略网络接口

如果服务器有多个网卡,有时候需要忽略掉其中的几个,下面的配置示例会忽略"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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值