springcloud中Hystrix的使用

说明

Hystrix

提供了服务熔断、降级、限流、服务监控的功能

场景说明:当访问量激增或者某服务发生故障,调用者会一直等待,然后就会发生一连串的连锁反应,倒是服务器的大面积的瘫痪,为了应对此种情况,需要用到Hystrix做系统的保护。

熔断、降级、限流

降级(丢车保帅):在秒杀时,通过服务降级把注册、修改个人信息等非核心功能关闭掉。
熔断:支付依赖第三方服务,要设置熔断策略,熔断后要给出友好提示,比如10分钟后再来支付。
限流:抢购下单接口采用限流方式,如抢购1000件商品,则设置2000大小的队列,请求超过2000后直接拒绝掉。

测试降级

说明: 1、使用到了eureka、openFeign,我以前的博客有相应的搭建细节

​ 2、降级可以配置在生产者或者消费者上,我个人推荐放到消费者上。

搭建生产者

说明: 1、通过等待超时异常来进行测试

pom

<dependencies>
    <!--hystrix-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--eureka client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--web-->
    <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>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

application.yml

server:
  port: 8001

spring:
  application:
    # 服务名称
    name: hystrix-provider

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
      defaultZone: http://localhost:7001/eureka  # 单机版

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
//本服务启动后会自动注册进eureka服务中
@EnableEurekaClient
public class HystrixProvider8001 {
    public static void main(String[] args)
    {
        SpringApplication.run(HystrixProvider8001.class,args);
    }
}

业务类(controller)

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
class PaymentController
{

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

    /**
     * create by: ZhangYiXiong
     * description: 功能说明→ 正常访问
     * create time: 2022/1/26 16:59
     * @params 
     * @return 
     */
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id)
    {
        return serverPort+id;
    }

    /**
     * create by: ZhangYiXiong
     * description: 功能说明→ 模拟超时异常
     * create time: 2022/1/26 16:59
     * @params 
     * @return 
     */
    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) throws InterruptedException
    {
        Thread.sleep(5000);
        return serverPort+id;
    }
}

搭建消费者

pom

<dependencies>
    <!--openfeign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--hystrix-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--eureka client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--web-->
    <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>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

application.ym

server:
  port: 80

spring:
  application:
    # 服务名称消费者
    name: hystrx-consumer

eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
      defaultZone: http://localhost:7001/eureka  # 单机版

# 开启hystrix
feign:
  hystrix:
    enabled: true

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

// 开启hystrix
@EnableHystrix
@SpringBootApplication
@EnableFeignClients
public class HystrixConsumer80 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixConsumer80.class,args);
    }
}

业务类(service)

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "HYSTRIX-PROVIDER")
public interface ConsumerService {

    @GetMapping("/payment/hystrix/ok/{id}")
    String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}

业务类(controller)


import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.xiong.service.ConsumerService;
import javax.annotation.Resource;

@RestController
@Slf4j
//统一异常处理的方法
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class HystrixController {
    
    @Resource
    private ConsumerService consumerService;

    //正常访问
    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    @HystrixCommand
    public String paymentInfo_OK(@PathVariable("id") Integer id)
    {
        String result = consumerService.paymentInfo_OK(id);
        return result;
    }

    //通过hystrix保护
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    @HystrixCommand
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
    {
        String result = consumerService.paymentInfo_TimeOut(id);
        return result;
    }

    //报错访问
    @GetMapping("/consumer/payment/hystrix/timeout2/{id}")
    public String paymentInfo_TimeOut2(@PathVariable("id") Integer id)
    {
        String result = consumerService.paymentInfo_TimeOut(id);
        return result;
    }

    //统一异常处理方法
    public String payment_Global_FallbackMethod()
    {
        return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
    }
}

启动及测试

启动

启动注册中心

启动生产者

启动消费者

测试

分别访问

http://localhost/consumer/payment/hystrix/ok/100
http://localhost/consumer/payment/hystrix/timeout/100
http://localhost/consumer/payment/hystrix/timeout2/100

第一个正常显示、第二个抛出自定义异常、第三个抛出不友好异常

至此测试成功

测试熔断

说明:只修改了8001生产者代码

启动类开启hystrix

@EnableHystrix

新增service

@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",
                commandProperties = {
                    @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),
                })
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
    if(id < 0)
    {
        throw new RuntimeException("******id 不能负数");
    }
    String serialNumber = UUID.randomUUID().toString();

    return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;
}

public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id)
{
    return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " +id;
}

controller中新增方法

@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
    String result = providerService.paymentCircuitBreaker(id);
    log.info("****result: "+result);
    return result;
}

启动并测试

启动

只启动8001服务于注册中心

报错请求

http://localhost:8001/payment/circuit/-100

正常请求

http://localhost:8001/payment/circuit/100

测试

多次访问错误请求,之后再访问正常请求,之后发现正常请求依然报自定义异常,过一段时间后恢复正常

如此则配置成功

测试限流

修改配置文件

1、如果是线程隔离,可以通过线程数+队列大小限制。参数如下:

hystrix.threadpool.default.coreSize

hystrix.threadpool.default.maxQueueSize

hystrix.threadpool.default.queueSizeRejectionThreshold

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds

2、如果是信号量隔离,可以设置最大并发请求数。参数如下:

hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests

实时监控

……

常见面试题

……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值