# 熔断降级

在调用关系复杂的微服务系统中，任何一个调用节点的问题都可能导致整个调用链的“雪崩”。服务熔断技术的核心思想是调用超过一定时间时，采用备用的策略（降级）。

熔断技术可以分为服务端熔断和客户端熔断两种。

{% hint style="info" %}
是否采用熔断技术要根据系统实际情况决定，如果服务极少被其他系统调用，不建议使用熔断。
{% endhint %}

## 依赖

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

## 配置

开发者需要在入口类上配置`@EnableCircuitBreaker`启用熔断的支持。

{% code title="DemoApplication.java" %}

```java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
@EnableDiscoveryClient
@EnableCircuitBreaker
public class DemoApplication {

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

{% endcode %}

## 服务端熔断

服务端熔断只需在必要的业务方法增加`@HystrixCommand`注解，通过`fallbackMethod`属性指定降级的方法即可。降级方法一般来说返回默认值即可。

{% code title="FooService.java" %}

```java
package com.example.demo.service;

import com.example.demo.*;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.taocares.commons.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class FooService {

    @Autowired
    private FooRepository fooRepository;

    @HystrixCommand(fallbackMethod = "findAllFallback")
    public List<FooDto> findAll() {
        List<Foo> fooList = fooRepository.findAll();
        return BeanUtils.copyProperties(fooList, FooDto.class);
    }

    public List<FooDto> findAllFallback() {
        return new ArrayList<>();
    }
}
```

{% endcode %}

## 客户端熔断

很多时候，服务调用者希望自己维护降级策略（调用失败时的处理、超时时长等），借助Feign我们可以很方便的和Hystrix集成。

配置文件中需要启用Feign对Hystrix的支持：

{% code title="application.yml" %}

```yaml
feign:
  hystrix:
    enabled: true
```

{% endcode %}

开发者只需配置`@FeignClient`注解的`fallback`属性指定对应的降级类即可。

{% code title="FooClient.java" %}

```java
package com.example.demo.client;

import com.example.demo.dto.FooDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(name = "foo-service", path = "/foos", fallback = FooClientFallback.class)
public interface FooClient {

    @GetMapping("/{id}")
    FooDto findById(@PathVariable("id") Long fooId);
}
```

{% endcode %}

一般来说，降级类实现远程接口定义，以便保证和原始接口的一致性。

{% code title="FooClientFallback.java" %}

```java
package com.example.demo.client;

import com.example.demo.dto.FooDto;
import org.springframework.stereotype.Component;

@Component
public class FooClientFallback implements FooClient {

    @Override
    public FooDto findById(Long fooId) {
        return null;
    }
}
```

{% endcode %}

## 参考文档

关于Hystrix技术的更多内容请参考官方文档：<https://cloud.spring.io/spring-cloud-static/Finchley.SR1/multi/multi__circuit_breaker_hystrix_clients.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://taocares.gitbook.io/development-guide/kai-fa-zhi-nan/rong-duan-jiang-ji.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
