1、Sentinel 是什麼
Sentinel 是阿里中間件團隊開源的,面向分佈式服務架構的輕量級流量控制產品,主要以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度來幫助用戶保護服務的穩定性。 點此地址瞭解更多Sentinel。html
2、Sentinel 怎麼用
Sentinel分爲兩個部分:客戶端以及控制檯。java
- 控制檯用於管理限流,熔斷規則的發佈與監控。
- 客戶端則用於接收規則,並執行相關規則。
1. 下載Sentinel控制檯
當前最新的release版本爲1.4.0git
https://github.com/alibaba/Sentinel/releases/tag/1.4.0github
2. 運行Sentinel控制檯
注意:啓動 Sentinel 控制檯須要 JDK 版本爲 1.8 及以上版本。spring
使用以下命令啓動控制檯:api
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 爲例):spring-boot
<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 參數spa
-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 指定控制檯顯示的項目名稱
更詳細的信息能夠參考啓動配置項。
而後你能夠愉快的打開控制檯對你的服務進行限流,熔斷降級了。
3、現有的問題
- 規則的推送目前採用的是以http接口的形式進行數據處理,當發佈規則時,須要採用遍歷全部的客戶端,以http的形式進行數據推送,此方式的問題在於服務部署數量愈來愈多,發佈規則也就愈來愈慢,愈來愈困難。
- Sentinel的熔斷限流統計則是以異常發生數爲依據,真正使用過程當中還須要排除業務異常。
- 監控數據目前的作法是遍歷全部的客戶端採用http進行批量遠程讀取,並存儲入庫,且實時監控僅能查看5分鐘內的metric數據。
- Sentinel的啓動注入參數的方式太過原始。
4、如何改造
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的方式,採用自動化配置。
5、項目推薦
樓主本身改造了一個版本,目前已實現的功能以下:
- 新增dubbo的filter將異常包裝成統一返回體,將異常狀態碼定義爲>=500的值(與HttpStatus相對應),修改SentinelResourceAspect實現,判斷返回的狀態碼是否爲>=500,若是是則進行熔斷統計。
- 並新增sentinel-dubbo-starter,進行自動配置化。
- Sentinel Dashboard改造:控制檯規則 -> 配置中心 -> 客戶端。
歡迎start,若有問題,歡迎指出,共同進步: