【配置】Hystrix 服务降级

本文详细介绍了Hystrix断路器在分布式系统中的应用,包括如何处理延迟和容错,防止级联故障,提高服务弹性。文章还提供了具体的环境配置、依赖引入、代码示例,展示了如何在Spring Cloud项目中启用Hystrix,以及如何定义和使用Fallback方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介:

Hystrix 是一个用于处理分布式系统的延迟容错的开源库, 在分布式系统中,许多不可避免的调用会失败, 比如超时,异常等。Hystrix 能够保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性

“断路器” 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似保险熔断),向调用方法返回一个符合预期的,可处理的被选响应(FallBack), 而不是长时间的等待或者抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会长时间,不必要地占用,从而避免了故障在分布式系统中的蔓延,从而导致雪崩效应。

前言:使用的consul注册中心和openfeign(消费端使用)

环境准备

POM
  • Provider
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.live</groupId>
    <artifactId>hystrix-provider8001</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.3.1.RELEASE</version>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • Consumer
<!--多一个openfeign依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>
YML
  • Provider
server:
  port: 8001
spring:
  application:
    name: hystrix-provider8001
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        instance-id: provider8001
        ip-address: true
  • Consumer

    • ribbon.ReadTimeout: 从服务器获取服务的最大时间

    • ribbon.ConnectTimeout: 连接至服务器的最大时间

    • logging.level.xx.xx.Xxxx: 开启openfeign的日志

      import feign.Logger;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class OpenfeignLogConfig {
      
          @Bean
          Logger.Level level() {
              return Logger.Level.FULL;
          }
      
      }
      
    • feign.hystrix.enabled: 启用feign对hystrix的支持

server:
  port: 80
spring:
  application:
    name: hystri-consumer80
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true
        service-name: ${spring.application.name}
        instance-id: consumer80
ribbon:
  ReadTimeout: 6000
  ConnectTimeout: 6000
logging:
  level:
    com.live.service.PaymentService: debug
feign:
  hystrix:
    enabled: true
启动类
  • Provider
    • @EnableCircuitBreaker: 启用Hystrix
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

@SpringBootApplication
@EnableCircuitBreaker
public class HystrixProvider8001 {

    public static void main(String[] args) {
        SpringApplication.run(HystrixProvider8001.class,args);
    }

}
  • Consumer
    • @EnableCiruitBreaker
    • @EnableFeignClients: 启用Feign
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableCircuitBreaker
@EnableFeignClients
public class HystrixConsumer80 {

    public static void main(String[] args) {
        SpringApplication.run(HystrixConsumer80.class,args);
    }

}

对每个方法定义FallBack Method

Service

在需要降级的方法上标识注解@HystrixCommand

降级方法和service定义在同一个类中

@HystrixCommand 属性描述
fallbackMethod降级方法的方法名
commandProperties设置Hystrix的各种属性
@HystrixProperty 属性描述
execution.isolation.thread.timeoutInMilliseconds如果这个方法执行时间超过了所设置的就调用fallback
circuitBreaker.enabledboolean 开启断路器
circuitBreaker.requestVolumeThreshold请求次数
circuitBreaker.sleepWindowInMilliseconds窗口期
circuitBreaker.errorThresholdPercentage请求失败百分比(和上三个同时使用,在一个窗口期内,有x次请求,且请求错误达到x的百分比就开启断路器)

更多的属性查看HystrixCommandProperties类
在这里插入图片描述

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class PaymentService {

    @HystrixCommand(fallbackMethod = "timeout_fallback",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "4000")
    })
    @GetMapping(value = "/timeoutTest")
    public String timeoutTest() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            log.info("====Timout Exception ヾ(≧ ▽ ≦)ゝ");
        }
        return Thread.currentThread().getName() + " => provider Timeout Test";
    }

    @HystrixCommand(fallbackMethod = "exception_fallback")
    @GetMapping(value = "/exceptionTest")
    public String exceptionTest() {
        int i = 10 / 0;
        return Thread.currentThread().getName() + " => provider Exception Test";
    }

    public String timeout_fallBack() {
        return Thread.currentThread().getName() + " => This is the provider timeout_fallback";
    }

    public String exception_fallback() {
        return Thread.currentThread().getName() + " => This is the provider exception_fallback";
    }

}

局部FallBack

  • 在类上标识注解 @DefaultProperties(defaultFallback=“方法名”)
  • 定义一个Fallback方法
  • 在需要Fallback的方法上标识注解 @HystrixCommand 即可
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.concurrent.TimeUnit;

@Service
@DefaultProperties(defaultFallback = "default_fallback")
@Slf4j
public class PaymentService {

    @HystrixCommand
    @GetMapping(value = "/normalTest")
    public String normalTest() {
        return Thread.currentThread().getName() + " => provider Normal Test";
    }

    @HystrixCommand
    @GetMapping(value = "/timeoutTest")
    public String timeoutTest() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            log.info("====Timout Exception ヾ(≧ ▽ ≦)ゝ");
        }
        return Thread.currentThread().getName() + " => provider Timeout Test";
    }

    @HystrixCommand
    @GetMapping(value = "/exceptionTest")
    public String exceptionTest() {
        int i = 10 / 0;
        return Thread.currentThread().getName() + " => provider Exception Test";
    }

    public String default_fallback() {
        return Thread.currentThread().getName() + " => This is the provider default_fallback";
    }

}

消费端-接口实现Service对Fallback统一处理(OpenFeign)

Service
在类上标识 @FeignClient 注解 value 指定微服务名,fallback指定处理服务降级的类
注意:这里的请求路径和服务提供者的Controller请求路径一致
import com.live.service.impl.PaymentServiceFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

@Component
@FeignClient(value = "hystrix-provider8001",fallback = PaymentServiceFallBack.class)
public interface PaymentService {

    @GetMapping(value = "/provider/normal")
    String normalTest();

    @GetMapping(value = "/provider/timeout")
    String timeoutTest();

    @GetMapping(value = "/provider/exception")
    String exceptionTest();

}
ImplFallback
实现Service接口,对方法进行降级处理;注意加上 @Component 注解加入Spring容器中
import com.live.service.PaymentService;
import org.springframework.stereotype.Component;

@Component
public class PaymentServiceFallBack implements PaymentService {

    @Override
    public String normalTest() {
        return Thread.currentThread().getName() + " => This is the consumer Normal fall back";
    }

    @Override
    public String timeoutTest() {
        return Thread.currentThread().getName() + " => This is the consumer Timeout fall back";
    }

    @Override
    public String exceptionTest() {
        return Thread.currentThread().getName() + " => This is the consumer Exception fall back";
    }
}

Controller

  • Provider
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@RequestMapping(value = "/provider")
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/normal")
    public String normal() {
        return paymentService.normalTest();
    }

    @GetMapping(value = "/timeout")
    public String timeout() {
        return paymentService.timeoutTest();
    }

    @GetMapping(value = "/exception")
    public String exception() {
        return paymentService.exceptionTest();
    }

}
  • Consumer
import com.live.service.PaymentService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {

    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/normal")
    public String normal() {
        return paymentService.normalTest();
    }

    @GetMapping(value = "/timeout")
    public String timeout() {
        return paymentService.timeoutTest();
    }

    @GetMapping(value = "/exception")
    public String exception() {
        return paymentService.exceptionTest();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeathAndLife

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值