Spring Cloud 学习笔记(一)——入门、特征、配置
[TOC]
0 放在前面
0.1 参考文档
- http://cloud.spring.io/spring-cloud-static/Brixton.SR7/
- https://springcloud.cc/
- http://projects.spring.io/spring-cloud/
0.2 maven配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.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.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
0.3 简介
Spring Cloud为开发人员提供了快速构建分布式系统中的一些通用模式(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式 会话,群集状态)。 分布式系统的协调引出样板模式(boiler plate patterns),并且使用Spring Cloud开发人员可以快速地实现这些模式来启动服务和应用程序。 它们可以在任何分布式环境中正常工作,包括开发人员自己的笔记本电脑,裸机数据中心和受管平台,如Cloud Foundry。
Version: Brixton.SR7
1 特征
Spring Cloud专注于为经典用例和扩展机制提供良好的开箱即用
- 分布式/版本配置
- 服务注册与发现
- 路由选择
- 服务调用
- 负载均衡
- 熔断机制
- 全局锁
- 领导人选举和集群状态
- 分布式消息
2 原生云应用程序
原生云是应用程序开发的一种风格,鼓励在持续交付和价值驱动领域的最佳实践。
Spring Cloud的很多特性是基于Spring Boot的。更多的是由两个库实现:Spring Cloud Context and Spring Cloud Commons。
2.1 Spring Cloud Context: 应用上下文服务
Spring Boot关于使用Spring构建应用有硬性规定:通用的配置文件在固定的位置,通用管理终端,监控任务。建立在这个基础上,Spring Cloud增加了一些额外的特性。
2.1.1 引导应用程序上下文
Spring Cloud会创建一个“bootstrap”的上下文,这是主应用程序的父上下文。对应的配置文件拥有最高优先级,并且,默认不能被本地配置文件覆盖。对应的文件名bootstrap.yml或bootstrap.properties。
可通过设置spring.cloud.bootstrap.enabled=false来禁止bootstrap进程。
2.1.2 应用上下文层级结构
当用SpringApplication或SpringApplicationBuilder创建应用程序上下文时,bootstrap上下文将作为父上下文被添加进去,子上下文将继承父上下文的属性。
子上下文的配置信息可覆盖父上下文的配置信息。
2.1.3 修改Bootstrap配置文件位置
spring.cloud.bootstrap.name(默认是bootstrap),或者spring.cloud.bootstrap.location(默认是空)
2.1.4 覆盖远程配置文件的值
spring.cloud.config.allowOverride=true
spring.cloud.config.overrideNone=true
spring.cloud.config.overrideSystemProperties=false
2.1.5 定制Bootstrap配置
在/META-INF/spring.factories的key为org.springframework.cloud.bootstrap.BootstrapConfiguration,定义了Bootstrap启动的组件。
在主应用程序启动之前,一开始Bootstrap上下文创建在spring.factories文件中的组件,然后是@Beans类型的bean。
2.1.6 定制Bootstrap属性来源
关键点:spring.factories、PropertySourceLocator
2.1.7 环境改变
应用程序可通过EnvironmentChangedEvent监听应用程序并做出响应。
2.1.8 Refresh Scope
Spring的bean被@RefreshScope将做特殊处理,可用于刷新bean的配置信息。
注意
- 需要添加依赖“org.springframework.boot.spring-boot-starter-actuator”
- 目前我只在@Controller测试成功
- 需要自己发送POST请求
/refresh - 修改配置文件即可
2.1.9 加密和解密
Spring Cloud可对配置文件的值进行加密。
如果有"Illegal key size"异常,那么需要安装JCE。
2.1.10 服务点
除了Spring Boot提供的服务点,Spring Cloud也提供了一些服务点用于管理,注意都是POST请求
/env:更新Environment、重新绑定@ConfigurationProperties跟日志级别/refresh重新加载配置文件,刷新标记@RefreshScope的bean/restart重启应用,默认不可用- 生命周期方法:
/pause、/resume
2.2 Spring Cloud Commons:通用抽象
服务发现、负载均衡、熔断机制这种模式为Spring Cloud客户端提供了一个通用的抽象层。
2.2.1 RestTemplate作为负载均衡客户端
通过@Bean跟@LoadBalanced指定RestTemplate。注意URI需要使用虚拟域名(如服务名,不能用域名)。
如下:
@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;
}
}
2.2.2 多个RestTemplate对象
注意@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);
}
}
2.2.3 忽略网络接口
忽略确定名字的服务发现注册,支持正则表达式配置。
3 Spring Cloud Config
Spring Cloud Config提供服务端和客户端在分布式系统中扩展配置。支持不同环境的配置(开发、测试、生产)。使用Git做默认配置后端,可支持配置环境打版本标签。
3.1 快速开始
可通过IDE运行或maven运行。
默认加载property资源的策略是克隆一个git仓库(at spring.cloud.config.server.git.uri')。
HTTP服务资源的构成:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
application是SpringApplication的spring.config.name,(一般来说'application'是一个常规的Spring Boot应用),profile是一个active的profile(或者逗号分隔的属性列表),label是一个可选的git标签(默认为"master")。
3.1.1 客户端示例
创建以Spring Boot应用即可,添加依赖“org.springframework.cloud:spring-cloud-starter-config”。
配置application.properties,注意URL为配置服务端的地址
spring.cloud.config.uri: http://myconfigserver.com
3.2 Spring Cloud Config 服务端
针对系统外的配置项(如name-value对或相同功能的YAML内容),该服务器提供了基于资源的HTTP接口。使用@EnableConfigServer注解,该服务器可以很容易的被嵌入到Spring Boot 系统中。使用该注解之后该应用系统就是一个配置服务器。
@SpringBootApplication
@EnableConfigServer
public class ConfigApplicion {
public static void main(String[] args) throws Exception {
SpringApplication.run(ConfigApplicion.class, args);
}
}
3.2.1 资源库环境
- {application} 对应客户端的"spring.application.name"属性
- {profile} 对应客户端的 "spring.profiles.active"属性(逗号分隔的列表)
- {label} 对应服务端属性,这个属性能标示一组配置文件的版本
如果配置库是基于文件的,服务器将从application.yml和foo.yml中创建一个Environment对象。高优先级的配置优先转成Environment对象中的PropertySource。
3.2.1.1 Git后端
默认的EnvironmentRepository是用Git后端进行实现的,Git后端对于管理升级和物理环境是很方便的,对审计配置变更也很方便。也可以file:前缀从本地配置库中读取数据。
这个配置库的实现通过映射HTTP资源的{label}参数作为git label(提交id,分支名称或tag)。如果git分支或tag的名称包含一个斜杠 ("/"),此时HTTP URL中的label需要使用特殊字符串"(_)"来替代(为了避免与其他URL路径相互混淆)。如果使用了命令行客户端如 curl,请谨慎处理URL中的括号(例如:在shell下请使用引号''来转义它们)。
Git URI占位符
Spring Cloud Config Server支持git库URL中包含针对{application}和 {profile}的占位符(如果你需要,{label}也可包含占位符, 不过要牢记的是任何情况下label只指git的label)。所以,你可以很容易的支持“一个应用系统一个配置库”策略或“一个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}不能匹配任何表达式,那么将使用“spring.cloud.config.server.git.uri”对应的值。在上例子中,对于 "simple" 配置库, 匹配模式是simple/* (也就说,无论profile是什么,它只匹配application名称为“simple”的应用系统)。“local”库匹配所有application名称以“local”开头任何应用系统,不管profiles是什么(来实现覆盖因没有配置对profile的匹配规则,“/*”后缀会被自动的增加到任何的匹配表达式中)。
Git搜索路径中的占位符
spring.cloud.config.server.git.searchPaths
3.2.1.2 版本控制后端文件系统使用
伴随着版本控制系统作为后端(git、svn),文件都会被check out或clone 到本地文件系统中。默认这些文件会被放置到以config-repo-为前缀的系统临时目录中。在Linux上,譬如应该是/tmp/config-repo-<randomid>目录。有些操作系统routinely clean out放到临时目录中,这会导致不可预知的问题出现。为了避免这个问题,通过设置spring.cloud.config.server.git.basedir或spring.cloud.config.server.svn.basedir参数值为非系统临时目录。
3.2.1.3 文件系统后端
使用本地加载配置文件。
需要配置:spring.cloud.config.server.native.searchLocations跟spring.profiles.active=native。
路径配置格式:classpath:/, classpath:/config,file:./, file:./config。
3.2.1.4 共享配置给所有应用
基于文件的资源库
在基于文件的资源库中(i.e. git, svn and native),这样的文件名application*命名的资源在所有的客户端都是共享的(如 application.properties, application.yml, application-*.properties,etc.)。
属性覆盖
“spring.cloud.config.server.overrides”添加一个Map类型的name-value对来实现覆盖。
例如
spring:
cloud:
config:
server:
overrides:
foo: bar
会使所有的配置客户端应用程序读取foo=bar到他们自己配置参数中。
3.2.2 健康指示器
通过这个指示器能够检查已经配置的EnvironmentRepository是否正常运行。
通过设置spring.cloud.config.server.health.enabled=false参数来禁用健康指示器。
3.2.3 安全
你可以自由选择任何你觉得合理的方式来保护你的Config Server(从物理网络安全到OAuth2 令牌),同时使用Spring Security和Spring Boot 能使你做更多其他有用的事情。
为了使用默认的Spring Boot HTTP Basic 安全,只需要把Spring Security 增加到classpath中(如org.springframework.boot.spring-boot-starter-security)。默认的用户名是“user”,对应的会生成一个随机密码,这种情况在实际使用中并没有意义,一般建议配置一个密码(通过 security.user.password属性进行配置)并对这个密码进行加密。
3.2.4 加密与解密
如果远程属性包含加密内容(以{cipher}开头),这些值将在通过HTTP传递到客户端之前被解密。
使用略
3.2.5 密钥管理
配置服务可以使用对称(共享)密钥或者非对称密钥(RSA密钥对)。
使用略
3.2.6 创建一个测试密钥库
3.2.7 使用多密钥和循环密钥
3.2.8 加密属性服务
3.3 可替换格式服务
配置文件可加后缀".yml"、".yaml"、".properties"
3.4 文本解释服务
/{name}/{profile}/{label}/{path}
3.5 嵌入配置服务器
一般配置服务运行在单独的应用里面,只要使用注解@EnableConfigServer即可嵌入到其他应用。
3.6 推送通知和总线
添加依赖spring-cloud-config-monitor,激活Spring Cloud 总线,/monitor端点即可用。
当webhook激活,针对应用程序可能已经变化了的,配置服务端将发送一个RefreshRemoteApplicationEvent。
3.7 客户端配置
3.7.1 配置第一次引导
通过spring.cloud.config.uri属性配置Config Server地址
3.7.2 发现第一次引导
如果用的是Netflix,则用eureka.client.serviceUrl.defaultZone进行配置。
3.7.3 配置客户端快速失败
在一些例子里面,可能希望在没有连接配置服务端时直接启动失败。可通过spring.cloud.config.failFast=true进行配置。
3.7.4 配置客户端重试
添加依赖spring-retry、spring-boot-starter-aop,设置spring.cloud.config.failFast=true。默认的是6次重试,初始补偿间隔是1000ms,后续补偿为1.1指数乘数,可通过spring.cloud.config.retry.*配置进行修改。
3.7.5 定位远程配置资源
路径:/{name}/{profile}/{label}
- "name" = ${spring.application.name}
- "profile" = ${spring.profiles.active} (actually Environment.getActiveProfiles())
- "label" = "master"
label对于回滚到之前的版本很有用。
3.7.6 安全
通过spring.cloud.config.password、spring.cloud.config.username进行配置。
4 Spring Cloud Netflix
Spring Cloud 通过自动配置和绑定到Spring环境和其他Spring编程模型惯例,为Spring Boot应用程序提供Netflix OSS集成。 通过几个简单的注释,可以快速启用和配置应用程序中的常见功能模块,并使用久经考验的Netflix组件构建大型分布式系统。 提供的功能模块包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载均衡(Ribbon)。
4.1 服务发现:Eureka客户端
服务发现是microservice基础架构的关键原则之一。Eureka是Netflix服务发现的一种服务和客户端。
4.1.1 注册到Eureka
当一个客户端注册到Eureka,它提供关于自己的元数据(诸如主机和端口,健康指标URL,首页等)Eureka通过一个服务从各个实例接收心跳信息。如果心跳接收失败超过配置的时间,实例将会正常从注册里面移除。
可以使用@EnableEurekaClient或@EnableDiscoveryClient注解。
配置eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/属性,注意修改URL地址。
确保spring.application.name有默认值。
注:@EnableEurekaClient只能用于Eureka,@EnableDiscoveryClient能用于zookeeper等其他注册组件。
@EnableEurekaClient使其成为Eureka实例(被其他服务发现)和客户端(能发现其他服务)注册到应用里面。可通过eureka.instance.*进行相关配置的修改。
4.1.2 对Eureka服务的身份验证
如果其中一个eureka.client.serviceUrl.defaultZone的url已经把凭证嵌入到它里面,那么HTTP基本的身份验证将会被自动添加到你的eureka客户端(curl风格,如http://user:password@localhost:8761/eureka)。 对于更复杂的需求,可以创建一个带“@Bean”注解的“DiscoveryClientOptionalArgs”类型并且为它注入“ClientFilter”实例。
4.1.3 健康指标和状态页面
健康指标和状态页面分别对应一个Eureka实例的“/health”和“/info”。
4.1.4 注册一个安全应用
若要用HTTPS,需要设置两个标记,分别是EurekaInstanceConfig,即eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]。
4.1.5 Eureka 健康检查
默认情况下,Eureka使用客户端心跳来确定一个客户端是否活着(状态为“UP”)。
4.1.6 Eureka给客户端和实例的元数据
有标准的元数据,如主机名、IP地址、端口号、状态页面和健康检查。额外的元数据可以被添加到实例注册在eureka.instance.metadataMap里面。
在 Cloudfoundry 使用 Eureka
Cloudfoundry有总的路由,所有在同个应用的实例有相同的主机名。
在AWS上使用Eureka
定制EurekaInstanceConfigBean
修改Eureka实例ID
通过eureka.instance.instanceId进行配置。
4.1.7 使用EurekaClient
使用@EnableDiscoveryClient(或@EnableEurekaClient),使它从Eureka Server发现服务实例。
注:不要在@PostConstruct方法或@Scheduled方法使用EurekaClient(或任何ApplicationContext还没被启动的地方)。
4.1.8 代替原生的Netflix EurekaClient
Spring Cloud已经支持Feign(一个REST客户端构建)跟Spring RestTemplate(使用逻辑Eureka服务标识符(VIPs)代替物理的URL)。
4.1.9 为什么注册一个服务这么慢?
实例默认与注册中心持续30秒的周期心跳(通过客户的serviceUrl)。当实例、服务端和客户端全都在它们的缓存里面拥有相同的元数据(这可能还需要3次心跳),那么服务对于客户端的discovery将变为不可用。可通过eureka.instance.leaseRenewalIntervalInSeconds这个修改配置,可以加快这一进程的客户端连接到其他服务。
4.2 服务发现: Eureka Server
例子,添加依赖spring-cloud-starter-eureka-server
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
服务端有一个带UI的首页,HTTP API端点在/eureka/*下提供标准的Eureka功能。
4.2.1 高可用
Eureka服务端没有后台存储,但是服务实例在注册里面全都得发送心跳去保持注册更新(在内存里操作)客户端们也有一份内存缓存着eureka的注册信息。
4.2.2 标准模式
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
4.2.3 节点感知
运行多个Eureka Servers。
Eureka甚至可以更有弹性和可用的运行多个实例,并让他们互相注册。事实上,这也是默认的行为,因此所有你需要让它工作的,只要添加一个有效的节点serviceUrl,例如:
---
spring:
profiles: peer1
eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2/eureka/
---
spring:
profiles: peer2
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1/eureka/
然后通过不同的“profile”进行运行不同的Eureka Server。
4.2.4 IP偏好
设置eureka.instance.preferIpAddress=true使应用注册到eureka的是IP地址而不是主机名。
4.3 断路器:Hystrix
Netflix创建了一个库实现断路器模式,名为Hystrix。一个低水平的服务群中一个服务挂掉会给用户导致级联失效的。当调用一个特定的服务达到一定阈值(在Hystrix里默认是5秒内20个失败),断路器开启并且调用没有成功的。开发人员能够提供错误原因和开启一个断路由回调。
例子,需添加依赖org.springframework.cloud.spring-cloud-starter-hystrix
@SpringBootApplication
@EnableCircuitBreaker
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
@Component
public class StoreIntegration {
@HystrixCommand(fallbackMethod = "defaultStores")
public Object getStores(Map<String, Object> parameters) {
//do stuff that might fail
}
public Object defaultStores(Map<String, Object> parameters) {
return /* something useful */;
}
}
经测试,失败就直接调用defaultStores()方法了。
4.3.1 传播安全上下文或使用 Spring Scopes
如果你想一些线程的本地的上下文传播到一个@HystrixCommand,默认声明将不会工作,因为他在线程池里执行命令。(在超时的情况下)。你可以切换Hystrix去使用同个线程让调用者使用一些配置,或直接在注解中,让它去使用不同的“隔离策略”。举例:
@HystrixCommand(fallbackMethod = "stubMyService",
commandProperties = {
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
}
)
...
如果你使用@SessionScope或@RequestScope同样适用。你会知道你要这么做,因为一个runtime异常说他不能找到作用域上下文。
4.3.2 健康指标
连接的断路器的状态也暴露在应用程序的/health端点中。
4.3.3 Hystrix 指标流
添加依赖org.springframework.boot.spring-boot-starter-actuator,使/hystrix.stream流作为一个管理端点。
4.4 断路器: Hystrix仪表盘
Hystrix的主要作用是会采集每一个HystrixCommand的信息指标,把每一个断路器的信息指标显示的Hystrix仪表盘上。
环境需要
- 添加依赖
org.springframework.cloud.spring-cloud-starter-hystrix-dashboard - 主类上注解
@EnableHystrixDashboard - 访问
/hystrix - 填写链接
http://host:port/hystrix.stream
4.4.1 Turbine
略
4.4.2 Turbine Stream
略
4.5 客户端负载均衡器:Ribbon
Ribbon是一个客户端负载均衡器,有很多控制HTTP和TCP客户端的行为,可使用@FeignClient注解。
4.5.1 自定义Ribbon客户端
略
4.5.2 在Eureka中使用Ribbon
略
4.5.3 示例: 没有Eureka时如何使用Ribbon
略
4.5.4 示例:禁用Eureka使用Ribbon
略
4.5.5 直接使用Ribbon的API
public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}
4.6 声明REST客户端:Feign
略
4.7 外部配置:Archaius
略
4.8 路由和过滤器:Zuul
Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
- 认证
- Insights
- 压力测试
- 金丝雀测试(Canary Testing)
- 动态路由
- 服务迁移
- 负载削减
- 安全
- 静态响应处理
- 主动/主动交换管理
4.8.1 嵌入Zuul反向代理
Spring Cloud创建了一个嵌入式Zuul代理来缓和急需一个UI应用程序来代理调用一个或多个后端服务的通用需求,这个功能对于代理前端需要访问的后端服务非常有用,避免了所有后端服务需要关心管理CORS和认证的问题。
。
在Spring Boot主函数上通过注解@EnableZuulProxy来开启。
4.8.2 Cookies和敏感HTTP头
4.8.3 路由Endpoint
使用@EnableZuulProxy同时引入了Spring Boot Actuator,默认将增加一个endpoint,提供http服务的/routes。
4.8.4 窒息模式和本地跳转
逐步替代旧的接口是一种通用的迁移现有应用程序或者API的方式,使用不同的具体实现逐步替换它们。Zuul代理是一种很有用的工具,因为你可以使用这种方式处理所有客户端到旧接口的请求。只是重定向了一些请求到新的接口。
4.8.5 通过Zuul上传文件
4.8.6 简单的嵌入Zuul
4.8.7 关闭Zuul过滤器
4.8.8 通过Sidecar进行多语言支持
4.9 RxJava with Spring MVC
Spring Cloud Netflix 包含 RxJava。
Spring Cloud Netflix提供并支持从Spring MVC Controllers返回rx.Single对象,还支持使用rx.Observable对象。
本文详细介绍了 SpringCloud 的入门知识、核心功能及其配置管理方式。内容覆盖服务发现、断路器、负载均衡等多个方面,并深入探讨了 SpringCloud Config 的配置管理机制。
510

被折叠的 条评论
为什么被折叠?



