欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

程序员文章站 2022-04-14 14:04:47
Hystrix介绍Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不长时间的等待或者抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要...

Hystrix介绍

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

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

github地址:https://github.com/Netflix/Hystrix

服务降级

所谓降级,就是当某个服务出现异常之后,服务器将不再被调用,此时服务端可以自己准备一个本地的fallback回调,返回一个缺省值。 这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。

可能出现服务降级的情况:

  1. 程序运行异常
  2. 服务超时
  3. 服务熔断出发服务降级
  4. 线程池/信号量打满也会导致服务降级

版本说明

Java : 1.8
Spring Boot : 2.1.5.RELEASE
Spring Cloud: Greenwich.SR1

项目说明

eureka-server:eureka服务中心
feign-client :feign生产者
feign-client-intf:feign接口提供者
hystrix-fallback:hystrix降级demo

eureka-server 前面文章已经提供不在粘贴出来了

feign-client-intf:feign接口提供者

pom.xml

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

server接口提供

@FeignClient("feign-client")
public interface IService {

    @GetMapping("/sayHi")
    public String sayHi();

    @PostMapping("/sayHi")
    public Friend sayHiPost(@RequestBody Friend friend);

    @GetMapping("/retry")
    public String retry(@RequestParam(name = "timeout") int timeout);

    @GetMapping("/error")
    public String error();

}

Friend实体类

@Data
public class Friend {

    private String name;

    private String port;

}

feign-client :feign生产者

pom.xml

dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
        <groupId>com.imooc</groupId>
        <artifactId>feign-client-intf</artifactId>
        <version>${project.version}</version>
    </dependency>

</dependencies>

application.properties

spring.application.name=feign-client
server.port=40006


eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/

Controller

@RestController
public class Controller implements IService {
    Logger log = LoggerFactory.getLogger(Controller.class);

    @Value("${server.port}")
    private String port;


    @GetMapping("/sayHi2")
    public String sayHi2() {
        return "This is " + port;
    }

    @Override
    public String sayHi() {
        return "This is " + port;
    }

    @Override

    public Friend sayHiPost(@RequestBody Friend friend) {
        log.info("You are " + friend.getName());
        friend.setPort(port);
        return friend;
    }

    @Override
    public String retry(@RequestParam(name = "timeout") int timeout) {
        System.out.println("timeout"+timeout);
        while (--timeout >= 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        }
        log.info("retry " + port);
        return port;
    }

    @Override
    public String error() {
        throw new RuntimeException("black sheep");
    }
}

FeignClientApplication启动类

@EnableDiscoveryClient
@SpringBootApplication
public class FeignClientApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(FeignClientApplication.class)
                .web(WebApplicationType.SERVLET)
                .run(args);
    }

}

hystrix-fallback:hystrix降级demo

spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

pom.xml

dependencies>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>feign-client-intf</artifactId>
            <version>${project.version}</version>
        </dependency>

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

application.properties

spring.application.name=hystrix-consumer
server.port=50001
spring.main.allow-bean-definition-overriding=true
eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/

# 开启Feign下面的Hystrix功能
feign.hystrix.enabled=true
# 是否开启服务降级
hystrix.command.default.fallback.enabled=true

# 全局超时
hystrix.command.default.execution.timeout.enabled=true
# 超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000
# 超时以后终止线程
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true
# 取消的时候终止线程
hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel=true
# hystrix.command.MyService#retry(int).execution.isolation.thread.timeoutInMilliseconds=3000



# 每台机器最大重试次数
feign-client.ribbon.MaxAutoRetries=0
# 可以再重试几台机器
feign-client.ribbon.MaxAutoRetriesNextServer=0
# 连接超时
feign-client.ribbon.ConnectTimeout=1000
# 业务处理超时
feign-client.ribbon.ReadTimeout=8000
# 在所有HTTP Method进行重试
feign-client.ribbon.OkToRetryOnAllOperations=false

Controller

@RestController
public class Controller {

    @Autowired
    private MyService myService;

    @Autowired
    private RequestCacheService requestCacheService;

    @GetMapping("/fallback")
    public String fallback() {
        return myService.error();
    }

    @GetMapping("/timeout")
    public String timeout(Integer timeout) {
        System.out.println(timeout);
        return myService.retry(timeout);
    }

