自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

輕松掌握!Spring Boot 集成 Resilience4j 實(shí)現(xiàn)斷路器的全流程實(shí)戰(zhàn)

開發(fā) 前端
斷路器模式 是微服務(wù)架構(gòu)中確保系統(tǒng)健壯性的重要模式之一。它能夠避免由于某個(gè)依賴服務(wù)的故障導(dǎo)致系統(tǒng)的整體崩潰。通過 Resilience4j,我們可以方便地在 Spring Boot 應(yīng)用中集成斷路器功能,并通過配置靈活地調(diào)整其行為。

在現(xiàn)代分布式系統(tǒng)架構(gòu)中,服務(wù)之間的通信非常頻繁,尤其是微服務(wù)架構(gòu)下,每個(gè)微服務(wù)都會(huì)依賴其他服務(wù)的響應(yīng)。雖然這種架構(gòu)能夠有效地提高系統(tǒng)的擴(kuò)展性和靈活性,但也帶來了一些問題,比如網(wǎng)絡(luò)延遲、依賴的服務(wù)不可用、超時(shí)等。為了避免整個(gè)系統(tǒng)因?yàn)槟硞€(gè)服務(wù)不可用而崩潰,我們可以使用 斷路器模式 來防止這種“雪崩效應(yīng)”的發(fā)生。

斷路器模式(Circuit Breaker Pattern)作為一種保護(hù)機(jī)制,可以幫助我們監(jiān)控和控制外部服務(wù)的調(diào)用。在服務(wù)出現(xiàn)故障時(shí),斷路器可以快速響應(yīng)并阻止后續(xù)調(diào)用,從而避免不必要的等待和資源消耗。本文將結(jié)合代碼示例,講解如何在 Spring Boot 項(xiàng)目中使用 Resilience4j 實(shí)現(xiàn)斷路器,并展示如何在前后端代碼中進(jìn)行交互,前端部分使用 Thymeleaf 模板引擎,結(jié)合 jQuery 和 Bootstrap 實(shí)現(xiàn)。

斷路器模式簡(jiǎn)介

斷路器模式 是應(yīng)對(duì)外部服務(wù)故障的一種保護(hù)機(jī)制。它的核心思想是,當(dāng)某個(gè)外部服務(wù)調(diào)用頻繁失敗時(shí),不再繼續(xù)嘗試調(diào)用該服務(wù),而是直接返回一個(gè)預(yù)設(shè)的結(jié)果或執(zhí)行一個(gè)備用邏輯(即回退方法)。斷路器模式通常包含以下三種狀態(tài):

  1. 關(guān)閉狀態(tài) (Closed):當(dāng)服務(wù)正常工作時(shí),斷路器處于關(guān)閉狀態(tài),所有請(qǐng)求都會(huì)直接通過并調(diào)用目標(biāo)服務(wù)。
  2. 打開狀態(tài) (Open):當(dāng)檢測(cè)到服務(wù)連續(xù)多次失敗,斷路器會(huì)進(jìn)入打開狀態(tài),此時(shí)所有請(qǐng)求都會(huì)被快速失敗,直接觸發(fā)回退方法。
  3. 半開狀態(tài) (Half-Open):經(jīng)過一段時(shí)間后,斷路器會(huì)自動(dòng)嘗試允許少量請(qǐng)求通過,如果這些請(qǐng)求成功,斷路器會(huì)回到關(guān)閉狀態(tài);否則,繼續(xù)保持打開狀態(tài)。

這種機(jī)制能夠有效防止系統(tǒng)因?yàn)槟硞€(gè)服務(wù)的不可用而產(chǎn)生的資源浪費(fèi)和響應(yīng)延遲。

運(yùn)行效果:

圖片圖片

若想獲取項(xiàng)目完整代碼以及其他文章的項(xiàng)目源碼,且在代碼編寫時(shí)遇到問題需要咨詢交流,歡迎加入下方的知識(shí)星球。

引入依賴 (pom.xml)

