微服務(wù)架構(gòu)中的穩(wěn)定性保障:服務(wù)熔斷、降級和限流策略詳解

2024-12-27 14:14 更新

大家好,我是V哥,國足0-7不敵日本,創(chuàng)下12年來最大慘敗,真的好久不看球賽了,我關(guān)心的是,作為國內(nèi)唯一一家轉(zhuǎn)播平臺愛奇藝體育昨天崩了,官方道歉文中解釋由于瞬時流量過大導(dǎo)致,這讓我想起服務(wù)熔斷、降級和限流是微服務(wù)架構(gòu)中用于提高系統(tǒng)穩(wěn)定性和可用性的三種關(guān)鍵策略。

介紹

服務(wù)熔斷(Circuit Breaker)

服務(wù)熔斷是一種防止服務(wù)故障蔓延的機制。它的概念來源于電力系統(tǒng)中的熔斷器,當(dāng)電流超過電路的承載能力時,熔斷器會自動斷開電路,以防止火災(zāi)等嚴(yán)重事故的發(fā)生。

在軟件架構(gòu)中,熔斷器模式通常用于處理服務(wù)調(diào)用鏈中的遠(yuǎn)程服務(wù)調(diào)用。當(dāng)某個服務(wù)調(diào)用失敗的次數(shù)超過預(yù)設(shè)閾值時,熔斷器會“斷開”,暫時停止對該服務(wù)的調(diào)用。這樣,系統(tǒng)可以快速失敗,避免長時間的等待或大量的錯誤,從而保持系統(tǒng)的穩(wěn)定性。在熔斷期間,通常會提供一個備用的行為或返回一個友好的錯誤信息。

服務(wù)降級(Service Degradation)

服務(wù)降級是一種在系統(tǒng)負(fù)載過高或某些服務(wù)不可用時,臨時關(guān)閉一些功能或降低服務(wù)標(biāo)準(zhǔn)的策略,以保證核心業(yè)務(wù)的正常運行。

在一個電商平臺中,當(dāng)遇到流量高峰時,可能會暫時關(guān)閉一些非核心功能,如商品推薦、優(yōu)惠券發(fā)放等,以減輕服務(wù)器壓力。或者,當(dāng)支付服務(wù)不可用時,系統(tǒng)可能會允許用戶將商品加入購物車,但暫時無法完成購買。

服務(wù)降級的目的是犧牲一部分用戶體驗,以確保系統(tǒng)不會因為過載而完全崩潰。

服務(wù)限流(Rate Limiting)

服務(wù)限流是一種控制服務(wù)調(diào)用頻率的策略,以保護系統(tǒng)不被過量的請求壓垮。

限流可以通過各種方式實現(xiàn),例如:

  • 令牌桶:按照固定速率向桶中添加令牌,每次請求需要消耗一個令牌。
  • 漏桶:請求以固定速率從桶中流出,如果流出速度跟不上請求速度,多余的請求會被拒絕。
  • 固定窗口計數(shù)器:在固定時間窗口內(nèi)計數(shù)請求次數(shù),超過限制則拒絕服務(wù)。

限流可以應(yīng)用于API網(wǎng)關(guān),以控制對下游服務(wù)的訪問頻率,也可以應(yīng)用于服務(wù)內(nèi)部,以控制處理請求的速度。

高并發(fā)的電商購物車服務(wù)案例

假設(shè)在一個高并發(fā)的電商購物車服務(wù)案例,實現(xiàn)服務(wù)熔斷、降級和限流。我們將使用Spring Boot和Spring Cloud Alibaba Sentinel來實現(xiàn)這些功能。

1. 項目結(jié)構(gòu)

假設(shè)我們的項目結(jié)構(gòu)如下:

shopping-cart-service
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── shoppingcart
│   │   │               ├── ShoppingCartApplication.java
│   │   │               ├── controller
│   │   │               │   └── ShoppingCartController.java
│   │   │               ├── service
│   │   │               │   └── ShoppingCartService.java
│   │   │               └── config
│   │   │                   └── SentinelConfig.java
│   │   └── resources
│   │       ├── application.yml
│   │       └── flow-rules.json
└── .gitignore

2. 添加依賴

pom.xml中添加Spring Boot和Spring Cloud Alibaba Sentinel依賴:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Cloud Alibaba Sentinel -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!-- Spring Boot Starter Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR9</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>

3. 應(yīng)用主類

ShoppingCartApplication.java中創(chuàng)建Spring Boot應(yīng)用:

package com.example.shoppingcart;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


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

4. 配置文件

application.yml中配置Sentinel Dashboard地址:

