2023-08-07
原文作者:Ressmix 原文地址:https://www.tpvlog.com/article/268

我之前讲解Hystrix时,都是使用原生的Netfilx Hystrix,但实践中我们一般不会直接使用。所以本章,我将讲解如何在Spring Cloud中使用Hystrix,Spring Cloud对Hystrix进行了封装,我之前已经讲解过了Eureka、Ribbon、Feign,事实上,Spring Cloud Netflix Hystrix既可以独立使用,也可以和Feign整合在一起,本章我会分别讲解这两种使用方式。

关于Spring Cloud Netflix Hystrix使用的更多介绍,可以参考官方文档:https://docs.spring.io/spring-cloud-netflix/docs/2.2.5.RELEASE/reference/html/#circuit-breaker-hystrix-clients。

一、独立使用

我们先来看下如何独立使用Spring Cloud Netflix Hystrix。首先需要引入spring-cloud-starter-netflix-hystrix这个maven依赖。我这里继续沿用《透彻理解Spring Cloud(二七)——Feign基本使用》中的示例。

1.1 Maven依赖

首先,在ServiceB工程中添加Maven依赖:

    <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.tpvlog</groupId>
          <artifactId>serviceB</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <packaging>jar</packaging>
    
          <name>serviceB</name>
          <url>http://maven.apache.org</url>
    
          <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          </properties>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.6.RELEASE</version>
        </parent>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Hoxton.SR8</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>com.tpvlog</groupId>
                <artifactId>service-a-api</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-netflix-eureka-client</artifactId>
                <version>2.2.5.RELEASE</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </project>

1.2 启动类

启动类中需要加上@EnableCircuitBreaker@EnableHystrix注解:

    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients
    @EnableCircuitBreaker
    public class ServiceBApplication {
        public static void main(String[] args) {
            SpringApplication.run(ServiceBApplication.class, args);
        }
    }

@EnableHystrix注解仅仅是对@EnableCircuitBreaker注解的一个包装而已。

1.3 服务类

最后是服务类,这里用了一个@HystrixCommand注解,Spring Cloud会为我们生成一个代理类,最终方法的执行会交给代理类,fallbackMethod指定了降级逻辑:

    @Service
    public class SomeService {
    
        @HystrixCommand(fallbackMethod = "defaultStores",commandProperties = {
          @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
        })
        public Object getStores(Map<String, Object> parameters) {
            //do stuff that might fail
        }
    
        // 降级方法
        public Object defaultStores(Map<String, Object> parameters) {
            return /* something useful */;
        }
    }

我们还可以通过注解中的commandProperties属性配置HystrixCommand的参数,比如execution.isolation.strategy表示配置资源隔离策略。

二、整合Feign

我们再来看下如何将Feign和Hystrix整合在一起。默认情况下,Hystrix的group name就是ServiceA这种服务名称,也就是说你要调用一个服务的话,那么针对每个服务就有一个线程池,然后针对服务的每个接口方法,对应有一个自动生成的HystrixCommand,CommandKey是接口类#方法名

2.1 配置文件

首先,需要在配置文件中开启Hystrix:

    # To enbale Hystrix in Feign
    feign:
      hystrix:
        enabled: true
    
    # To set thread isolation to SEMAPHORE
    hystrix:
      command:
        default:
          execution:
            isolation:
              strategy: SEMAPHORE

然后可以通过hystrix.command.XXX配置Hystrix的参数,我这里用了default,表示对所有HsystrixCommand生效。我们也可以用具体的服务名称替换,比如serviceA。

2.2 服务类

接着,需要在服务接口中添加fallback配置,表示降级逻辑:

    @FeignClient(name = "ServiceA",fallback = ServiceAClientFallback.class)    
    public interface ServiceAClient extends ServiceAInterface {
    }
    static class ServiceAClientFallback implements ServiceAClient {
        public String sayHello() {
            // 降级机制
        }
    }

如果我们需要知道fallback异常的原因,可以使用fallbackFactory

    @FeignClient(name = "ServiceA",fallbackFactory = ServiceAClientFallbackFactory.class)    
    public interface ServiceAClient extends ServiceAInterface {
    }
    static class ServiceAClientFallbackFactory implements FallbackFactory<ServiceAClient> {
        @Override
        public ServiceAClient create(Throwable cause) {
            return new ServiceAClient() {
                @Override
                public String sayHello() {
                    return "fallback; reason was: " + cause.getMessage();
                }
            };
        }
    }

三、总结

本章,我讲解了Spring Cloud Netflix Hystrix的两种使用方式,事实上它们的底层原理是一样的,我后续分析源码时会详细讲解。另外,Hystrix在使用时,一般也会用它的统计仪表盘——Hystrix DashboardTurbine,我这里就不再赘述了,它们的使用都很简单,读者可以参考Spring Cloud 官方文档。

阅读全文