第七章:Spring Cloud Consul
这个项目在spring boot基础上,通过自动化配置,提供对Consul各组件的整合;并绑定到spring运行环境及各模块中。在您的分布式应用系统中,可以很方便的使用注解,去启用配置强大的组件,实现分布式通用模式。例如 服务发现模式(Eureka),终端器模式(Hystrix),快捷路由模式(Zuul),客户端负载均衡模式(Ribbon)等。
安装Consul
请按照安装文档中的操作步骤安装Consul。
Consul代理
Consul代理客户端必须对所有的Spring Cloud Consul应用可用。默认情况下,代理客户端的地址希望是localhost:8500
。看代理文档详细说明如何启动代理客户端以及如何连接到代理服务端集群中。对于开发,在安装完consul以后你可以使用以下命令启动代理客户端:
./src/main/bash/local_run_consul.sh
这会启动一个Consul服务在8500端口上,在界面上http://localhost:8500路径是可用的。
通过Consul发现服务
服务发现模式是微服务化架构的关键原则。需要调用各服务的客户端的配置,或者让各模块都遵从一定形式的约定,很困难,也很繁琐。Consul通过改变Http api和dns提供了服务发现服务。Spring Cloud Consul为服务注册和服务发现提供了http api。这不会阻止非Spring Cloud applications对dns的改变。 Consul代理服务通过gossip协议交换数据用Raft consensus协议格式运行在集群中。
通过Consul注册服务
用Consul注册服务,可以提供服务本身的基础数据,包括主机和端口,运行健康状态的诊断地址,主页等。Http检查会被默认创建,Consul每隔10秒请求一次/health路径。如果健康检查失败,服务会被标记为严重的:
Consul客户端示例代码:
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello world";
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
(例如,通常是Spring boot 应用)。如果Consul的客户端不是在localhost:8500
路径,则需要配置客户端的路径。例如:
application.yml
spring:
cloud:
consul:
host: localhost
port: 8500
提示:如果你用Spring Cloud Consul Config,以上的值应该在bootstrap.yml文件中配置而不是application.yml中。
默认运行环境中获取应用名称 (service ID),虚拟主机和非安全端口,分别是${spring.application.name}
, ${spring.application.name}
和 ${server.port}
。
@EnableDiscoveryClient
使应用注册了一个服务本身实例,也声明了它是Eureka的客户端(可以查询到其他注册过的服务实例)。
Http健康认证检查
Consul的健康认证检查的路径是"/health",这是Spring Boot Actuator 应用的默认路径。你应该修改这些,即便是实际应用的,你也应该不使用默认的上下文路径或者servlet路径(例如server.servletPath=/foo
),或者管理端路径management.contextPath=/admin
。Consul用来作健康认证检查的默认间隔时间可能也已经配置过了。"10s" and "1m" 分别代表10秒和1分钟。例如:
application.yml
spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.contextPath}/health
healthCheckInterval: 15s
元数据和Consul标签
Consul目前不通过服务支持元数据。Spring Cloud的ServiceInstance
有一个Map<String, String>
的元数据字段。在Consul官方支持元数据之前Spring Cloud Consul会一直用Consul标签展示元数据。key=value
格式的标签会分别分割为键值。没有'='的会认为key和value都一样。
application.yml
spring:
cloud:
consul:
discovery:
tags: foo=bar, baz
以上文档里的配置会被认为foo→bar和baz→baz这样的2个结果。
>让Consul实例的id唯一
默认情况下consul的实例的id会用spring上下文的id注册。默认Spring上下文的id是${spring.application.name}:逗号','分隔,profiles:${server.port}
。大多数情况下,这可以允许一个服务的多个实例运行在同一机器上。如果追求更高的唯一性,你可以用Spring Cloud通过spring.cloud.consul.discovery.instanceId
属性重写唯一的id。例如:
application.yml
spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
通过这个元数据信息,多个实例部署在一个服务器上,这会生成随机数,保证id的唯一性。Cloudfoundry中,spring.application.instance_id
会通过Spring Boot Actuator应用自动生成,因此,随机数也会用不上。
用服务发现客户端
Spring Cloud用逻辑服务名代替url地址对Feign(一个rest的客户端构建库)和Spring RestTemplate支持。
你可以通过org.springframework.cloud.client.discovery.DiscoveryClient
提供简单的服务发现的api客户端,不仅仅是netflix。例如
@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List<ServiceInstance> list = discoveryClient.getInstances("STORES");
if (list != null && list.size() > 0 ) {
return list.get(0).getUri();
}
return null;
}
用Consul作分布配置
Consul提供键/值存储,用以存储配置和元数据信息。Spring Cloud Consul配置是配置服务端和客户端的替代方案。配置,在bootstrap阶段,被加载到spring环境变量中。默认情况下,配置存在/config目录中。多个PropertySource实例基于应用名以及有效的对象,按照Spring Cloud配置对属性映射的顺序被创建。例如你一个以testApp为名的应用,和dev为名的对象,会有以下属性源文件被创建:
config/testApp,dev/
config/testApp/
config/application,dev/
config/application/
越精细的属性源文件越在上面,最底下是最笼统的属性配置源文件。config/application文件下的所有属性是各个应用使用consul作为配置的文件。config/testApp只是testApp应用的属性配置文件。
配置文件目前在应用启动的时候开始读取。对/refresh路径发送一个Http post请求,会让配置被重新载入。监控键值存储(Consul支持的)是否被修改,在目前项目中还不支持,未来项目中会添加这一特性。
如何激活
添加org.springframework.cloud:spring-cloud-consul-config依赖,会启用自动配置,设置Spring Cloud Consul的配置。
自定义
Consul的配置可以通过以下属性自定义:
bootstrap.yml
spring:
cloud:
consul:
config:
enabled: true
prefix: configuration
defaultContext: apps
profileSeparator: '::'
enabled设置为false会禁用Consul配置
prefix设置配置的基础目录
defaultContext设置所有应用的公用配置的目录名
profileSeparator设置属性源文件分割对象的分隔符
YAML或者配置属性
可能把所有的配置放到YAML或者属性文件,单个的键值属性的存储更方便。spring.cloud.consul.config.format可以设置YAML或者PROPERTIES,指定配置文件的格式。举例用YAML:
bootstrap.yml
spring:
cloud:
consul:
config:
enabled: true
prefix: configuration
defaultContext: apps
profileSeparator: '::'
在Consul中,YAML的键必须设置为合适的数据。用以上的默认设置键可能像这样:
config/testApp,dev/data
config/testApp/data
config/application,dev/data
config/application/data
YAML中,可以设置数量不限的以上键值对的列表。
你可以用spring.cloud.consul.config.data-key设置,改变键值设置。
git2consul和配置一起使用
git2consul从git资源上读入文件加载到单个的配置,的社区项目。默认情况下,文件名是键名。YAML和属性文件分别支持.yml和.properties的文件格式。设置spring.cloud.consul.config.format为FILES。例如:
bootstrap.yml
spring:
cloud:
consul:
config:
format: FILES
给定以下的配置/config,development对象和foo应用:
.gitignore
application.yml
bar.properties
foo-development.properties
foo-production.yml
foo.properties
master.ref
以下属性源文件会被创建:
config/foo-development.properties
config/foo.properties
config/application.yml
每个键值都需要准确的在YAML或者Properties文件中组织好。
请求失败得最快
在某些情况下(例如本地开发或者一些测试场景中),consul不能用作配置,不响应请求失败会更方便。在 bootstrap.yml
配置中设置spring.cloud.consul.config.failFast=false,会写入一个警告消息到日志中,而不是抛出异常。这会允许应用正常的启动并继续。
Consul重试
如果你的应用在启动的时候,偶然原因不可用的话,你可以让他在失败后再试试。你需要在classpath下添加spring-retry和spring-boot-starter-aop的依赖。在默认间隔1000ms后默认尝试6次,每次默认间隔时长乘以1.1 。你可以用spring.cloud.consul.retry.*配置这些配置属性。这对Spring Cloud Consul配置和发现服务的注册都有用。
提示:通过@Bean注解"consulRetryInterceptor"为id的RetryOperationsInterceptor类型的对象,可以完全控制重试。Spring Retry有RetryInterceptorBuilder,能令你更方便的创建这样的一个对象。
Spring cloud总线和Consul
以后的版本中有添加。
断路器和Hystrix一起用
从spring-cloud-starter-hystrix项目的pom.xml文件开始的应用可以使用Spring Cloud Netflix提供的Hystrix断路器。Hystrix并不取决于Netflix的服务发现客户端。@EnableHystrix注解可以被添加到配置类(可能是入口类)。@HystrixCommand注解的方法会被断路器保护。更多详情见文档。
Hystrix度量整合Turbine和Consul
Turbine(Spring Cloud Netflix项目提供的),聚合了多个Hystrix测量流实例,因此面板上会展示一个整体的视图。Turbine用DiscoveryClient服务发现客户端接口去发现相关的实例。要把Turbine和Spring Cloud Consul一起用的话,和以下类似的形式配置Turbine:
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
注意Turbine依赖不是最初始项目。它包含了Netflix Eureka的依赖支持。
application.yml
spring.application.name: turbine
applications: consulhystrixclient
turbine:
aggregator:
clusterConfig: ${applications}
appConfig: ${applications}
clusterConfig和appConfig部分必须匹配上,因此逗号,分割的id列表放到配置属性中,是很有用的。
Turbine.java
@EnableTurbine
@EnableDiscoveryClient
@SpringBootApplication
public class Turbine {
public static void main(String[] args) {
SpringApplication.run(DemoturbinecommonsApplication.class, args);
}
}