今天就跟大家聊聊有關如何正確的使用Spring Boot單體應用熔斷技術,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
阿里出品,Spring Cloud Alibaba限流組件,目前持續更新中
自帶Dashboard,可以查看接口Qps等,并且可以動態修改各種規則
流量控制,直接限流、冷啟動、排隊
熔斷降級,限制并發限制數和相應時間
系統負載保護,提供系統級別防護,限制總體CPU等
主要核心:資源,規則(流量控制規則、熔斷降級規則、系統保護規則、來源訪問控制規則 和 熱點參數規則。),和指標
文檔非常清晰和詳細,中文
支持動態規則(推模式和拉模式)
Netflix出品,Spring Cloud Netflix限流組件,已經停止新特性開發,只進行bug修復,最近更新為2018年,功能穩定
有簡單的dashboard頁面
以隔離和熔斷為主的容錯機制,超時或被熔斷的調用將會快速失敗,并可以提供 fallback 機制的初代熔斷框架,異常統計基于滑動窗口
是一款輕量、簡單,并且文檔非常清晰、豐富的熔斷工具。是Hystrix替代品,實現思路和Hystrix一致,目前持續更新中
需要自己對micrometer、prometheus以及Dropwizard metrics進行整合
CircuitBreaker 熔斷
Bulkhead 隔離
RateLimiter QPS限制
Retry 重試
TimeLimiter 超時限制
Cache 緩存
基于Guava的令牌桶,可以輕松實現對QPS進行限流

3.1.1、引入依賴
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.0.3.RELEASE</version> </dependency>
3.1.2、改造接口或者service層
@SentinelResource(value = "allInfos",fallback = "errorReturn")
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
//資源名稱
String value() default "";
//流量方向
EntryType entryType() default EntryType.OUT;
//資源類型
int resourceType() default 0;
//異常處理方法
String blockHandler() default "";
//異常處理類
Class<?>[] blockHandlerClass() default {};
//熔斷方法
String fallback() default "";
//默認熔斷方法
String defaultFallback() default "";
//熔斷類
Class<?>[] fallbackClass() default {};
//統計異常
Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
//忽略異常
Class<? extends Throwable>[] exceptionsToIgnore() default {};
}@RequestMapping("/get")
@ResponseBody
@SentinelResource(value = "allInfos",fallback = "errorReturn")
public JsonResult allInfos(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num){
try {
if (num % 2 == 0) {
log.info("num % 2 == 0");
throw new BaseException("something bad with 2", 400);
}
return JsonResult.ok();
} catch (ProgramException e) {
log.info("error");
return JsonResult.error("error");
}
}3.1.3、針對接口配置熔斷方法或者限流方法
默認過濾攔截所有Controller接口
/**
* 限流,參數需要和方法保持一致
* @param request
* @param response
* @param num
* @return
* @throws BlockException
*/
public JsonResult errorReturn(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num) throws BlockException {
return JsonResult.error("error 限流" + num );
}
/**
* 熔斷,參數需要和方法保持一直,并且需要添加BlockException異常
* @param request
* @param response
* @param num
* @param b
* @return
* @throws BlockException
*/
public JsonResult errorReturn(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num,BlockException b) throws BlockException {
return JsonResult.error("error 熔斷" + num );
}注意也可以不配置限流或者熔斷方法。通過全局異常去捕獲UndeclaredThrowableException或者BlockException避免大量的開發量
3.1.4、接入dashboard
spring: cloud: sentinel: transport: port: 8719 dashboard: localhost:8080

3.1.5、規則持久化和動態更新
接入配置中心如:zookeeper等等,并對規則采用推模式
3.2.1、引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.0.4.RELEASE</version> </dependency>
3.2.2、改造接口
@HystrixCommand(fallbackMethod = "timeOutError")
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {
String groupKey() default "";
String commandKey() default "";
String threadPoolKey() default "";
String fallbackMethod() default "";
HystrixProperty[] commandProperties() default {};
HystrixProperty[] threadPoolProperties() default {};
Class<? extends Throwable>[] ignoreExceptions() default {};
ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;
HystrixException[] raiseHystrixExceptions() default {};
String defaultFallback() default "";
}@RequestMapping("/get")
@ResponseBody
@HystrixCommand(fallbackMethod = "fallbackMethod")
public JsonResult allInfos(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num){
try {
if (num % 3 == 0) {
log.info("num % 3 == 0");
throw new BaseException("something bad whitch 3", 400);
}
return JsonResult.ok();
} catch (ProgramException | InterruptedException exception) {
log.info("error");
return JsonResult.error("error");
}
}3.2.3、針對接口配置熔斷方法
/**
* 該方法是熔斷回調方法,參數需要和接口保持一致
* @param request
* @param response
* @param num
* @return
*/
public JsonResult fallbackMethod(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num) {
response.setStatus(500);
log.info("發生了熔斷??!");
return JsonResult.error("熔斷");
}3.2.4、配置默認策略
hystrix: command: default: execution: isolation: strategy: THREAD thread: # 線程超時15秒,調用Fallback方法 timeoutInMilliseconds: 15000 metrics: rollingStats: timeInMilliseconds: 15000 circuitBreaker: # 10秒內出現3個以上請求(已臨近閥值),并且出錯率在50%以上,開啟斷路器.斷開服務,調用Fallback方法 requestVolumeThreshold: 3 sleepWindowInMilliseconds: 10000
3.2.5、接入監控