首先,我們需要在 pom.xml 文件中引入相關(guān)的依賴。這里包括 Spring Boot、Resilience4j、Lombok 以及用于模板渲染的 Thymeleaf 依賴。

<?xml versinotallow="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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.icoderoad</groupId>
	<artifactId>circuit-breaker</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>circuit-breaker</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<!-- Spring Boot Starter Web -->
	    <dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-web</artifactId>
	    </dependency>
	
	    <!-- Resilience4j 斷路器 -->
	    <dependency>
		    <groupId>io.github.resilience4j</groupId>
		    <artifactId>resilience4j-spring-boot3</artifactId>
		    <version>2.2.0</version>
		</dependency>
	
	    <!-- Lombok -->
	    <dependency>
	        <groupId>org.projectlombok</groupId>
	        <artifactId>lombok</artifactId>
	        <scope>provided</scope>
	    </dependency>
	
	    <!-- Thymeleaf 模板引擎 -->
	    <dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-thymeleaf</artifactId>
	    </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

配置文件 (application.yml)

接下來,我們需要在 application.yml 中為 Resilience4j 斷路器配置相關(guān)參數(shù)。這些參數(shù)用于定義斷路器的行為,包括滑動(dòng)窗口的大小、失敗率閾值、斷路器打開狀態(tài)的等待時(shí)間等。

resilience4j:
  circuitbreaker:
    configs:
      default:
        slidingWindowSize: 10 # 增大滑動(dòng)窗口以計(jì)算多個(gè)請(qǐng)求的失敗率
        failureRateThreshold: 50 # 設(shè)置更高的失敗率閾值,例如 50%
        waitDurationInOpenState: 10000 # 打開狀態(tài)持續(xù)時(shí)間 10 秒
        permittedNumberOfCallsInHalfOpenState: 3 # 半開狀態(tài)下允許通過的請(qǐng)求數(shù)量
        minimumNumberOfCalls: 5 # 最少需要 5 個(gè)請(qǐng)求才能計(jì)算失敗率
        automaticTransitionFromOpenToHalfOpenEnabled: true
    instances:
      myService:
        baseConfig: default
        
  timeout:
    default:
      timeoutDuration: 2s # 設(shè)置超時(shí)時(shí)間為 2 秒

timeoutDuration:請(qǐng)求超過 2 秒沒有返回時(shí)會(huì)觸發(fā)超時(shí)異常。

failureRateThreshold:將失敗率設(shè)置為 50%,這樣只要一半的請(qǐng)求失敗,斷路器就會(huì)打開。

minimumNumberOfCalls:設(shè)置為 5,以確保在少量請(qǐng)求中也能計(jì)算失敗率

讀取配置類 (@ConfigurationProperties)

我們可以使用 @ConfigurationProperties 注解來讀取配置文件中的斷路器相關(guān)配置,并通過 Lombok 自動(dòng)生成類的 getter 和 setter 方法。

package com.icoderoad.circuit.breaker.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Data;

@Data
@Component
@ConfigurationProperties(prefix = "resilience4j.circuitbreaker")
public class CircuitBreakerProperties {
	
    private CircuitBreakerConfig configs;
    
    private CircuitBreakerInstance instances;

}

package com.icoderoad.circuit.breaker.config;

import lombok.Data;

@Data
class CircuitBreakerConfig {
    private DefaultConfig defaultConfig;
}

package com.icoderoad.circuit.breaker.config;

import lombok.Data;

@Data
class DefaultConfig {
    private int slidingWindowSize;
    private int failureRateThreshold;
    private int waitDurationInOpenState;
}

package com.icoderoad.circuit.breaker.config;

import lombok.Data;

@Data
class CircuitBreakerInstance {
    private MyServiceConfig myService;
}


package com.icoderoad.circuit.breaker.config;

import lombok.Data;

@Data
class MyServiceConfig {
    private String baseConfig;
}

實(shí)體類

假設(shè)我們有一個(gè)簡(jiǎn)單的 User 實(shí)體類,Lombok 可以幫助我們簡(jiǎn)化代碼:

