每天学点SpringCloud(六):Hystrix使用

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。博客源地址为zhixiang.org.cn https://blog.csdn.net/myFirstCN/article/details/81048280   Hystrix是一个实现断路器模式的库。
版权声明:本文为博主原创文章,未经博主允许不得转载。博客源地址为zhixiang.org.cn https://blog.csdn.net/myFirstCN/article/details/81048280

 

 

Hystrix是一个实现断路器模式的库。什么是断路器模式呢?就像我们家庭中的电闸一样,如果有那一处出现意外,那么电闸就会立刻跳闸来防止因为这一处意外而引起更大的事故,直到我们确认处理完那一处意外后才可以再打开电闸。而Hystrix的存在就是为了预防程序中出现这种问题而导致程序不可用的情况。

 

 

 

比如说我们有三个微服务 A、B、C,其中A依赖于B,B依赖于C,如果这时候C出现了问题,那么就导致B不可用,紧接着A也不可用,更有可能导致整个系统不可用。我们接下来就来看看如何利用Hystrix预防这种情况

 

 

创建项目

首先我们复制一份cloud-demo-consumer项目,改名为cloud-demo-consumer-hystrix

引入Hystrix的依赖

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

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

 

application.xml不用变

spring:
  application:
    name: consumer-demo-hystrix
server:
  port: 8090
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://root:root@localhost:8761/eureka
  instance:
    prefer-ip-address: true

  application:
    name: consumer-demo-hystrix
server:
  port: 8090
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://root:root@localhost:8761/eureka
  instance:
    prefer-ip-address: true

 

CloudDemoConsumerApplication改名为CloudDemoConsumerHystrixApplication,并且它的注解应该是

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreake

@EnableEurekaClient
@EnableCircuitBreake

上方我们不认识的这个@EnableCircuitBreake注解就是表示开启断路器模式的注解

 

然后我们看一下controller

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getUser/{id}")
    @HystrixCommand(fallbackMethod = "getUserFallback")
    public User getUser(@PathVariable Long id){
         return restTemplate.getForObject("http://provider-demo/user/getUser/"+id,User.class);
    }
    public User getUserFallback(Long id) {
        User user = new User();
        user.setName("王五");
        return user;
    }
}

@RequestMapping("/user")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getUser/{id}")
    @HystrixCommand(fallbackMethod = "getUserFallback")
    public User getUser(@PathVariable Long id){
         return restTemplate.getForObject("http://provider-demo/user/getUser/"+id,User.class);
    }
    public User getUserFallback(Long id) {
        User user = new User();
        user.setName("王五");
        return user;
    }
}

它相比较于原先的controller仅仅是多了一个@HystrixCommand(fallbackMethod = "getUserFallback")注解和一个方法,这个注解呢就是指定Hystrix在此方法超时时调用的方法。

 

测试

首先启动我们代表Eureka服务的项目,然后启动cloud-demo-provider项目,紧接着启动我们现在的项目。

 

项目启动以后我们打开浏览器访问localhost:8088/user/getUser/2的时候发现一切正常,网页上返回了张三这个用户。如果我们没有引入Hystrix的时候如果这时候把服务提供者停掉的话在访问会出现什么情况呢,是不是会报错,或者超时呀。

但是现在不一样了,我们引入了Hystrix,所以我们现在停掉提供者访问的时候会发现程序走了注解指定的fallbackMethod,也就是方法getUserFallBack,这个时候我们浏览器得到的结果是王五。

 

Hystrix默认的超时时间是1秒,也就是说它在等待服务提供者1秒后如果得不到结果的话就会认为提供者挂了,紧接着调用fallbackMethod。

这个时间其实我们可以控制,只需要在yml文件中配置一个属性就可以自定义这个时间

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 1000 #1000毫秒
.command.default.execution.isolation.thread.timeoutInMilliseconds: 1000 #1000毫秒

 

 

Feign的支持

接下来我们看一下Feign是怎么使用Hystrix,

这次我们改造cloud-demo-consumer-feign项目,项目名称改为cloud-demo-consumer-feign-hystrix,同样向上述 方式一样引入Hystrix的依赖,

接着 CloudDemoConsumerFeignApplication类名改为 CloudDemoConsumerFeignHystrixApplication,同样的加入@EnableCircuitBreaker注解

有一点不一样的地方是我们需要在yml文件中配置一下来开启Hystrix

feign.hystrix.enabled: true
.hystrix.enabled: true

 

这里controller中需要改造的不再是指定单个方法,而是指定接口的实现类

@FeignClient(name = "provider-demo", fallback = HystrixClientFallback.class)
name = "provider-demo", fallback = HystrixClientFallback.class)

