簡體   English   中英

Spring 引導 Resilience4j 斷路器和回退未實現

[英]Spring Boot Resilience4j circuit breaker and fall back not implementing

我有一個簡單的 rest api 和 Resilience4j 實現,但由於某種原因,斷路器或后備實現不起作用。 我不確定我是否使用了正確的依賴。 我有一個簡單的 member-info-api,它使用另一個 api,稱為 benefit-api。 我已經在 api 調用和創建超時異常的邏輯上實現了斷路器。 當它運行時,它仍然等待超時,然后拋出 TimeOutException。 看起來我的斷路器沒有被實施。 這是我的代碼:

build.gradle

plugins {
    id 'org.springframework.boot' version '2.7.2'
    id 'io.spring.dependency-management' version '1.0.12.RELEASE'
    id 'java'
}

group = 'com.thomsoncodes'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', "2021.0.3")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'io.projectreactor:reactor-test'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

tasks.named('test') {
    useJUnitPlatform()
}

controller class

@RestController
public class WebController {
    public static final Logger LOG = LoggerFactory.getLogger(WebController.class);
    @Autowired
    private MemberInfoService memberInfoService;
    
    @GetMapping("member/{memId}")
    public ResponseEntity<MemberInfo> memberInfo(@PathVariable("memId") String memId) throws TimeoutException { 
        LOG.info("---Beginning of the WebController.methodmemberInfo()---");
        MemberInfo resp = null;
        resp = memberInfoService.getMemberInfo(memId);
        
        LOG.info("---End of the WebController.methodmemberInfo()---");
        return new ResponseEntity<MemberInfo>(resp, (HttpStatus.OK));
    }
}

MemberInfoService.java

@Service
public class MemberInfoService {
    public static final Logger LOG = LoggerFactory.getLogger(MemberInfoService.class);
    
    @Autowired
    private UserInfoService userInfoService;
    
    @Autowired
    private BenefitService benefitService;

    public MemberInfo getMemberInfo(String memId) throws TimeoutException {
        LOG.info("---End of the WebController.MemberInfoService()---");
        
        MemberInfo memberInfo = null;
        memberInfo = userInfoService.getUserInfo(memId);
        Benefit benefit = null;
        benefit = benefitService.getBenefitInfo(memId);
        memberInfo.setBenefit(benefit);
        
        LOG.info("---End of the WebController.MemberInfoService()---");
        return memberInfo;
    }
}

BenefitService.java

@Service
public class BenefitService {
    public static final Logger LOG = LoggerFactory.getLogger(BenefitService.class);

    @Autowired
    private WebClient benefitApiClient;
    
    @CircuitBreaker(name = "benefitService", fallbackMethod = "buildFallbackBenefitInfo")
    @RateLimiter(name = "benefitService", fallbackMethod = "buildFallbackBenefitInfo")
    @Retry(name = "retryBenefitService", fallbackMethod = "buildFallbackBenefitInfo")
    public Benefit getBenefitInfo(String memId) throws TimeoutException {
        LOG.info("---Beginning of the BenefitService.getBenefitInfo()---");
        randomlyRunLong();
        return benefitApiClient.get()
                .uri("/member/benefit/" + memId)
                .retrieve()
                .bodyToMono(Benefit.class)
                .block();
    }
    
    public Benefit buildFallbackBenefitInfo(String memId, Throwable t) throws TimeoutException {
        Benefit benefit = null;
        benefit = new Benefit();
        benefit.setBenefitId("00000");
        benefit.setMemeberId("00000");
        
        return benefit;
    }
    
    
    private void randomlyRunLong() throws TimeoutException{
        Random rand = new Random();
        int randomNum = rand.nextInt((3 - 1) + 1) + 1;
        if (randomNum==3) sleep();
    }
    private void sleep() throws TimeoutException{
        try {
            System.out.println("Sleep");
            Thread.sleep(5000);
            throw new java.util.concurrent.TimeoutException();
        } catch (InterruptedException e) {
            LOG.error(e.getMessage());
        }
    }       
}

應用程序.yml

server:
  port: 9095

management.endpoints.enabled-by-default: false
management.endpoint.health:
 enabled: true
 show-details: always
 
resilience4j.circuitbreaker:
  instances:
    benefitService:
      registerHealthIndicator: true
      ringBufferSizeInClosedState: 5
      ringBufferSizeInHalfOpenState: 3
      waitDurationInOpenState: 10s
      failureRateThreshold: 50
      recordExceptions:
        - org.springframework.web.client.HttpServerErrorException
        - java.io.IOException
        - java.util.concurrent.TimeoutException
        - org.springframework.web.client.ResourceAccessException

resilience4j.ratelimiter:
  instances:
    benefitService:
      limitForPeriod: 5
      limitRefreshPeriod: 5000
      timeoutDuration: 1000ms

resilience4j.retry:
  instances:
    retryBenefitService:
      maxRetryAttempts: 5
      waitDuration: 10000
      retry-exceptions:
        - java.util.concurrent.TimeoutException

resilience4j.bulkhead:
  instances:
    bulkheadBenefitService:
      maxWaitDuration: 2ms
      maxConcurrentCalls: 20


resilience4j.thread-pool-bulkhead:
  instances:
    bulkheadBenefitService:
      maxThreadPoolSize: 1
      coreThreadPoolSize: 1
      queueCapacity: 1

我不確定我在這里做錯了什么。 非常感謝您的幫助。 提前致謝

默認的Resilience4j 方面順序

Retry( CircuitBreaker( RateLimiter( TimeLimiter( Bulkhead( function)))))

您的 RateLimiter 具有后備功能,因此它永遠不會引發異常,因此 CircuitBreaker 永遠不會看到失敗的調用。 僅指定將執行的最后一個方面的后備。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM