一、Sentinel 是什么
Sentinel 是阿里中間件團隊開源的,面向分布式服務架構的輕量級流量控制產品,主要以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度來幫助用戶保護服務的穩定性。 點此地址了解更多Sentinel。
二、Sentinel 怎么用
Sentinel分為兩個部分:客戶端以及控制台。
- 控制台用於管理限流,熔斷規則的發布與監控。
- 客戶端則用於接收規則,並執行相關規則。
1. 下載Sentinel控制台
當前最新的release版本為1.4.0
https://github.com/alibaba/Sentinel/releases/tag/1.4.0
2. 運行Sentinel控制台
注意:啟動 Sentinel 控制台需要 JDK 版本為 1.8 及以上版本。
使用如下命令啟動控制台:
java -Dserver.port=8080 \ -Dcsp.sentinel.dashboard.server=localhost:8080 \ -Dproject.name=sentinel-dashboard \ -jar sentinel-dashboard.jar
其中 -Dserver.port=8080 用於指定 Sentinel 控制台端口為 8080。
訪問http://localhost:8080查看控制台信息。
3. 客戶端Dubbo集成
使用時需引入以下模塊(以 Maven 為例):
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-dubbo-adapter</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-transport-simple-http</artifactId> <version>1.4.0</version> </dependency>
啟動時加入 JVM 參數
-Djava.net.preferIPv4Stack=true \ -Dcsp.sentinel.api.port=8720 \ -Dcsp.sentinel.dashboard.server=localhost:8787 \ -Dproject.name=example-customer
啟動項參數說明:
- -Dcsp.sentinel.api.port 接受數據推薦的http端口
- -Dcsp.sentinel.dashboard.server 指定控制台地址
- -Dproject.name 指定控制台顯示的項目名稱
更詳細的信息可以參考啟動配置項。
然后你可以愉快的打開控制台對你的服務進行限流,熔斷降級了。
三、現有的問題
- 規則的推送目前采用的是以http接口的形式進行數據處理,當發布規則時,需要采用遍歷所有的客戶端,以http的形式進行數據推送,此方式的問題在於服務部署數量越來越多,發布規則也就越來越慢,越來越困難。
- Sentinel的熔斷限流統計則是以異常發生數為依據,真正使用過程中還需要排除業務異常。
- 監控數據目前的做法是遍歷所有的客戶端采用http進行批量遠程讀取,並存儲入庫,且實時監控僅能查看5分鍾內的metric數據。
- Sentinel的啟動注入參數的方式太過原始。
四、如何改造
1. 關於Dashboard的數據推送問題的改造,思路可以考慮將數據傳遞到配置中心,利用配置中心來進行數據推送廣播。
- 改造前:客戶端利用sentinel-transport-simple-http模塊暴露一個特定的端口,Sentinel Dashboard通過http的形式進行數據推送,客戶端接收后將規則保存在本地內存中。
- 改造后:客戶端注冊到相關的注冊中心中,Sentinel Dashboard控制台將配置信息推送到配置中心,如nacos,zookeeper中,由配置中心去進行配置推送。
2. 關於Sentinel的業務異常問題,可以考慮采用類似於Hystrix的方法,HystrixBadRequestException被Hystrix認定為這是消費者自身的問題,而非提供者的服務不穩定,即我們常說的業務異常不被熔斷。
方法1:采用包裝異常的形式,將所有的異常包裝為統一的結構體,並設定異常狀態碼,例如業務異常都是400,服務異常是500。
public class Result<T> { /** * 狀態碼 */ private int code; /** * 消息 */ private String message; /** * 數據 */ private T result; // TODO 忽略get,set } Entry entry = null; try { entry = SphU.entry(resourceName, entryType, 1, pjp.getArgs()); Object result = pjp.proceed(); // 核心判斷 if (result instanceof Result && ((Result) result).getCode() == 500) { Tracer.trace(new RuntimeException(((Result) result).getMessage())); } return result; } catch (BlockException ex) { return handleBlockException(pjp, annotation, ex); } catch (Throwable ex) { Tracer.trace(ex); throw ex; } finally { if (entry != null) { entry.exit(); } }
方法2:采用拋異常的形式,定義一個BussinessException業務異常。
Entry entry = null; try { entry = SphU.entry(resourceName, entryType, 1, pjp.getArgs()); return pjp.proceed(); } catch (BlockException ex) { return handleBlockException(pjp, annotation, ex); } catch (BussinessException ex) { // 核心處理 throw ex; } catch (Throwable ex) { Tracer.trace(ex); throw ex; } finally { if (entry != null) { entry.exit(); } }
至於采用何種方式進行改造,見仁見智吧。
3. Sentinel監控問題,可以考慮采用CrateDB + Grafana/或者數據落地InfluxDB等方式。
相關鏈接參考:
4. Sentinel的啟動注入參數的方式太過原始,可以考慮使用spring-boot-starter的方式,采用自動化配置。
五、項目推薦
樓主自己改造了一個版本,目前已實現的功能如下:
- 新增dubbo的filter將異常包裝成統一返回體,將異常狀態碼定義為>=500的值(與HttpStatus相對應),修改SentinelResourceAspect實現,判斷返回的狀態碼是否為>=500,如果是則進行熔斷統計。
- 並新增sentinel-dubbo-starter,進行自動配置化。
- Sentinel Dashboard改造:控制台規則 -> 配置中心 -> 客戶端。
歡迎start,如有問題,歡迎指出,共同進步: