您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)如何正確的使用Spring Boot單體應(yīng)用熔斷技術(shù),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
阿里出品,Spring Cloud Alibaba限流組件,目前持續(xù)更新中
自帶Dashboard,可以查看接口Qps等,并且可以動(dòng)態(tài)修改各種規(guī)則
流量控制,直接限流、冷啟動(dòng)、排隊(duì)
熔斷降級(jí),限制并發(fā)限制數(shù)和相應(yīng)時(shí)間
系統(tǒng)負(fù)載保護(hù),提供系統(tǒng)級(jí)別防護(hù),限制總體CPU等
主要核心:資源,規(guī)則(流量控制規(guī)則、熔斷降級(jí)規(guī)則、系統(tǒng)保護(hù)規(guī)則、來(lái)源訪(fǎng)問(wèn)控制規(guī)則 和 熱點(diǎn)參數(shù)規(guī)則。),和指標(biāo)
文檔非常清晰和詳細(xì),中文
支持動(dòng)態(tài)規(guī)則(推模式和拉模式)
Netflix出品,Spring Cloud Netflix限流組件,已經(jīng)停止新特性開(kāi)發(fā),只進(jìn)行bug修復(fù),最近更新為2018年,功能穩(wěn)定
有簡(jiǎn)單的dashboard頁(yè)面
以隔離和熔斷為主的容錯(cuò)機(jī)制,超時(shí)或被熔斷的調(diào)用將會(huì)快速失敗,并可以提供 fallback 機(jī)制的初代熔斷框架,異常統(tǒng)計(jì)基于滑動(dòng)窗口
是一款輕量、簡(jiǎn)單,并且文檔非常清晰、豐富的熔斷工具。是Hystrix替代品,實(shí)現(xiàn)思路和Hystrix一致,目前持續(xù)更新中
需要自己對(duì)micrometer、prometheus以及Dropwizard metrics進(jìn)行整合
CircuitBreaker 熔斷
Bulkhead 隔離
RateLimiter QPS限制
Retry 重試
TimeLimiter 超時(shí)限制
Cache 緩存
基于Guava的令牌桶,可以輕松實(shí)現(xiàn)對(duì)QPS進(jìn)行限流
3.1.1、引入依賴(lài)
<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 { //資源名稱(chēng) String value() default ""; //流量方向 EntryType entryType() default EntryType.OUT; //資源類(lèi)型 int resourceType() default 0; //異常處理方法 String blockHandler() default ""; //異常處理類(lèi) Class<?>[] blockHandlerClass() default {}; //熔斷方法 String fallback() default ""; //默認(rèn)熔斷方法 String defaultFallback() default ""; //熔斷類(lèi) Class<?>[] fallbackClass() default {}; //統(tǒng)計(jì)異常 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、針對(duì)接口配置熔斷方法或者限流方法
默認(rèn)過(guò)濾攔截所有Controller接口
/** * 限流,參數(shù)需要和方法保持一致 * @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 ); } /** * 熔斷,參數(shù)需要和方法保持一直,并且需要添加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 ); }
注意也可以不配置限流或者熔斷方法。通過(guò)全局異常去捕獲UndeclaredThrowableException或者BlockException避免大量的開(kāi)發(fā)量
3.1.4、接入dashboard
spring: cloud: sentinel: transport: port: 8719 dashboard: localhost:8080
3.1.5、規(guī)則持久化和動(dòng)態(tài)更新
接入配置中心如:zookeeper等等,并對(duì)規(guī)則采用推模式
3.2.1、引入依賴(lài)
<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、針對(duì)接口配置熔斷方法
/** * 該方法是熔斷回調(diào)方法,參數(shù)需要和接口保持一致 * @param request * @param response * @param num * @return */ public JsonResult fallbackMethod(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer num) { response.setStatus(500); log.info("發(fā)生了熔斷?。?quot;); return JsonResult.error("熔斷"); }
3.2.4、配置默認(rèn)策略
hystrix: command: default: execution: isolation: strategy: THREAD thread: # 線(xiàn)程超時(shí)15秒,調(diào)用Fallback方法 timeoutInMilliseconds: 15000 metrics: rollingStats: timeInMilliseconds: 15000 circuitBreaker: # 10秒內(nèi)出現(xiàn)3個(gè)以上請(qǐng)求(已臨近閥值),并且出錯(cuò)率在50%以上,開(kāi)啟斷路器.斷開(kāi)服務(wù),調(diào)用Fallback方法 requestVolumeThreshold: 3 sleepWindowInMilliseconds: 10000
3.2.5、接入監(jiān)控
曲線(xiàn):用來(lái)記錄2分鐘內(nèi)流量的相對(duì)變化,我們可以通過(guò)它來(lái)觀察到流量的上升和下降趨勢(shì)。
集群監(jiān)控需要用到注冊(cè)中心
3.3.1、引入依賴(lài)
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、針對(duì)接口配置熔斷方法
/** * 需要參數(shù)一致,并且加上相應(yīng)異常 * @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、配置規(guī)則
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
配置的規(guī)則可以被代碼覆蓋
3.3.5、配置監(jiān)控
如grafana等
是否需要過(guò)濾部分異常
是否需要全局默認(rèn)規(guī)則
可能需要引入其他中間件
k8s流量控制
規(guī)則存儲(chǔ)和動(dòng)態(tài)修改
接入改造代價(jià)
看完上述內(nèi)容,你們對(duì)如何正確的使用Spring Boot單體應(yīng)用熔斷技術(shù)有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。