首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【愚公系列】2023年11月 Java教学课程 190-SpringCloud(Hystrix熔断器介绍和服务降级)

【愚公系列】2023年11月 Java教学课程 190-SpringCloud(Hystrix熔断器介绍和服务降级)

作者头像
愚公搬代码
发布2025-06-02 14:43:18
发布2025-06-02 14:43:18
12500
代码可运行
举报
文章被收录于专栏:历史专栏历史专栏
运行总次数:0
代码可运行

🚀前言

微服务中的熔断器是一种模式,旨在提高应用程序的可靠性和可用性。它是一种机制,用于监视应用程序的运行状况,识别异常情况并在必要时自动断开对不可用服务的访问,以保护整个系统免受失败服务的影响。

熔断器通过设置一个阈值来实现自动断开服务,当服务的错误率超过这个阈值时,熔断器将打开,并快速断开对这个服务的访问,以避免问题蔓延到整个系统。在断开服务的同时,熔断器会向系统发送警报,以通知管理员采取必要的措施。

熔断器在微服务中的作用非常重要,它可以保证应用程序的可用性,在面对故障和异常情况时,保护系统免受影响。因此,熔断器常被认为是微服务系统设计中的核心部分。

🚀一、Hystrix熔断器

SpringCloud提供了Hystrix作为熔断器,Hystrix已经成为微服务治理领域的标准之一。以下是Hystrix熔断器的几个核心组件:

  1. 断路器:断路器状态默认为闭合状态,当超时时间或者失败率超过阈值时,就会打开断路器,这时后续请求会直接返回错误结果,不会继续请求服务提供方,以此保护服务的稳定性。
  2. 线程池:Hystrix会开辟一个线程池处理熔断器相关的请求,通过线程池的管理可以避免因为熔断器的运行导致线程资源不足的问题。
  3. 命令模式:通过将请求封装为一个命令对象,在执行命令的过程中实现熔断器的监控和控制。
  4. 监控面板:Hystrix提供了一个可视化的监控面板,可以查看各个熔断器的状态,包括请求量、请求成功率、异常率等信息。
  5. 回退机制:当熔断器打开后,可以根据策略执行回退操作,比如返回默认值、调用备用接口等来确保系统的稳定性。

除了Hystrix之外,SpringCloud还提供了Resilience4j和Sentinel等熔断器,可以根据具体业务需求选择合适的熔断器。

🔎1.Hystrix概述

Hystrix是Netflix开源的一款用于分布式系统的容错框架。它可以帮助你控制分布式系统中随时可能出现的延迟和故障,从而提高系统的可靠性和稳定性。Hystrix通过隔离服务之间的调用,使得在系统的某个服务出现问题时,不会对整个系统产生影响。同时,它还可以提供实时的监控和统计信息,以帮助你了解系统的运行状况。Hystrix的核心理念是"断路器模式",通过检测服务的异常情况,将服务的请求短路,以避免服务间的级联故障,从而提高系统的可靠性和可用性。

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

🔎2.Hystrix主要功能

Hystrix是一个用于处理分布式系统中的故障和延迟的库,它提供了以下主要功能:

  1. 故障隔离:Hystrix通过将服务调用隔离在独立的线程池中,防止故障在整个系统中传播。如果某个服务出现故障,Hystrix可以快速失败并返回一个备用的响应,而不会影响其他服务的正常运行。
  2. 服务降级:当依赖的服务出现故障或延迟时,Hystrix可以提供备用的响应或执行预定义的降级逻辑,以保证系统的可用性和性能。
  3. 超时控制:Hystrix可以设置每个服务调用的超时时间,当服务调用时间超过设定的阈值时,Hystrix会中断该调用并执行降级逻辑。
  4. 熔断机制:Hystrix通过监控服务调用的失败率和响应时间来实现熔断机制。当失败率或响应时间超过一定的阈值时,Hystrix会打开熔断器,停止对该服务的调用一段时间,以避免对该服务的进一步压力。
  5. 实时监控和指标收集:Hystrix提供了实时监控和指标收集功能,可以通过Hystrix Dashboard或其他监控工具来查看服务调用的状态、失败率、响应时间等指标,以及触发熔断的情况。