曲線:用來記錄2分鐘內流量的相對變化,我們可以通過它來觀察到流量的上升和下降趨勢。
集群監控需要用到注冊中心
3.3.1、引入依賴
dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-bulkhead</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-ratelimiter</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-timelimiter</artifactId> <version>1.6.1</version> </dependency>
可以按需要引入:bulkhead,ratelimiter,timelimiter等
3.3.2、改造接口
@RequestMapping("/get")
@ResponseBody
//@TimeLimiter(name = "BulkheadA",fallbackMethod = "fallbackMethod")
@CircuitBreaker(name = "BulkheadA",fallbackMethod = "fallbackMethod")
@Bulkhead(name = "BulkheadA",fallbackMethod = "fallbackMethod")
public JsonResult allInfos(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num){
log.info("param----->" + num);
try {
//Thread.sleep(num);
if (num % 2 == 0) {
log.info("num % 2 == 0");
throw new BaseException("something bad with 2", 400);
}
if (num % 3 == 0) {
log.info("num % 3 == 0");
throw new BaseException("something bad whitch 3", 400);
}
if (num % 5 == 0) {
log.info("num % 5 == 0");
throw new ProgramException("something bad whitch 5", 400);
}
if (num % 7 == 0) {
log.info("num % 7 == 0");
int res = 1 / 0;
}
return JsonResult.ok();
} catch (BufferUnderflowException e) {
log.info("error");
return JsonResult.error("error");
}
}3.3.3、針對接口配置熔斷方法
/**
* 需要參數一致,并且加上相應異常
* @param request
* @param response
* @param num
* @param exception
* @return
*/
public JsonResult fallbackMethod(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num, BulkheadFullException exception) {
return JsonResult.error("error 熔斷" + num );
}3.3.4、配置規則
resilience4j.circuitbreaker: instances: backendA: registerHealthIndicator: true slidingWindowSize: 100 backendB: registerHealthIndicator: true slidingWindowSize: 10 permittedNumberOfCallsInHalfOpenState: 3 slidingWindowType: TIME_BASED minimumNumberOfCalls: 20 waitDurationInOpenState: 50s failureRateThreshold: 50 eventConsumerBufferSize: 10 recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate resilience4j.retry: instances: backendA: maxRetryAttempts: 3 waitDuration: 10s enableExponentialBackoff: true exponentialBackoffMultiplier: 2 retryExceptions: - org.springframework.web.client.HttpServerErrorException - java.io.IOException ignoreExceptions: - io.github.robwin.exception.BusinessException backendB: maxRetryAttempts: 3 waitDuration: 10s retryExceptions: - org.springframework.web.client.HttpServerErrorException - java.io.IOException ignoreExceptions: - io.github.robwin.exception.BusinessException resilience4j.bulkhead: instances: backendA: maxConcurrentCalls: 10 backendB: maxWaitDuration: 10ms maxConcurrentCalls: 20 resilience4j.thread-pool-bulkhead: instances: backendC: maxThreadPoolSize: 1 coreThreadPoolSize: 1 queueCapacity: 1 resilience4j.ratelimiter: instances: backendA: limitForPeriod: 10 limitRefreshPeriod: 1s timeoutDuration: 0 registerHealthIndicator: true eventConsumerBufferSize: 100 backendB: limitForPeriod: 6 limitRefreshPeriod: 500ms timeoutDuration: 3s resilience4j.timelimiter: instances: backendA: timeoutDuration: 2s cancelRunningFuture: true backendB: timeoutDuration: 1s cancelRunningFuture: false
配置的規則可以被代碼覆蓋
3.3.5、配置監控
如grafana等
是否需要過濾部分異常
是否需要全局默認規則
可能需要引入其他中間件
k8s流量控制
規則存儲和動態修改
接入改造代價
看完上述內容,你們對如何正確的使用Spring Boot單體應用熔斷技術有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。