在目前SpringCloud生态中,大量使用Hystrix作为断路器的最佳实践。Hystrix即英文豪猪一词,具备有多刺,可以有效的保护自身的一种兽类动物。Hystrix是Netflix开源的一个延迟和容错库,在SpringCloud对其进行了相关修改后融入了SpringCloud生态,成为了Spring Cloud Hystrix。
Hystrix提供以下几种方式来实现延迟和容错,从而保障服务不应级联出现失败:
包裹请求
使用 HystrixCommand注解标注当前服务方法,即所有请求都被Hystrix过滤器过滤,请求也是经过Hystrix包裹的。每个请求都被独立线程执行,注意Hystrix使用了典型的设计模式-命令模式。
断路机制
当某依赖服务出现错误,并且错误率已经超过阈值,Hystrix可以手动断路停止请求该依赖服务一段时间。
资源隔离
Hystrix实质上为每个外部依赖服务建立了一个小型请求线程池(可以认为是某种信号量),如果请求线程池满,发往该依赖服务的请求立即被拒绝,而不是继续进行排队等候、寻址、路由等动作,加速了错误判定,提高了请求效率。
监控
Hystrix实时监控每个请求的状态变化,可以实时得知请求成功、失败、超时等状态变化,并可以得知请求是否被拒绝(是否来自于依赖服务或Hystrix)。
Rollback机制
Rollback机制类似于数据库执行事务时,对相关错误事务进行回滚的操作。一般来说Hystrix允许开发者自定义回滚动作(一般来说返回缺省值)。
自我恢复机制
参见上一章中相关说明,Hystrix会自动检测依赖服务状态,如果外部依赖服务已经恢复则Hystrix会自动关闭断路器。实际上我们认为此时Hystrix处于纠缠态,这种纠缠态在本地服务即断路器开启,外部服务则认为Hystrix转发了相关请求并给予了回应,这种纠缠态基本定位了断路器半开。(薛定谔的猫)
使用Hystrix
首先在Demo4中主Pom文件中添加相关依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在Demo4的Client模块添加依赖后,为启动类添加断路器注解:
package org.bruce.demo.testfeign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Classname TestFeignApplication
* @Description TODO
* @Date 2021/10/22 下午 5:00
* @Created by bruce.hong
*/
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
@EntityScan("org.bruce.demo.entities.*")
public class TestFeignApplication {
public static void main(String[] args) {
SpringApplication.run(TestFeignApplication.class, args);
}
}
EnableCircuitBreaker即断路器注解,即允许当前项目使用Hystrix断路器。
Demo3中Client模块调用了Service模块的Feign接口,为Client模块的相关控制器添加断路器及回滚代码:
package org.bruce.demo.testfeign.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.bruce.demo.entities.User;
import org.bruce.demo.testfeign.feign.UserFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
/**
* @Classname TestController
* @Description TODO
* @Date 2021/10/25 上午 10:27
* @Created by bruce.hong
*/
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private UserFeignService userService;
/**
* 添加断路器的 服务方法
* @param userId
* @return
*/
@GetMapping("/users")
@HystrixCommand(fallbackMethod = "getUserByIdRollback")
public User getUserById( Long userId) {
return userService.findById(userId);
}
/**
* 断路器回滚调用的相关方法
* 返回一个初始化后的用户对象(缺省值)
* @return
*/
public User getUserByIdRollback(){
return new User();
}
}
添加了相关代码后,按照如下步骤运行:
- 运行Nacos
- 运行Client模块
- 通过localhost:9201/test/users?userid=1 调用接口
- 返回如下图的数据结果:
注意:
访问test/users API接口时,Server模块并未运行,Feign接口实际上是无法调用的。Hystrix通过断路器回滚机制,返回了缺省值,保障了服务继续运行提高了容错性。
代码参见:
Bruce.hong的阿里云Bruce.hong的阿里云