微服务熔断与降级

服务熔断:

熔断是在服务端进行配置。

一般是某个服务故障,或者异常引起的,类似现实世界中的保险丝 ,当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时。

服务降级:

降级是在客户端配置。

所谓降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。降级逻辑可以是返回默认值、调用备用服务等。

服务熔断类型有下面3中状态:

  • 熔断打开:服务发生异常则不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当超过MTTR服务仍然没有恢复正常,则进入半熔断状态。
  • 熔断关闭:服务发生异常也不会对服务进行熔断。
  • 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则,则当前服务恢复正常,关闭熔断。

断路器开启或关闭的条件如下:

  • 开启的条件:当满足下面两个条件之一断路器就会开启。

    • (1)当达到一定的阈值的时候(默认10秒钟超过20个请求次数)。
    • (2)当失败率达到一定的时候(默认10秒内超过50%的请求次数)。
  • 关闭条件:断路器开启之后(默认5秒),这个时候断路器是半开状态,会让其他一个请求进行转发,如果成功,断路器会关闭;若失败,继续开启。

1. 服务熔断与服务降级的触发条件

  • 服务熔断:基于服务调用失败速率和错误比例触发,目的是保护系统。
  • 服务降级:基于服务不可用或响应过慢时主动触发,目的是保障核心功能。

2. 服务熔断与服务降级的实现目标

  • 服务熔断:预防性的机制,避免系统崩溃。
  • 服务降级:应急性的措施,保证服务稳定。
  1. 服务熔断与服务降级的工作时机
  • 服务熔断:熔断器状态根据失败率和时间窗口动态变化。
  • 服务降级:调用失败或响应慢时立即执行降级逻辑。

实战代码:实现服务熔断与服务降级

以下是基于Spring Cloud Netflix Hystrix的服务熔断与服务降级示例,展示如何实现和配置它们。

1. 服务熔断与降级实现

步骤1:添加依赖项

pom.xml

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

步骤2:启用Hystrix

HystrixApplication.java

package com.example.configserver;

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

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

步骤3:创建服务并配置降级与熔断逻辑

MyService.java

package com.example.demo.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

@Service
public class MyService {

    @HystrixCommand(fallbackMethod = "defaultResponse")
    public String riskyService() {
        // 模拟长时间运行的服务调用
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Service response";
    }

    public String defaultResponse() {
        return "Default response";
    }
}

MyController.java

package com.example.demo.controller;

import com.example.demo.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private MyService myService;

    @GetMapping("/risky")
    public String riskyEndpoint() {
        return myService.riskyService();
    }
}
相关推荐
Abladol-aj30 分钟前
并发和并行的基础知识
java·linux·windows
清水白石00830 分钟前
从一个“支付状态不一致“的bug,看大型分布式系统的“隐藏杀机“
java·数据库·bug
Elihuss1 小时前
ONVIF协议操作摄像头方法
开发语言·php
Swift社区5 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht5 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht5 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20245 小时前
Swift 数组
开发语言
吾日三省吾码6 小时前
JVM 性能调优
java
stm 学习ing6 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc7 小时前
《Python基础》之字符串格式化输出
开发语言·python