    @GetMapping("/timeout2")
    @HystrixCommand(
            fallbackMethod = "timeoutFallback",
            commandProperties = {
               @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value="3000")
            }
    )
    public String timeout2(Integer timeout) {
        return myService.retry(timeout);
    }

    public String timeoutFallback(Integer timeout) {
        return "success";
    }

    @GetMapping("/cache")
    public Friend cache(String name) {
        @Cleanup HystrixRequestContext context =
                HystrixRequestContext.initializeContext();

        Friend friend = requestCacheService.requestCache(name);
        friend = requestCacheService.requestCache(name);
        return friend;
    }

}

MyService

@FeignClient(name = "feign-client", fallback = Fallback.class)
public interface MyService extends IService {

}

Fallback 降级处理类

@Slf4j
@Component
public class Fallback implements MyService {

    @Override
    //@HystrixCommand(fallbackMethod = "fallback2")
    public String error() {
        log.info("Fallback: I'm not a black sheep any more");
        throw new RuntimeException("first fallback");
    }

    @HystrixCommand(fallbackMethod = "fallback3")
    public String fallback2() {
        log.info("fallback again");
        throw new RuntimeException("fallback again");
    }

    public String fallback3() {
        log.info("fallback again and again");
        return "success";
    }


    @Override
    public String sayHi() {
        return null;
    }

    @Override
    public Friend sayHiPost(@RequestBody Friend friend) {
        return null;
    }

    @Override
    public String retry(@RequestParam(name = "timeout") int timeout) {
        return "You are late !";
    }

}

RequestCacheService Request Cache减压

@Slf4j
@Service
public class RequestCacheService {

    @Autowired
    private MyService service;

    @CacheResult
    @HystrixCommand(commandKey = "cacheKey")
    public Friend requestCache(@CacheKey String name) {
        log.info("request cache " + name);
        Friend friend = new Friend();
        friend.setName(name);
        friend = service.sayHiPost(friend);
        log.info("after requesting cache " + name);
        return friend;
    }

}

HystrixFallbackApplication启动类

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class HystrixFallbackApplication {

    public static void main(String[] args) throws NoSuchMethodException {
        new SpringApplicationBuilder(HystrixFallbackApplication.class)
                .web(WebApplicationType.SERVLET)
                .run(args);

//        System.out.println(Feign.configKey(MyService.class,
//                MyService.class.getMethod("retry", int.class)));
    }

}

测试

依次启动:
eureka-server:eureka服务中心
feign-client :feign生产者
hystrix-fallback:hystrix降级demo
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

Fallback多级降级测试

测试步骤:
1.通过postman来调用hystrix-fallback fallback接口
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

2.然后通过feign来调用feign-client的error接口来获取一个异常看看能不能降级。spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
3.多级降级处理
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
postman 放回的结果,然后分析一下结果。
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
在feign-client当中 抛出了一个RuntimeException的错误。然后会被hystrix进行降级处理。
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
我们再去hystrix-fallback的控制台看看有没有被降级。
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
这三条输出对应的就是之前多级处理的打印的结果说明 多级降级是成功的。

Timeout降级测试

1.设置全局的超时时间 超过时间就会Timeout降级 这里我是设置的3s
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

2通过postman来调用hystrix-fallback timeout接口
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
3.然后通过feign来调用feign-client的retry接口让线程sleep相应的时间
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
4.如果没有超时就会retrun 出feign-clien端口号 超时了的话就会进入timeout降级处理类
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
5.先测试2s 没有超时的结果
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

6.先然后测试3s 超时的结果
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压

Request Cache减压测试

1.通过postman来调用hystrix-fallback cache接口,然后接口里面连续调用了 两次requestCacheService.requestCache(name);
如果打印两遍相同的log说明没有被缓存到本地,解压失败。
如果只打印一遍og说明有被缓存到本地,解压成功。
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
requestCacheService.requestCache
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
调用接口
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
只打印了一遍Log说明解压成功
spring cloud Feign+Hystrix实现Fallback多级降级,Timeout降级,Request Cache减压
以上有问题请指出来!交流学习

本文地址:https://blog.csdn.net/qq_40297844/article/details/109779276

相关标签: spring cloud java