代码在 https://github.com/betterGa/SpringCloudDemo
一、Hystrix 容错机制 与 数据监控
容错机制是指 在不改变各个微服务的调用关系的前提下,针对错误情况进行预先处理。(可以联想电路中的保险丝,当电路中某个单元发生故障了,就通过烧断保险丝的方式来阻止事故继续蔓延。)
Hystrix 的主要作用就是 当服务提供者发生故障无法访问的时候,向服务消费者返回一个 fallback 的降级处理,从而 保证系统能顺利运行。
- 设计原则
(1) 服务隔离机制:防止某个服务提供者出现故障而影响整个系统的运行。
(2) 服务降级机制:当服务提供者出现故障时,向服务消费者返回一个 fallback 降级处理。
(3)熔断机制:当服务消费者请求失败率打到某个特定的数值时,会迅速的启动熔断机制,并且对错误进行修复。
(4)提供实时的监控和报警功能:保证熔断机制的运行。
(5)提供实时的配置修改功能:保证熔断机制的运行。
上一篇已经结合 Feign 讲解了 Hystrix 的容错机制,容错功能指的是当服务的调用发生问题的时候,我们做一个降级处理,用另外一部分代码进行处理,可以有效防止程序因为响应时间过长而造成整个系统崩溃,并且还能给用户提供更为友好的交互。
Hystrix 除了熔断机制外,还提供了对请求的数据监控,本篇着重讲解Hystix 的数据监控。Hystrix 数据监控需要结合 Spring Boot Actuator 来使用,Actuator 提供了对服务的健康监控、数据统计,可以通过 hystrix.stream 节点获取监控请求数据,提供了可视化的监控界面。
新建一个 module 并导入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
创建配置文件:
server:
port: 8060
spring:
application:
name: hystrix
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
management:
endpoints:
web:
exposure:
include: 'hystrix.stream'
创建启动类,使用 @EnableCircuitBreaker 注解声明启用数据监控,使用 @EnableHystrixDashboard 注解声明启用可视化的数据监控:
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
public class HystrixApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixApplication.class,args);
}
}
拷贝实体类,并提供声明式接口:
@FeignClient(value = "provider")
public interface FeignProviderClient {
@GetMapping("/student/findAll")
public Collection<Student> findAll();
@GetMapping("/student/index")
public String index();
}
提供控制类:
@RestController
@RequestMapping("/hystrix")
public class HystrixHandler {
@Autowired
private FeignProviderClient feignProviderClient;
@RequestMapping("/findAll")
public Collection<Student> findAll(){
return feignProviderClient.findAll();
}
@RequestMapping("/index")
public String index(){
return feignProviderClient.index();
}
}
接下来,分别启动注册中心、服务提供者、hystrix:
可以看到,数据监控页面一直在刷新访问数据,数据为空是因为我们没有访问具体的接口。
访问 http://localhost:8060/hystrix/index :
再访问 http://localhost:8060/hystrix/findAll:
但是这样的数据不够直观,这时,访问 http://localhost:8060/hystrix,可以看到可视化的监控界面,输入要监控的地址节点 即可看到该节点的可视化数据监控。在填写入数据监测的地址http://localhost:8060/actuator/hystrix.stream 和 title 后 :
就可以看到可视化监控界面:
二、Config 配置中心
在基于微服务的分布式系统中,每个业务模块 都可以拆分成独立自主的服务,由多个请求来协助完成某个需求,那么在某一具体的业务场景中,某一个请求需要调用多个服务来完成。这样就存在一个问题,多个服务所对应的配置项也是非常多的,每个服务都有自己的配置文件,如果某一个微服务配置进行了修改,那么其他的服务消费者也需要做出对应的调整,如果在每个服务消费者对应的配置文件中去修改的话是非常麻烦的,并且改完后每个服务还需要重新部署。这时候就需要 把各个服务的配置进行统一管理,便于部署与维护,所以 Spring Cloud 提出了解决方法,就是 Spring Cloud Config 。
Spring Cloud Config 可以通过服务端为多个客户端提供配置服务。Spring Cloud Config 可以将配置文件存储在本地,也可以将配置文件存储在远程仓库 Git 中,可以在不重启微服务的前提下来修改它的配置。具体操作就是创建 Config Server,通过它管理所有的配置文件。
1、本地文件系统
先新建 module,再导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
接下来,创建配置文件 application.yml:
server:
port: 8762
spring:
application:
name: nativeconfigserver
profiles:
active: native
cloud:
config:
server:
native:
search-locations: classpath:/shared
参数说明:
- profiles.active:配置文件获取方式,native 表示从本地获取
- cloud.config.server.native.search-locations:本地配置文件存放的路径,classpath 表示当前文件所在目录
然后,在 resources 包下新建 shared 文件夹,在其中新建配置文件 configclient-dev.yml:
server:
port: 8070
foo: foo version 1
接下来,创建启动类,使用 @EnableConfigServer 注解声明一个配置中心:
@SpringBootApplication
@EnableConfigServer
public class NativeConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(NativeConfigServerApplication.class, args);
}
}
创建一个微服务客户端,来读取本地配置中心的文件(也就是 configclient-dev.yml),还是新建 modole,并导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
接下来,创建配置文件,命名为 bootstrap.yml,注意:不能是 application.yml 这个默认配置文件的名称,因为我们的配置要从配置中心拿,只需要写一些其他的配置项信息,如下:
spring:
application:
name: configclient
profiles:
active: dev
cloud:
config:
uri: http://localhost:8762
fail-fast: true
参数说明
- cloud.config.uri:本地 Config Server 的访问路径
- cloud.config.fail-fase:设置客户端优先判断 Config Server 获取是否正常
通过 spring.application.name 结合 spring.profiles.active 拼接获得目标配置文件名称 configclient-dev.yml,去 Config Server 中查找该文件。
接下来,创建启动类:
@SpringBootApplication
public class NativeConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(NativeConfigClientApplication.class,args);
}
}
再提供控制类:
@RestController
@RequestMapping("/native")
public class NativeConfigHandler {
@Value("${server.port}")
private String port;
@Value("${server.foo}")
private String foo;
@GetMapping("/index")
public String index(){
return this.port+"-"+this.foo;
}
}
然后,启动注册中心、ConfigServer 和 ConfigClient,(这俩是没有注册到注册中心的,在 Instance 中看不到:
)访问 http://localhost:8070/native/index ,运行结果:
2、远程仓库
首先,新建一个 directory,提供一个 配置文件:
server:
port: 8070
eureka:
client:
service:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: configclient
然后把它提交到 git 中:
接下来就要去 git 仓库中读取配置,新建 module ,然后导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
创建配置文件:
server:
port: 8888
spring:
application:
name: configserver
cloud:
config:
server:
git:
uri: https://github.com:betterGa/SpringCloudDemo.git
username:
password:
label: master
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
接下来,创建启动类:
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
接下来,需要创建 config client ,还是创建 module,然后导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
创建 bootstrap.yml :
spring:
cloud:
config:
name: configclient
label: master
discovery:
enable: true
service-id: configserver
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
配置说明:
- spring: cloud: config: name: 当前服务注册在 Eureka Server 上的名称,与远程仓库配置文件的配置文件名对应。
- spring: cloud: config: label:Git Respository 的分支。
- spring: cloud: config: discovery: enable :是否开启 Config 服务发现支持。
- spring: cloud: config: discovery: service-id:配置中心在 Eureka Server 上注册的名称。
创建启动类:
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class,args);
}
}
创建控制类:
@RestController
@RequestMapping("/hello")
public class HellloHandler {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index() {
return this.port;
}
}
三、服务跟踪
分布式系统中有很多个服务在相互调用,调用关系是错综复杂的,如果这时出现了问题,我们在进行问题排查的时候,或者在优化架构的时候,工作量就比较大,这时候就需要我们 能够准确的跟踪到每个网络请求,了解整个运行流程,如网络请求经过了哪些微服务,在每个微服务里是否有延迟等信息,这样就方便我们排查问题,这时我们就可以使用 Spring Cloud Zipkin 来实现。
Spring Cloud Zipkin 是一个可以采集并且跟踪分布式系统中请求数据的组件,让开发者可以更加直观的监控到请求在各个微服务所耗费的时间等, Zipkin 包括 Zipkin Server 服务端和 Zipkin Client 客户端。 Zipkin Server 服务端是用来采集微服务之间的追踪数据的,通过 Zipkin Client 客户端完成数据的生成和展示。
先新建一个 module,导入依赖:
<dependencies>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
然后新建配置文件:
server:
port: 9090
创建启动类,使用 @EnableZipkinServer 注解 声明启动 Zipkin Server:
@SpringBootApplication
@EnableZipkinServer
public class ZipKinApplication {
public static void main(String[] args) {
SpringApplication.run(ZipKinApplication.class,args);
}
}
然后搭建客户端,让 Server 监控跟踪到客户端的请求,新建 module,并导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
提供配置文件:
server:
port: 8090
spring:
application:
name: zipkinclient
sleuth:
web:
client:
enabled: true
sampler:
probability: 1.0
zipkin:
base-url: http://localhost:9090/
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
参数说明:
- spring.sleuth.web.client.enabled:设置开启请求跟踪
- pring.sleuth.sampler.probability:设置采样比例,默认是1.0
- spring.zipkin.base-url:Zipkin Server 的地址
提供启动类:
@SpringBootApplication
public class ZipClientApplication {
public static void main(String[] args) {
SpringApplication.run(ZipClientApplication.class,args);
}
}
提供控制类:
@RestController
@RequestMapping
public class ZipclientHandler {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index(){
return this.port;
}
}
启动注册中心、zipkinserver、zipkinclient,在运行 zipkinserver 启动类的时候报错了:
大意是说 试图调用不存在的方法 zipkin.server.internal.ZipkinHealthIndicator 方法,但是 @EnableConfigServer 注解是没有爆红的,import zipkin.server.internal.EnableZipkinServer; 是导入没问题的,我照着 它说重复了的 jar 包的路径 The class hierarchy was loaded from the following locations:
把 jar 包删掉,结果连注册中心都报错了… …
问题在于, SpringBoot2.2.x 以后的版本 集成 zipkin 的方式改变了,原来是通过@EnablezipkinServer注解,现在 服务端应该通过下载 jar 包,然后 启动项目(来集成 。
在 https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/ 可以选择版本,选择 后缀为 -exec.jar 的(我的 Spring Boot 是 2.3.4 ,选择的 zipkin 是 2.12.8 ),之后切换到 jar 包在的路径,然后用 java -jar 的方式启动就可以了(默认端口号是 9411 ,所以如果提供了 zipkin client,需要把它的配置文件中的端口号改成 9411,对应的配置应该是 zipkin: base-url: http://localhost:9411):
zipkinserver 启动类运行成功后,再运行 zipkinclient 启动类,然后访问 http://localhost:9411/zipkin/ ,可以看到:
然后访问客户端的请求:
可以看到服务被监控到了:
点进去还可以看到更详细的信息:
四、总结
(1)Hystrix 除了熔断机制外,还提供了对请求的数据监控,Hystrix 数据监控需要结合 Spring Boot Actuator 来使用,Actuator 提供了对服务的健康监控、数据统计,可以通过 hystrix.stream 节点获取监控请求数据,提供了可视化的监控界面。
启动类上需要使用 @EnableCircuitBreaker 注解声明启用数据监控,
使用 @EnableHystrixDashboard 注解声明启用可视化的数据监控,使用 @EnableFeignClient 注解来使用声明式接口。
(2)微服务中需要把各个服务的配置进行统一管理,便于部署与维护,所以 Spring Cloud 提出了解决方法,就是 Spring Cloud Config。
具体操作是 创建配置中心(服务端) Config Server,通过它管理所有的配置文件,可以把配置文件存在本地,也可以存在远程仓库。然后 使用 @EnableConfigServer 注解声明配置中心;还要创建个客户端 Config Client,提供配置文件 bootstrap.yml,在其中指定配置文件的名称,这样它就会到配置中心去读取配置信息。配置中心 和 客户端是不需要注册到注册中心的。
(3)Spring Cloud Zipkin 是一个可以采集 并且 跟踪 分布式系统中请求数据的组件,让开发者可以更加直观的监控到请求在各个微服务所耗费的时间等。
Zipkin 也是包括 Zipkin Server 服务端和 Zipkin Client 客户端。
Zipkin Server 服务端是用来采集微服务之间的追踪数据的,通过 Zipkin Client 客户端完成数据的生成和展示。
具体操作是 使用 @EnableZipkinServer 注解 声明启动 Zipkin Server,然后访问客户端里的请求,服务端可以监控到。
👉 总的来说,在整个 Spring Cloud 框架中,有 server、client 的概念,Eureka Server 是注册中心,其他所有的组件都是 client,注册中心要把所有的服务都注册进来,做服务治理;然后通过 Ribbon 或者 Fein 进行负载均衡,它们都是做服务通信,Zuul 是服务网关,Hystrix 是熔断器,做服务容错,Config 做服务配置,Actuarot 做 服务监控,Zipkin 做服务跟踪,这些都是核心组件。
具体操作是 第一步需要先创建父工程,引入 parent 、Spring Boot 和 Spring Cloud 依赖,然后对于各个组件,需要新建 module、 导入依赖、提供配置文件、创建启动类,而且像 Config、Zipkin, 也会有 server、client 的概念,像服务配置,就要有配置中心,和配置客户端,由配置中心去读客户端里的信息;像服务跟踪,也要由服务端去采集、跟踪客户端的访问信息。