SpringCloud之Hystrix实战

本文详细介绍了Hystrix作为服务熔断器的作用,防止微服务雪崩,以及在实际使用中的注意事项,如超时配置。通过实例展示了如何在Spring Boot项目中配置和使用Hystrix,包括启动类设置、YAML配置、Controller应用。同时,讲解了Feign整合Hystrix进行服务调用时的配置和测试,包括FeignClient注解的使用以及降级回调的实现。

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

目录

一、Hystrix有什么作用?

二、Hystrix使用注意事项

2.1 Hystrix默认超时时间是1秒

2.2 Hystrix超时时间设置分为两种

2.3 HystrixCommand注解

三、Hystrix使用

3.1 项目目录结构

3.2 portal-server修改

3.2.1 pom.xml文件

3.2.2 启动类开启Hystrix

3.2.3 application.yml配置文件

3.2.4 HystrixController

3.3 测试结果

四、Feign整合Hystrix使用

4.1 说明

4.2 @FeignClient注解

4.3 配置文件application.yml增加feign的hystrix开启功能

4.4 Feign声明式调用接口

4.4.1 feign调用接口GoodsFeignHystrixRemoteService

 4.4.2 GoodsFeignHystrixRemoteServiceFallBack

 4.4.2 GoodsFeignHystrixRemoteServiceFallBackFacttory

4.5 测试结果

 

一、Hystrix有什么作用?

 随着技术的发展,越来越多的项目采用微服务分布式架构;这些服务之间有时需要相互调用的,并且为了保持高可用的状态,是需要集群部署的。但是这些服务之间的调用,因为网络原因和自身存在的一些问题,是不能保证100%调用成功的。如果调用失败,但同时又有大量的请求进来,会占用过多的资源导致服务瘫痪,因为微服务之间是相互调用的,因此可能会导致多个服务都不可用,造成服务雪崩。   

Hystrix是一个用于分布式服务调用的断路器,可以在服务调用超时、异常等情况下进行服务降级和限流,这样就避免了服务调用方的线程不被长时间、不必要的占用,避免了资源的过度占用,造成分布式服务的雪崩。

二、Hystrix使用注意事项

2.1 Hystrix默认超时时间是1秒

2.2 Hystrix超时时间设置分为两种

  • 注解配置
  • 配置文件配置

2.3 HystrixCommand注解

  • fallbackMethod:配置回调方法,即服务降级方法
  • ignoreExceptions:配置不进入降级方法的异常
  • commandProperties:hystrix属性设置,包括超时设置
  • threadPoolkey:线程池唯一标识
  • threadPoolProperties:线程池属性设置,包括核心线程树和队列大小,可以做限流

 

三、Hystrix使用

3.1 项目目录结构

3.2 portal-server修改

3.2.1 pom.xml文件

<?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">
    <parent>
        <artifactId>spring-cloud-study</artifactId>
        <groupId>com.wj</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>portal-server</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.wj</groupId>
            <artifactId>cloud-common-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--引入hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>

</project>

3.2.2 启动类开启Hystrix

  • 注解@EnableCircuitBreaker和注解@EnableHystrix的作用相同,开启Hystrix断路器
  • 注解@SpringCloudApplication注解相当于@EnableCircuitBreaker、@EnableHystrix和@SpringBootApplication的集合
package com.wj.portal.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;

/**
 * @EnableDiscoveryClient和@EnableEurekaClient共同点:让注册中心发现,扫描到该服务。
 * 不同点:@EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient 可以是其他注册中心,比如zookeeper。
 * @EnableCircuitBreaker和@EnableHystrix的作用是一样的,开启断路器;
 * @SpringCloudApplication:此注解的作用相当于@EnableCircuitBreaker、@EnableDiscoveryClient和@SpringBootApplication
 * @author wangjian
 */
//开启eureka客户端
@EnableEurekaClient
//@EnableDiscoveryClient
@EnableFeignClients("com.wj.common.api.feign")//开启feign,并配置扫描路径
@SpringBootApplication
@EnableHystrix//启用hystrix
//@EnableCircuitBreaker
//@SpringCloudApplication
@ComponentScan(value = {"com.wj.portal.server.*","com.wj.common.api.*"})
public class PortalServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(PortalServerApplication.class,args);
    }
}

3.2.3 application.yml配置文件

  • Hystrix的超时配置可在配置文件和注解中配置,两者只需要配置其一
# 端口号配置
server:
  port: 9100

# 应用名称配置
spring:
  application:
    name: portal-server

#eureka客户端配置
eureka:
  instance:
    # 向注册中心发送心跳间隔时间,告诉注册中心自己还活着;默认时间是30s
    lease-renewal-interval-in-seconds: 10
    # 如果30秒内没有向注册中心发送心跳,代表发生故障,从注册中心移除掉,默认时间是90s
    lease-expiration-duration-in-seconds: 30
    #告诉服务端,服务实例以ip作为连接,而不是机器名,默认是false
    prefer-ip-address: true
    #告诉服务端,服务实例的名称
    instance-id: ${spring.application.name}
  client:
    #注册中心连接地址
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/,http://localhost:8762/eureka/

