目錄
使用SphU的API實現自定義資源
BlockException
使用@SentinelResource注解定義資源
SentinelResourceAspect
使用Sentinel實現限流降級等效果通常需要先把需要保護的資源定義好,之后再基于定義好的資源為其配置限流降級等規則。
Sentinel對于主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor 等都做了適配,具體可以參考主流框架適配。只需要引入對應的依賴即可方便地整合 Sentinel。
但框架適配主要是對一些http或RPC接口做資源定義,如果涉及到一些代碼塊或者方法是無法做資源定義的,這種情況下就需要通過編碼方式自定義資源,并通過捕獲異常的方式實現限流或降級的邏輯。
使用SphU的API實現自定義資源
SphU類在sentinel-core依賴中,主要用于對資源的訪問控制。當系統想要執行某個資源操作時,通過調用 SphU.entry 方法來檢查該資源是否受到流量控制。
- 如果資源當前處于限流狀態,那么 SphU.entry 會拋出 BlockException 異常,表示請求被限流,此時系統可以進行降級操作。
- 如果資源沒有受到限流,那么 SphU.entry 會返回一個 Entry 對象,表示一次資源操作開始,系統可以繼續執行相關的業務代碼。
- 注意SphU.entry 需要和 entry.exit 一起配合使用,確保在業務代碼執行完后執行?entry.exit
BlockException
BlockException是sentinel流控觸發后的異常類,其下包含很多個子類,分別對應不同的場景:
- FlowException ? ? ? ?限流異常
- ParamFlowException ? 熱點參數限流的異常
- DegradeException ? ? 降級異常
- AuthorityException ? 授權規則異常
- SystemBlockException 系統規則異常
使用SphU的API前,需要確保項目中直接或間接引入了sentinel-core的依賴(通常框架適配的stater中已經引入了)
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version>
</dependency>
下面是一個通過SphU自定義資源的實例代碼:
public PriceDTO queryPrice(String skuCode) {PriceParam param = new PriceParam();param.setSkuCode(skuCode);Entry entry = null;try {entry = SphU.entry(SentinelResourceConstant.MARKETING_SPECIAL_ACTIVITY_QUERY_SHOP_SKU_PRICE);return productFacade.queryPrice(param).unboxing();}catch(FlowException e) {log.error("查詢商品價格接口觸發限流,skuCode:{}", skuCode);return null;}catch(DegradeException e) {log.error("查詢商品價格接口觸發降級,skuCode:{}", skuCode);return null;} finally {if (entry != null) {entry.exit();}}
}
使用@SentinelResource注解定義資源
上面通過SphU API自定義資源可以最小粒度的控制要保護的資源,但是侵入較大,增加了代碼的復雜性。而另外一中方式就是使用@SentinelResource 注解,這種方式對代碼入侵程度相對較低。
SentinelResourceAspect
使用@SentinelResource 注解來實現資源定義,原理與上面的API其實是一樣的,Sentinel 中定義了SentinelResourceAspect 通過切面方式攔截后同樣通過SphU API來實現流控功能。
既然注解方式是通過切面來實現的,那么在使用注解方式進行資源定義的前提就是先通過配置的方式將 SentinelResourceAspect 注冊為一個 Spring Bean,有了這個bean以后@SentinelResource注解才可以生效。
@Configuration
public class SentinelAspectConfiguration {@Beanpublic SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect();}
}
開啟配置后即可在代碼中使用@SentinelResource注解對某個方法進行Sentinel資源定義。
@Service
public class TestService {// 資源定義并設置流控處理@SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")public String hello(long s) {return String.format("Hello at %d", s);}// Fallback 函數,函數簽名與原函數一致或加一個 Throwable 類型的參數.public String helloFallback(long s) {return String.format("Halooooo %d", s);}// Block 異常處理函數,參數最后多一個 BlockException,其余與原函數一致.public String exceptionHandler(long s, BlockException ex) {// Do some log here.ex.printStackTrace();return "Oops, error occurred at " + s;}
}