当前位置: 首页 > article >正文

Spring Cloud — 微服务容错保护 Hystrix入门

微服务之间是通过网络进行相互调用,如果单个服务出现问题,用户调用相关服务时或造成调用延迟或失败,进而可能让整个系统奔溃。提前做好应急措施,当遇到问题时,可及时启动应急方案,让系统进行自我调节和保护。

1 Hystrix

Hystrix 是一个用于处理分布式系统延迟和容错的库,旨在通过隔离服务的访问点、停止级联故障以及提供回退选项来提高系统的整体弹性。

1.1 Hystrix 入门

maven依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

在Application类增加@EnableCircuitBreaker注解来开启Hystrix支持。

Hystrix 提供降级有2种方式:1)通过@HystrixCommand注解;2)通过继承HystrixCommand或HystrixObservableCommand类。

1.1.1 @HystrixCommand注解

@RequestMapping("/home")
@RestController
public class HomeController {

    private final RestTemplate restTemplate;
    private final UserService userService;

    public HomeController(RestTemplate restTemplate, UserService userService) {
        this.restTemplate = restTemplate;
        this.userService = userService;
    }

    @HystrixCommand(fallbackMethod = "infoCallback")
    @GetMapping("/info")
    public String info(String name) {
        return restTemplate.getForObject("http://provider/user/info?name=" + name + "consumer",String.class);
    }

    @HystrixCommand(fallbackMethod = "updateCallback")
    @PostMapping("/update")
    public String update(@RequestBody User user) {
        return userService.update(user);
    }

    public String infoCallback(String name) {
        return "/info 降级";
    }

    public String updateCallback(User user) {
        return "/update 降级," + user;
    }
}

fallbackMethod所指定的方法要与原方法具有相同的方法签名。

1.1.2 继承HystrixCommand

public class UserInfoFailCommand extends HystrixCommand<String> {

    private final RestTemplate restTemplate;
    private final String name;

    public UserInfoFailCommand(RestTemplate restTemplate, String name) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")));
        this.restTemplate = restTemplate;
        this.name = name;
    }

    @Override
    protected String run() throws Exception {
        return restTemplate.getForObject("http://provider/user/info?name=" + name,String.class);
    }

    @Override
    protected String getFallback() {
        return "userInfoFailCommand 降级 info";
    }
}
@RequestMapping("/home")
@RestController
public class HomeController {

    private final RestTemplate restTemplate;

    public HomeController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping("/info3")
    public String info3(String name) {
        UserInfoFailCommand command = new UserInfoFailCommand(restTemplate,name);
        return command.execute();
    }
}

默认是阻塞式的,可提供同步和异步两种方式。同步通过execute()方法直接返回结果,异步执行通过queue()方法返回一个Future对象。

1.1.3 继承HystrixObservableCommand

public class UserInfoObservableCommand extends HystrixObservableCommand<String> {

    private final RestTemplate restTemplate;
    private final String name;

    public UserInfoObservableCommand(RestTemplate restTemplate, String name) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")));
        this.restTemplate = restTemplate;
        this.name = name;
    }

    @Override
    protected Observable<String> construct() {
        String res = restTemplate.getForObject("http://provider/user/info?name=" + name, String.class);
        return Observable.just(res + ",UserInfoObservableCommand construct");
    }

    @Override
    protected Observable<String> resumeWithFallback() {
        return Observable.just("UserInfoObservableCommand info 降级");
    }
}
@RequestMapping("/home")
@RestController
public class HomeController {

    private final RestTemplate restTemplate;

    public HomeController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping("/info4")
    public String info4(String name) {
        UserInfoObservableCommand command = new UserInfoObservableCommand(restTemplate, name);
        Iterator<String> iterator = command.observe().toBlocking().getIterator();
        StringBuilder sb = new StringBuilder();
        while (iterator.hasNext()) sb.append(iterator.next());
        return sb.toString();
    }
}

非阻塞的。只能是异步调用。通过observe()和toObservable()方法返回一个Observable对象。observe()方法会立即发出请求,toObservable()方法只有在订阅该对象时,才会发出请求。