#hystrix配置
#hystrix的超时时间可在配置文件或注解配置
#hystrix.command.default.execution.timeout.enabled说明:
#为true时,需两个方法配置超时设置,分别是Ribbon的ReadTimeout和hystrix的timeoutInMilliseconds,以值小的为准
#为false时,hystrix不进行超时熔断,根据Ribbon的ReadTimeout抛出的异常进行熔断,具体情况取决于ribbon的connectTimeout配置的超时时间和其他情况为准
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true #为true时,需两个方法配置超时设置,分别是Ribbon的ReadTimeout和hystrix的timeoutInMilliseconds,以值小的为准
        isolation:
          thread:
            timeoutInMilliseconds: 5000
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000

3.2.4 HystrixController

package com.wj.portal.server.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.wj.common.api.base.Result;
import com.wj.common.api.entity.Goods;
import com.wj.common.api.feign.GoodsRemoteService;
import com.wj.portal.server.constants.GoodsUrlConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * hystrix控制器
 * @author wangjian
 */
@RestController
@RequestMapping("/hystrix")
public class HystrixController {

    //注入RestTemplate
    @Autowired
    private RestTemplate restTemplate;

    /**
     * hystrix调用获取产品列表
     * hystrix说明:
     *      1.默认超时时间是1秒
     *      2.超时时间设置有两种方式,配置一种即可:
     *          2.1 注解配置:具体详情见下方注解配置
     *          2.2 配置文件配置:具体情况见配置文件
     *      3.可以用作限流:
     *          3.1 threadPoolKey:线程池唯一标识
     *          3.2 threadPoolProperties:线程池配置
     * @HystrixCommand说明:
     *      1.fallbackMethod:配置服务降级方法
     *      2.ignoreExceptions:配置抛出的异常不进入服务降级方法
     *      3.commandProperties:配置hystrix超时设置
     * @return
     */
    @HystrixCommand(
            //降级方法配置
            fallbackMethod = "fallback",
            //忽略异常配置
            ignoreExceptions = {Throwable.class,Exception.class},
            //超时配置
            commandProperties = {
                    @HystrixProperty(name = "execution.timeout.enabled",value = "true"),
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
            },
            //线程池配置
            threadPoolKey = "limit",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize",value ="2"),
                    @HystrixProperty(name = "maxQueueSize",value = "1")
            }
    )
    @GetMapping("/goods/hystrix/list")
    public Result<List<Goods>> feignList(){
        //设置4秒,测试超时降级
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /*
         * 默认情况下,不论是此方法,还是远程调用的方法发生异常或超时,都会进行服务降级,
         * 除非配置了忽略异常,调用的时长小于配置的时长不会进行服务降级
         */
        //远程调用
        ResponseEntity<Result> forEntity = restTemplate.getForEntity(GoodsUrlConstant.GOODS_LIST_URL, Result.class);
        Result result = forEntity.getBody();
        //测试调用者抛出异常降级
//        throw new RuntimeException("运行异常");
        return result;
    }

    /**
     * 回调降级方法
     * throwable:抛出的异常
     * 说明:
     *      1.默认情况,不论是服务调用者还是服务提供者抛出异常都会进行服务降级
     *      2.回调降级方法加上Throwable,可以捕获到抛出的异常
     * @return
     */
    public Result<List<Goods>> fallback(Throwable throwable){
        throwable.printStackTrace();
        return Result.error(400,"服务降级!");
    }

}

3.3 测试结果

四、Feign整合Hystrix使用

4.1 说明

  • SpringCloud Dalston版本默认关闭,需配置打开,不然feign调用不能熔断降级;
  • SpringCloud新的版本feign调用同一个服务必须写在同一个feign调用接口中,具体从哪一个版本开始的没有去验证
  • feign的声明接口的Fallback和FallbackFactory只能用一个,两个同时配置,只能Fallback生效,FallbackFactory不能生效

4.2 @FeignClient注解

  • value:指定调用的服务在注册中心的名称
  • fallback:指定feign调用失败降级的接口实现类
  • fallbackFactory:捕获降级的具体异常

4.3 配置文件application.yml增加feign的hystrix开启功能

# 端口号配置
server:
  port: 9100

# 应用名称配置
spring:
  application:
    name: portal-server

#eureka客户端配置
eureka:
  instance:
    # 向注册中心发送心跳间隔时间,告诉注册中心自己还活着;默认时间是30s
    lease-renewal-interval-in-seconds: 10
    # 如果30秒内没有向注册中心发送心跳,代表发生故障,从注册中心移除掉,默认时间是90s
    lease-expiration-duration-in-seconds: 30
    #告诉服务端,服务实例以ip作为连接,而不是机器名,默认是false
    prefer-ip-address: true
    #告诉服务端,服务实例的名称
    instance-id: ${spring.application.name}
  client:
    #注册中心连接地址
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/,http://localhost:8762/eureka/