package com.icoderoad.circuit.breaker.entity;

import lombok.Data;

@Data
public class User {
    private Long id;
    private String name;
    private String email;
}

配置類

在你的配置類或主應(yīng)用類中,添加一個(gè)方法,使用 @Bean 注解來定義 RestTemplate。

package com.icoderoad.circuit.breaker.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

斷路器業(yè)務(wù)邏輯實(shí)現(xiàn)

接下來,在服務(wù)層中,我們通過 RestTemplate 調(diào)用外部服務(wù),并為該方法應(yīng)用斷路器。為了模擬外部調(diào)用,我們將把外部服務(wù)調(diào)用更改為服務(wù)內(nèi)部的調(diào)用(例如 /api/internalService),來模擬服務(wù)依賴。

package com.icoderoad.circuit.breaker.service;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class MyService {

    private final RestTemplate restTemplate;

    public MyService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @CircuitBreaker(name = "myService", fallbackMethod = "fallback")
    public String callInternalService() {
        // 模擬服務(wù)內(nèi)調(diào)用
        return restTemplate.getForObject("http://localhost:8080/api/internalService", String.class);
    }

    // 回退方法,當(dāng)斷路器觸發(fā)時(shí)執(zhí)行
    public String fallback(Throwable t) {
        return "內(nèi)部服務(wù)不可用,請(qǐng)稍后再試。";
    }
}

控制器

我們創(chuàng)建一個(gè)控制器來處理前端發(fā)來的請(qǐng)求,并調(diào)用服務(wù)層的 callInternalService 方法。

package com.icoderoad.circuit.breaker.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.icoderoad.circuit.breaker.service.MyService;

@RestController
public class CircuitBreakerController {

    private final MyService myService;

    public CircuitBreakerController(MyService myService) {
        this.myService = myService;
    }

    @GetMapping("/api/call")
    public String callService() {
        return myService.callInternalService();
    }
}

另外,為了模擬外部調(diào)用服務(wù)的內(nèi)部服務(wù)接口,我們可以簡(jiǎn)單創(chuàng)建一個(gè)模擬的內(nèi)部服務(wù)端點(diǎn)。

package com.icoderoad.circuit.breaker.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class InternalServiceController {

    @GetMapping("/api/internalService")
    public String internalService() {
    	try {
            // 模擬服務(wù)延遲5秒,超過Resilience4j設(shè)置的2秒超時(shí)
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "服務(wù)調(diào)用失敗!";
        }
        // 模擬隨機(jī)失敗
        if (Math.random() > 0.5) {
            throw new RuntimeException("模擬服務(wù)異常");
        }
        return "服務(wù)調(diào)用成功!";
    }
}

在這個(gè)例子中,我們使用 RestTemplate 發(fā)起對(duì)本地服務(wù)的調(diào)用,模擬服務(wù)依賴。當(dāng)請(qǐng)求失敗時(shí),

斷路器會(huì)進(jìn)入打開狀態(tài),隨后的請(qǐng)求將直接調(diào)用 fallback 方法,返回一個(gè)預(yù)定義的消息以避免等待。

前端實(shí)現(xiàn) (Thymeleaf + jQuery + Bootstrap)

前端部分將使用 Thymeleaf 作為模板引擎,結(jié)合 jQuery 和 Bootstrap 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的界面,用戶可以通過點(diǎn)擊按鈕來觸發(fā)服務(wù)調(diào)用,并顯示結(jié)果。

在 src/main/resources/templates 目錄下創(chuàng)建 index.html 文件:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Resilience4j 斷路器示例</title>
    <link rel="stylesheet" >
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
</head>
<body>
    <div class="container">
        <h1>斷路器示例</h1>
        <button id="callService" class="btn btn-primary">調(diào)用服務(wù)</button>
        <div id="response" class="mt-3"></div>
    </div>

    <script>
        $('#callService').click(function () {
            $.ajax({
                url: '/api/call',
                type: 'GET',
                success: function (data) {
                    $('#response').text(data);
                },
                error: function () {
                    $('#response').text('服務(wù)調(diào)用失??!');
                }
            });
        });
    </script>