🔎3.项目结构

🦋3.1 注册中心源码

1、pom.xml文件

代码语言:javascript
代码运行次数:0
运行
复制
<?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>hystrix-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>

    <dependencies>

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

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

    </dependencies>
</project>

2、EurekaApp文件

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.eureka;

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

@SpringBootApplication
// 启用EurekaServer
@EnableEurekaServer
public class EurekaServerApplication {

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

3.application.yml文件

代码语言:javascript
代码运行次数:0
运行
复制
server:
  port: 8761

eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    register-with-eureka: false # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
    fetch-registry: false # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
  server:
    enable-self-preservation: false # 关闭自我保护机制
    eviction-interval-timer-in-ms: 3000 # 检查服务的时间间隔

🔎4.Hystrix降级

服务降级是指在系统出现异常或者高并发等情况下,保证系统的核心功能正常运行,而放弃一些非核心功能的调用,从而避免系统的崩溃或者影响业务。

在微服务中,服务降级比较常见,主要是因为微服务架构中服务之间相互依赖,当某个服务出现异常时,可能会引起整个系统的崩溃。

服务降级的实现方式有多种,常用的方式是设置超时时间和异常处理。当服务返回时间超过预设时间或者发生异常时,可以返回一个默认值或者错误信息,从而保证核心功能的正常运行。

服务降级应该是一个综合性的策略,需要根据具体情况来制定,以避免影响业务。在实际应用中,可以根据服务的重要程度和业务场景来设定服务降级策略。

🦋4.1 服务端降级

hystrix-provider服务端模块

1、引入Hystrix依赖

代码语言:javascript
代码运行次数:0
运行
复制
<?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>cloud-demo</artifactId>
        <groupId>cn.itcast.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hystrix-provider</artifactId>
    <dependencies>

        <!--spring boot 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>


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

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

2、application.yml配置

代码语言:javascript
代码运行次数:0
运行
复制
server:
  port: 8001

eureka:
  instance:
    hostname: localhost # 主机名
    prefer-ip-address: true # 将当前实例的ip注册到eureka server 中。默认是false 注册主机名
    ip-address: 127.0.0.1 # 设置当前实例的ip
    instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} # 设置web控制台显示的 实例id
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
spring:
  application:
    name: hystrix-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

3、启动类添加激活注解

使用@EnableCircuitBreaker启动注解:

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.provider;

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

/**
 * 启动类
 */

@EnableEurekaClient //该注解 在新版本中可以省略
@SpringBootApplication
@EnableCircuitBreaker // 开启Hystrix功能
public class ProviderApp {


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

有的环境会提示@EnableCircuitBreaker is deprecated已弃用,用@EnableHystrix注解代替即可。

3、业务类方法上添加启用

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.provider.domain;

/**
 * 商品实体类
 */
public class Goods {

    private int id;
    private String title;//商品标题
    private double price;//商品价格
    private int count;//商品库存

    public Goods() {
    }

    public Goods(int id, String title, double price, int count) {
        this.id = id;
        this.title = title;
        this.price = price;
        this.count = count;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}
代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.provider.service;

import com.itheima.provider.dao.GoodsDao;
import com.itheima.provider.domain.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Goods 业务层
 */
@Service
public class GoodsService {

    @Autowired
    private GoodsDao goodsDao;


    /**
     * 根据id查询
     * @param id
     * @return
     */
    public Goods findOne(int id){
        return goodsDao.findOne(id);
    }
}
代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.provider.dao;

import com.itheima.provider.domain.Goods;
import org.springframework.stereotype.Repository;

import javax.validation.ReportAsSingleViolation;

/**
 * 商品Dao
 */

@Repository
public class GoodsDao {

    public Goods findOne(int id){
        return new Goods(1,"华为手机",3999,10000);
    }
}

4、使用

使用@HystrixCommand(fallbackMethod ="findOne_fallback")启动降级:

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.provider.controller;

import com.itheima.provider.domain.Goods;
import com.itheima.provider.service.GoodsService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * Goods Controller 服务提供方
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

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