来看一下这个实现类

@Component
public class HystrixClientFallback implements UserFeignClient {
    @Override
    public User getUser(Long id) {
        User user = new User();
        user.setName("王五");
        return user;
    }
}


public class HystrixClientFallback implements UserFeignClient {
    @Override
    public User getUser(Long id) {
        User user = new User();
        user.setName("王五");
        return user;
    }
}

 

这样的话如果接口中有多个方法的话我们就不必为每一个方法取指定了。

 

现在我们已经解决了服务提供者挂掉的事情了,但是有点不好的是,我们现在还不能知道服务提供者到底是咋挂的,要是能捕获到服务提供者

抛的异常就好了,其实Hystrix对这个是支持的,我们接下来看一下

 

fallbackFactory

 

UserFeignClient上方的注解需要变一下

@FeignClient(name = "provider-demo", fallbackFactory = HystrixClientFactory.class)
name = "provider-demo", fallbackFactory = HystrixClientFactory.class)

这次使用的是fallbackFactory这个属性,我们看一下它指定的这个类又是怎么实现的呢

 

@Component
public class HystrixClientFactory implements FallbackFactory<UserFeignClient> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFactory.class);

    @Override
    public UserFeignClient create(Throwable cause) {
        HystrixClientFactory.LOGGER.info("the provider error is: {}", cause.getMessage());
        return new UserFeignClient() {
            @Override
            public User getUser(Long id) {
                User user = new User();
                user.setName("王五");
                return user;
            }
        };
    }
}

public class HystrixClientFactory implements FallbackFactory<UserFeignClient> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFactory.class);

    @Override
    public UserFeignClient create(Throwable cause) {
        HystrixClientFactory.LOGGER.info("the provider error is: {}", cause.getMessage());
        return new UserFeignClient() {
            @Override
            public User getUser(Long id) {
                User user = new User();
                user.setName("王五");
                return user;
            }
        };
    }
}

 

我们可以看到,在这个create的工厂方法中,它的入参就是服务提供者的异常,得到了这个异常以后才会去做实现。这样是不是更加灵活了呢?

 

GitHub:https://github.com/2388386839/spring-cloud-demo

码云:https://gitee.com/zhixiang_blog/spring-cloud-demo

 

如果对您有所帮助,请记得帮忙点一个star哦

 

 

 

本文出自https://zhixiang.org.cn,转载请保留。

相关文章
|
4天前
|
消息中间件 负载均衡 Java
【Spring Cloud 初探幽】
【Spring Cloud 初探幽】
13 1
|
6天前
|
Java 开发者 微服务
Spring Cloud原理详解
【5月更文挑战第4天】Spring Cloud是Spring生态系统中的微服务框架,包含配置管理、服务发现、断路器、API网关等工具,简化分布式系统开发。核心组件如Eureka(服务发现)、Config Server(配置中心)、Ribbon(负载均衡)、Hystrix(断路器)、Zuul(API网关)等。本文讨论了Spring Cloud的基本概念、核心组件、常见问题及解决策略,并提供代码示例,帮助开发者更好地理解和实践微服务架构。此外,还涵盖了服务通信方式、安全性、性能优化、自动化部署、服务网格和无服务器架构的融合等话题,揭示了微服务架构的未来趋势。
31 6
|
10天前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
|
10天前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。
|
12天前
|
消息中间件 Java RocketMQ
Spring Cloud RocketMQ:构建可靠消息驱动的微服务架构
【4月更文挑战第28天】消息队列在微服务架构中扮演着至关重要的角色,能够实现服务之间的解耦、异步通信以及数据分发。Spring Cloud RocketMQ作为Apache RocketMQ的Spring Cloud集成,为微服务架构提供了可靠的消息传输机制。
27 1
|
12天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
15 2
|
12天前
|
监控 Java Sentinel
Spring Cloud Sentinel:概念与实战应用
【4月更文挑战第28天】在分布式微服务架构中,确保系统的稳定性和可靠性至关重要。Spring Cloud Sentinel 为微服务提供流量控制、熔断降级和系统负载保护,有效预防服务雪崩。本篇博客深入探讨 Spring Cloud Sentinel 的核心概念,并通过实际案例展示其在项目中的应用。
23 0
|
12天前
|
Cloud Native Java Nacos
Spring Cloud Nacos:概念与实战应用
【4月更文挑战第28天】Spring Cloud Nacos 是一个基于 Spring Cloud 构建的服务发现和配置管理工具,适用于微服务架构。Nacos 提供了动态服务发现、服务配置、服务元数据及流量管理等功能,帮助开发者构建云原生应用。
20 0
|
15天前
|
Java 数据安全/隐私保护 Sentinel
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流