#hystrix配置
#hystrix的超时时间可在配置文件或注解配置
#hystrix.command.default.execution.timeout.enabled说明:
#为true时,需两个方法配置超时设置,分别是Ribbon的ReadTimeout和hystrix的timeoutInMilliseconds,以值小的为准
#为false时,hystrix不进行超时熔断,根据Ribbon的ReadTimeout抛出的异常进行熔断,具体情况取决于ribbon的connectTimeout配置的超时时间和其他情况为准
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true #为true时,需两个方法配置超时设置,分别是Ribbon的ReadTimeout和hystrix的timeoutInMilliseconds,以值小的为准
        isolation:
          thread:
            timeoutInMilliseconds: 5000
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000


#feign整合hystrix配置
#SpringCloud Dalston版本默认关闭,需配置打开,不然feign调用不能熔断降级
feign:
  hystrix:
    enabled: true

4.4 Feign声明式调用接口

4.4.1 feign调用接口GoodsFeignHystrixRemoteService

package com.wj.common.api.feign;

import com.wj.common.api.base.Result;
import com.wj.common.api.entity.Goods;
import com.wj.common.api.feign.factory.GoodsFeignHystrixRemoteServiceFallBackFacttory;
import com.wj.common.api.feign.fallback.GoodsFeignHystrixRemoteServiceFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

/**
 * Feign整合Hystrix
 *      fallback:指定降级的fallback
 *      fallbackFactory:捕获降级的具体异常
 * 注意问题:
 *      需要调用同一个服务的不同方法时,需写在同一个feign调用接口内,
 *      否则会出现异常:
 *          "The bean 'goods-server.FeignClientSpecification', defined in null,
 *          could not be registered. A bean with that name has already been defined in null and overriding is disabled."
 *       这里都是调用goods-server的服务,我写在了两个feign接口中:GoodsFeignHystrixRemoteService和GoodsRemoteService
 *       是为了区分feign组件和feign整合Hystrix的用法,因此启动项目时,需要注释掉一个
 * @author wangjian
 */
@FeignClient(value = "goods-server",/*fallback = GoodsFeignHystrixRemoteServiceFallBack.class,*/
        fallbackFactory = GoodsFeignHystrixRemoteServiceFallBackFacttory.class)
public interface GoodsFeignHystrixRemoteService {

    /**
     * feign整合hystrix产品提供者
     * 获取产品列表
     * @return
     */
    @GetMapping("/feignHystrix/goods/list")
    public Result<List<Goods>> feignHystrixList();

    /**
     * feign整合hystrix产品提供者
     * 获取产品详情
     * @return
     */
    @GetMapping("/feignHystrix/goods/info")
    Result<Goods> feignHystrixInfo();
}

 4.4.2 GoodsFeignHystrixRemoteServiceFallBack

package com.wj.common.api.feign.fallback;

import com.wj.common.api.base.Result;
import com.wj.common.api.entity.Goods;
import com.wj.common.api.feign.GoodsFeignHystrixRemoteService;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * feign整合hystrix,服务降级
 * @author wangjian
 */
@Component
public class GoodsFeignHystrixRemoteServiceFallBack implements GoodsFeignHystrixRemoteService {
    @Override
    public Result<List<Goods>> feignHystrixList() {
        return Result.ok("goods-server服务降级!");
    }

    @Override
    public Result<Goods> feignHystrixInfo() {
        return Result.ok("goods-server服务降级!");
    }
}

 4.4.2 GoodsFeignHystrixRemoteServiceFallBackFacttory

package com.wj.common.api.feign.factory;

import com.wj.common.api.base.Result;
import com.wj.common.api.entity.Goods;
import com.wj.common.api.feign.GoodsFeignHystrixRemoteService;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * feign整合hystrix异常处理,获取具体的服务错误信息
 * @author wangjian
 */
@Component
public class GoodsFeignHystrixRemoteServiceFallBackFacttory implements FallbackFactory<GoodsFeignHystrixRemoteService> {
    @Override
    public GoodsFeignHystrixRemoteService create(Throwable throwable) {
        return new GoodsFeignHystrixRemoteService() {
            @Override
            public Result<List<Goods>> feignHystrixList() {
                throwable.printStackTrace();
                return Result.error(400,"feign调用产品列表服务异常:"+throwable.getMessage());
            }

            @Override
            public Result<Goods> feignHystrixInfo() {
                throwable.printStackTrace();
                return Result.error(400,"feign调用获取详情服务异常:"+throwable.getMessage());
            }
        };
    }
}

4.5 测试结果

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值