server:
  port: 8080


spring:
  application:
    name: shopping-cart-service


spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      datasource:
        ds1:
          type: file
          data-id: ${spring.application.name}-flow-rules
          rule-type: flow
          url: file:///path/to/your/flow-rules.json

5. 熔斷、降級和限流規(guī)則

flow-rules.json中配置熔斷、降級和限流規(guī)則:

[
  {
    "resource": "addCart",
    "limitApp": "default",
    "grade": 1,
    "strategy": 0,
    "controlBehavior": 0,
    "threshold": 10,
    "action": 1
  },
  {
    "resource": "addCart",
    "limitApp": "default",
    "grade": 0,
    "strategy": 0,
    "controlBehavior": 1,
    "threshold": 5,
    "action": 1
  },
  {
    "resource": "addCart",
    "limitApp": "default",
    "grade": 0,
    "strategy": 0,
    "controlBehavior": 0,
    "threshold": 20,
    "action": 2
  }
]

6. 控制器

ShoppingCartController.java中創(chuàng)建REST API:

package com.example.shoppingcart.controller;


import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.shoppingcart.service.ShoppingCartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class ShoppingCartController {


    @Autowired
    private ShoppingCartService shoppingCartService;


    @GetMapping("/addCart")
    public String addCart(@RequestParam String productId, @RequestParam int quantity) {
        try (Entry entry = SphU.entry("addCart")) {
            return shoppingCartService.addCart(productId, quantity);
        } catch (BlockException ex) {
            return shoppingCartService.fallback();
        }
    }
}

7. 服務(wù)

ShoppingCartService.java中實現(xiàn)業(yè)務(wù)邏輯:

package com.example.shoppingcart.service;


public class ShoppingCartService {


    public String addCart(String productId, int quantity) {
        // 模擬業(yè)務(wù)邏輯
        if (quantity > 10) {
            throw new RuntimeException("Quantity too large");
        }
        return "Added " + quantity + " of " + productId + " to cart";
    }


    public String fallback() {
        return "Cart service is temporarily unavailable";
    }
}

8. 配置類

SentinelConfig.java中配置Sentinel規(guī)則:

package com.example.shoppingcart.config;


import com.alibaba.csp.sentinel.init.InitConfig;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


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


@Configuration
public class SentinelConfig {


    @Bean
    public InitConfig initConfig() {
        InitConfig initConfig = new InitConfig();
        initConfig.setDataSource("file", "classpath:flow-rules.json");
        return initConfig;
    }


    @Bean
    public List<FlowRule> flowRules() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule("addCart");
        rule.setCount(10); // 限流閾值
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // QPS模式
        rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); // 直接拒絕
        rules.add(rule);
        return rules;
    }


    @Bean
    public List<DegradeRule> degradeRules() {
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule("addCart");
        rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // 響應(yīng)時間模式
        rule.setCount(500); // 響應(yīng)時間閾值
        rule.setTimeWindow(10); // 時間窗口
        rule.setMinRequestAmount(5); // 最小請求量
        rules.add(rule);
        return rules;
    }
}

9. 啟動Sentinel Dashboard

確保你已經(jīng)啟動了Sentinel Dashboard,可以通過以下命令啟動:

java -jar sentinel-dashboard.jar

10. 運行應(yīng)用

運行ShoppingCartApplication,然后通過瀏覽器或Postman測試API:

http://localhost:8080/addCart?productId=123&quantity=5

解釋一下

  1. 熔斷:當(dāng)addCart方法的調(diào)用次數(shù)超過10次時,Sentinel會觸發(fā)熔斷,直接返回降級邏輯。
  2. 降級:當(dāng)addCart方法的響應(yīng)時間超過500ms,或者調(diào)用次數(shù)超過5次時,Sentinel會觸發(fā)降級,返回降級邏輯。
  3. 限流:當(dāng)addCart方法的調(diào)用次數(shù)超過10次時,Sentinel會觸發(fā)限流,直接拒絕請求。

通過這些配置,我們可以在高并發(fā)場景下保護我們的服務(wù),避免系統(tǒng)過載。

最后

  • 熔斷:當(dāng)服務(wù)不可用時,快速失敗,避免系統(tǒng)過載。
  • 降級:在系統(tǒng)壓力較大時,暫時關(guān)閉或降低非核心服務(wù)的質(zhì)量,保證核心服務(wù)的可用性。
  • 限流:控制請求的速率,防止系統(tǒng)因請求過多而崩潰。

這三種策略通常結(jié)合使用,以提高大型分布式系統(tǒng)的穩(wěn)定性和可用性。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號