SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断
什么是Sentinel?
請查看文章:SpringCloud Alibaba微服務(wù)實戰(zhàn)(一) - 基礎(chǔ)環(huán)境搭建
構(gòu)建服務(wù)消費者cloud-sentinel進(jìn)行服務(wù)調(diào)用
服務(wù)創(chuàng)建請查看文章:SpringCloud Alibaba微服務(wù)實戰(zhàn)(二) - Nacos服務(wù)注冊與restTemplate消費
1.在父項目中創(chuàng)建子module項目名字為cloud-sentinel,在pom中引入nacos服務(wù)注冊依賴
<!--Spring web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--SpringCloud Alibaba nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
完整服務(wù)消費者cloud-sentinel的pom.xml
<?xml version="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><artifactId>cloud-alibaba</artifactId><groupId>com.zsy.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><artifactId>cloud-sentinel</artifactId><dependencies><!--Spring web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--SpringCloud Alibaba nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build><repositories><!--指定阿里云鏡像庫下載依賴--><repository><id>central</id><name>aliyunmaven</name><url>http://maven.aliyun.com/nexus/content/groups/public/</url></repository></repositories>
</project>
2.配置application.yml或者properties文件
server:port: 8085
spring:#服務(wù)應(yīng)用名字application:name: cloud-sentinelcloud:# 指定nacos控制臺地址,配置注冊ip:端口,注意即使是80端口也不可能省略nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:dashboard: 127.0.0.1:8080 # sentinel服務(wù)端地址eager: true # 取消延遲加載
3.FeignClient接口定義AccountService
package com.zsy.springcloud.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.Map;
@FeignClient("cloud-account")
public interface AccountService {//獲取客戶信息@RequestMapping(value = "/getAccount", method = RequestMethod.GET)public Map<String,Object> getAccount();
}
4.創(chuàng)建消費者AccountConsumerController
package com.zsy.springcloud.controller;
import com.zsy.springcloud.service.AccountService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Log4j2
@RestController
public class AccountConsumerController {@Resourceprivate AccountService accountService;@RequestMapping(value = "/getAccount", method = RequestMethod.GET)public Map<String,Object> getAccount() {Map<String,Object> account = new HashMap<>();log.info("---------消費者開始------------");account = accountService.getAccount();log.info("---------消費者結(jié)束--------account{}----", account);return account;}
}
5.配置消費者啟動服務(wù)的啟動類
package com.zsy.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient //開啟服務(wù)注冊
@EnableFeignClients//開啟feign客戶端
public class CloudSentinelApplication {public static void main(String[] args) {SpringApplication.run(CloudSentinelApplication.class, args);}
}
6.啟動cloud-sentinel服務(wù)項目,啟動成功,如下圖
7. 驗證服務(wù),瀏覽器訪問http://localhost:8085/getAccount,返回如下圖
查看消費者cloud-sentinel控制臺,如下圖
查看服務(wù)者cloud-account控制臺,如下圖
限流
限流配置
訪問:http://127.0.0.1:8080/,登錄sentinel
理想是豐滿的,現(xiàn)實是骨感的。為了方便測試,我們就將cloud-sentinel中的getAccount接口的QPS單機(jī)閾值設(shè)置成1,如果每秒QPS超過1,直接丟棄。
打開瀏覽器,快速刷新瀏覽器,當(dāng)每秒請求書超過1時會看到如下錯誤:
不要慌,這說明我們的目的達(dá)到了,限流成功!
自定義異常
我們可以通過@SentinelResource中添加blockHandler參數(shù),給其添加自定義異常方法。如:
package com.zsy.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.zsy.springcloud.service.AccountService;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;@Log4j2
@RestController
public class AccountConsumerController {@Resourceprivate AccountService accountService;@RequestMapping(value = "/getAccount", method = RequestMethod.GET)@SentinelResource(value = "getAccount",blockHandler = "handleException")public Map<String,Object> getAccount() {Map<String,Object> account = new HashMap<>();log.info("---------消費者開始------------");account = accountService.getAccount();log.info("---------消費者結(jié)束--------account{}----", account);return account;}/*** 自定義異常策略* 返回值和參數(shù)要跟目標(biāo)函數(shù)一樣,參數(shù)可以追加BlockException*/public Map<String,Object> handleException(BlockException exception){Map<String,Object> account = new HashMap<>();log.info("flow exception{}",exception.getClass().getCanonicalName());account.put("msg","別點了,達(dá)到閥值了,稍后再試");return account;}
}
注意,自定義的異常方法的參數(shù)和返回值要跟目標(biāo)方法一樣,參數(shù)可以追加BlockException
打開瀏覽器,快速刷新瀏覽器,當(dāng)每秒請求書超過1時會看到如下錯誤:
@SentinelResource 屬性介紹
熔斷
什么是熔斷?
消費者order-service需要先調(diào)用product-service獲取具體的product,然后再處理其他的業(yè)務(wù)邏輯。但是這個product-service接口不是很穩(wěn)定,經(jīng)常拋出異常,或者是響應(yīng)緩慢,宕機(jī)。導(dǎo)致order-service的響應(yīng)變慢;如果置之不理,order-service可能會被product-service拖垮。這時候為了保護(hù)order-service,我們需要對product-service接口進(jìn)行熔斷。
總結(jié):熔斷是通過限制自己對外部系統(tǒng)的調(diào)用, 起到節(jié)約響應(yīng)時間、維護(hù)鏈路穩(wěn)定的作用
熔斷
Sentinel中的熔斷降級有三個降級策略:
RT(平均響應(yīng)時間):
當(dāng)資源的平均響應(yīng)時間超過閾值之后,資源進(jìn)入準(zhǔn)降級狀態(tài)。接下來如果持續(xù)進(jìn)入 5 個請求,它們的 RT 都持續(xù)超過這個閾值,那么在接下的時間窗口之內(nèi),對這個方法的調(diào)用都會自動拋出 DegradeException 異常。在下一個時間窗口到來時, 會接著再放入5個請求, 再重復(fù)上面的判斷.
異常比例
當(dāng)資源的每秒異常總數(shù)占通過量的比值超過閾值之后,資源進(jìn)入降級狀態(tài),即在接下的時間窗口之內(nèi),對這個方法的調(diào)用都會自動地拋出DegradeException異常。異常比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%。
異常數(shù)
當(dāng)資源近 1 分鐘的異常數(shù)目超過閾值之后會進(jìn)行熔斷。
未進(jìn)行熔斷配置,服務(wù)異常驗證
1.配置服務(wù)拋出異常
2.驗證,訪問http://localhost:8085/getAccount,頁面展示如下圖:
控制臺如下圖:
在日常中,我們肯定不希望發(fā)生這樣的事故。我們可以通過熔斷實現(xiàn)服務(wù)降級來處理這種情況
熔斷配置
1.自定義異常,創(chuàng)建異常本地實現(xiàn)類,實現(xiàn)FeignClient接口
package com.zsy.springcloud.fallback;
import com.zsy.springcloud.service.AccountService;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Log4j2
@Service
public class AccountServiceBack implements AccountService {@Overridepublic Map<String, Object> getAccount() {Map<String,Object> account = new HashMap<>();account.put("msg","服務(wù)熔斷了,本地處理");return account;}
}
.2.修改FeignClient接口定義AccountService
package com.zsy.springcloud.service;
import com.zsy.springcloud.fallback.AccountServiceBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.Map;
@FeignClient(value = "cloud-account",fallback = AccountServiceBack.class)
public interface AccountService {//獲取客戶信息@RequestMapping(value = "/getAccount", method = RequestMethod.GET)public Map<String,Object> getAccount();
}
3.配置application.yml或者properties文件
server:port: 8085
spring:#服務(wù)應(yīng)用名字application:name: cloud-sentinelcloud:# 指定nacos控制臺地址,配置注冊ip:端口,注意即使是80端口也不可能省略nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:dashboard: 127.0.0.1:8080 # sentinel服務(wù)端地址eager: true # 取消延遲加載
feign:hystrix:enabled: true #打開feign對hustrix的支持,FeignClient 中的 fallback不起任何作用
因為Fallback是通過Hystrix實現(xiàn)的, 所以需要開啟Hystrix,spring boot application.properties文件配置feign.hystrix.enabled=true,這樣就開啟了Fallback
4.配置getAccount熔斷
5.驗證,訪問http://localhost:8085/getAccount,頁面展示如下圖:
控制臺如下圖:
熔斷配置完成,我們已經(jīng)給我們的微服務(wù)加上了限流熔斷保護(hù),再也不用擔(dān)心異常流量的沖擊,下游系統(tǒng)不穩(wěn)定導(dǎo)致自身服務(wù)不可用了。本片文章只是對Sentinel進(jìn)行了一個入門級的交流,Sentinel更高級的等后面有時間了另行分享。
1.Sentinel的配置默認(rèn)是放在內(nèi)存中的,每當(dāng)應(yīng)用重啟或者sentinel重啟都會丟失數(shù)據(jù),該如何處理?
。。。。。。。。。.。。。。。。。。。。。。。。。
碼云地址:https://gitee.com/zlzhaoe/cloud-alibaba
總結(jié)
以上是生活随笔為你收集整理的SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringCloud Alibaba微
- 下一篇: SpringCloud Alibaba微