</body>
</html>

在這個(gè)前端頁面中,當(dāng)用戶點(diǎn)擊按鈕時(shí),將通過 jQuery 發(fā)起一個(gè) AJAX 請(qǐng)求,并顯示服務(wù)的響應(yīng)結(jié)果。

斷路器的運(yùn)行機(jī)制及測(cè)試

啟動(dòng)應(yīng)用后,訪問頁面 http://localhost:8080并點(diǎn)擊“調(diào)用服務(wù)”按鈕,系統(tǒng)會(huì)嘗試調(diào)用 /api/internalService。在正常情況下,頁面會(huì)顯示“服務(wù)調(diào)用成功!”的響應(yīng)。但如果在短時(shí)間內(nèi)多次觸發(fā)失?。梢允謩?dòng)引入錯(cuò)誤或拋出異常),斷路器會(huì)打開,此時(shí)調(diào)用會(huì)返回回退方法的結(jié)果 “內(nèi)部服務(wù)不可用,請(qǐng)稍后再試?!?/p>

通過觀察,可以看到斷路器的幾種狀態(tài)變化:

  1. 在正常工作時(shí),服務(wù)調(diào)用正常。
  2. 當(dāng)連續(xù)失敗達(dá)到閾值時(shí),斷路器打開,直接返回回退方法的結(jié)果。
  3. 一段時(shí)間后,斷路器進(jìn)入半開狀態(tài),允許部分請(qǐng)求通過,如果恢復(fù)正常則關(guān)閉斷路器。

結(jié)論

斷路器模式 是微服務(wù)架構(gòu)中確保系統(tǒng)健壯性的重要模式之一。它能夠避免由于某個(gè)依賴服務(wù)的故障導(dǎo)致系統(tǒng)的整體崩潰。通過 Resilience4j,我們可以方便地在 Spring Boot 應(yīng)用中集成斷路器功能,并通過配置靈活地調(diào)整其行為。

本文詳細(xì)講解了如何通過 Spring Boot 與 Resilience4j 實(shí)現(xiàn)斷路器模式,并結(jié)合 Thymeleaf 前端模板與 jQuery 的異步請(qǐng)求展示了一個(gè)完整的前后端交互流程。在實(shí)際項(xiàng)目中,可以進(jìn)一步擴(kuò)展 Resilience4j 的功能,比如結(jié)合 限流、重試 等模式,以提高系統(tǒng)的可用性和穩(wěn)定性。通過這種機(jī)制,不僅能夠提高系統(tǒng)對(duì)不可預(yù)見故障的處理能力,還能為用戶提供更好的體驗(yàn),減少因?yàn)榉?wù)不可用帶來的負(fù)面影響。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2024-10-11 18:31:14

2022-11-16 17:16:41

spring限流

2021-12-15 08:15:26

Spring Circuit BreSpring Clou

2021-12-09 08:57:46

Spring ClouCircuit Bre斷路器

2023-06-27 07:31:59

微服務(wù)容錯(cuò)庫重試

2023-03-13 08:02:55

斷路器應(yīng)用API

2022-09-15 15:25:47

spring-微服務(wù)

2025-04-09 11:15:00

服務(wù)熔斷服務(wù)降分布式系統(tǒng)

2020-04-23 15:59:04

SpringKafka集群

2025-02-12 07:13:54

Knife4jAPISpringBoot

2018-11-02 15:45:41

Spring BootRedis數(shù)據(jù)庫

2025-04-03 07:56:08

電子簽名合同系統(tǒng)Spring

2022-10-08 11:39:56

斷路器Golang項(xiàng)目

2025-02-17 00:00:45

接口支付寶沙箱

2025-03-31 00:44:00

JavaAI開發(fā)

2025-03-11 08:20:58

2023-10-07 10:08:54

2009-10-12 13:18:55

RHEL 4內(nèi)核

2025-03-03 08:00:00

SpringBootEasyExcel數(shù)據(jù)導(dǎo)出
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)