    /**
     * 降级:
     *  1. 出现异常
     *  2. 服务调用超时
     *      * 默认1s超时
     *
     *  @HystrixCommand(fallbackMethod = "findOne_fallback")
     *      fallbackMethod:指定降级后调用的方法名称
     */

    @GetMapping("/findOne/{id}")
    @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
            //设置Hystrix的超时时间,默认1s
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")

    })
    public Goods findOne(@PathVariable("id") int id){

        //1.造个异常
        int i = 3/0;
        try {
            //2. 休眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Goods goods = goodsService.findOne(id);

        goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
        return goods;
    }


    /**
     * 定义降级方法:
     *  1. 方法的返回值需要和原方法一样
     *  2. 方法的参数需要和原方法一样
     */
    public Goods findOne_fallback(int id){
        Goods goods = new Goods();
        goods.setTitle("降级了~~~");

        return goods;
    }

}

注:降级(FallBack)方法必须与其对应的业务方法在同一个类中,否则无法生效。

1、类上加注解:DefaultProperties(defaultFallback=" ")指定全局兜底方法

2、方法加注解:@HystrixCommand

🦋4.2 客户端降级

hystrix-consumer客户端模块

1、引入Hystrix依赖

代码语言:javascript
代码运行次数:0
运行
复制
<?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>cloud-demo</artifactId>
        <groupId>cn.itcast.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hystrix-consumer</artifactId>

    <dependencies>

        <!--spring boot 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>

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

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

    </dependencies>
</project>

2、启动类添加激活注解

使用@EnableFeignClients启动注解:

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient // 激活DiscoveryClient
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients //开启Feign的功能
public class ConsumerApp {


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

3、改yml

我们的客户端是通过feign调用服务端,所以在order工程中修改yml,添加内容:

代码语言:javascript
代码运行次数:0
运行
复制
server:
  port: 9000


eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
spring:
  application:
    name: hystrix-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

# 开启feign对hystrix的支持
feign:
  hystrix:
    enabled: true

3、业务类方法上添加启用

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.consumer.domain;

/**
 * 商品实体类
 */
public class Goods {

    private int id;
    private String title;//商品标题
    private double price;//商品价格
    private int count;//商品库存

    public Goods() {
    }

    public Goods(int id, String title, double price, int count) {
        this.id = id;
        this.title = title;
        this.price = price;
        this.count = count;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}
代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.consumer.feign;


import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;



@FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
public interface GoodsFeignClient {


    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);

}
代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.consumer.feign;

import com.itheima.consumer.domain.Goods;
import org.springframework.stereotype.Component;

/**
 * Feign 客户端的降级处理类
 * 1. 定义类 实现 Feign 客户端接口
 * 2. 使用@Component注解将该类的Bean加入SpringIOC容器
 */
@Component
public class GoodsFeignClientFallback implements GoodsFeignClient {
    @Override
    public Goods findGoodsById(int id) {
        Goods goods = new Goods();
        goods.setTitle("又被降级了~~~");
        return goods;
    }
}

4、使用

代码语言:javascript
代码运行次数:0
运行
复制
package com.itheima.consumer.controller;


import com.itheima.consumer.domain.Goods;
import com.itheima.consumer.feign.GoodsFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/order")
public class OrderController {

    @Qualifier("com.itheima.consumer.feign.GoodsFeignClient")
    @Autowired
    private GoodsFeignClient goodsFeignClient;

    @GetMapping("/goods/{id}")
    public Goods findGoodsById(@PathVariable("id") int id){
        Goods goods = goodsFeignClient.findGoodsById(id);

        return goods;
    }


}

🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🚀前言
  • 🚀一、Hystrix熔断器
    • 🔎1.Hystrix概述
    • 🔎2.Hystrix主要功能
    • 🔎3.项目结构
      • 🦋3.1 注册中心源码
    • 🔎4.Hystrix降级
      • 🦋4.1 服务端降级
      • 🦋4.2 客户端降级
  • 🚀感谢:给读者的一封信
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档