1.1.4 在Feign中使用Hystrix回退

@Component
public class UserServiceCallback implements UserService{

    @Override
    public String info(String name) {
        return "info 降级2:" + name;
    }

    @Override
    public String update(User user) {
        return "update 降级2:" + user;
    }

}
@RequestMapping("/home")
@RestController
public class HomeController {

    private final UserService userService;

    public HomeController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/info2")
    public String info2(String name) {
        return userService.info(name + "feign");
    }

    @PostMapping("/update")
    public String update(@RequestBody User user) {
        return userService.update(user);
    }
}

需要在配置文件中feign.hystrix.enabled属性设置为true。

1.2 容错机制分析

Hystrix能根据以下条件进行服务降级:

  1. 可配置依赖调用超时时间,当调用超时时,直接返回或进行服务降级。
  2. 为每个依赖关系/服务调用维护一个小的线程池(或信号量),如果已满,那么依赖服务调用将立即被拒绝,而不是排队等待。
  3. 对服务调用的执行状态(成功、失败、超时及线程拒绝等)进行统计,如果某服务调用的错误百分比高于阈值,则可通过手动或自动方式打开断路器。

1.2.1 Hystrix的执行过程

图 Hystrix的执行过程

1 命令封装与执行

通过命令模式,将用户对业务服务请求操作进行封装成HystrixCommand与HystrixObservableCommand。

2 结果缓存是否可用

如果开启了缓存功能,Hystrix在执行命令时首先会检查是否缓存命中,如果是则立即将缓存结果返回,并不再继续执行该命令。

3 断路器是否已打开

如果已打开,说明相应服务不可用,此时进行服务降级。

4 是否有资源执行

判断与该命令相关的线程池和队列是否已满(如果使用信号量隔离,则判断信号量是否已满),如果已满,则不执行该命令,进行服务降级。

5 执行业务逻辑

命令执行过程中,如果超时,那么执行线程将会抛出移除,此时会转入到fallback处理。

6 更新断路器健康数据

在执行业务逻辑的过程中,Hystrix将会把采集到的执行状态(成功、失败、拒绝和超时等)数据提交给断路器。

7 服务降级

在实现服务降级时,最好能提供一个默认的处理结果,该结果最好从内存缓存或一个静态逻辑处理中计算到,不要在有任何网络调用的依赖。

1.2.2 断路器原理分析

断路器根据收集到的命令状态数据,来决定是否打开。如果打开,后续的请求都会进行服务降级处理。然后隔一段时间尝试半开,放一部分流量请求进来,重新统计命令状态数据,如果满足条件,则断路器关闭。


http://www.kler.cn/a/551228.html

相关文章:

  • 解锁机器学习核心算法 | K-平均:揭开K-平均算法的神秘面纱
  • spring boot知识点2
  • UI自动化测试的优缺点?
  • 如何在 Mac 上下载安装仙剑游戏仙剑世界?可以通过IPA砸壳包安装非常简单
  • js考核第五题
  • iOS 中使用 FFmpeg 进行音视频处理
  • 机器学习_11 线性回归知识点总结
  • Python----数据结构(单链表:节点,是否为空,长度,遍历,添加,删除,查找)
  • mysql 存储空间增大解决方案
  • WordPress Ai插件:支持提示词生成文章和chat智能对话
  • 算法与数据结构(最小栈)
  • 13、《SpringBoot+MyBatis集成(1)——快速入门》
  • Scikit-learn 使用指南:从入门到实战
  • 说说高级java每日一道面试题-2025年2月11日-数据库篇-MVCC 可以为数据库解决什么问题?
  • IB网络错误检查工具ibqueryerrors
  • 【数据分享】1929-2024年全球站点的逐年降雪深度数据(Shp\Excel\免费获取)
  • Azure上基于OpenAI GPT-4模型验证行政区域数据的设计方案
  • 锂电池matlab模型,适用物理对象建模
  • JAVA代码走查重构常用prompt
  • 前端如何播放二进制音频数据