Dubbo使用Sentinel來對服務進行降級與限流

1、Sentinel 是什麼

Sentinel 是阿里中間件團隊開源的,面向分佈式服務架構的輕量級流量控制產品,主要以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度來幫助用戶保護服務的穩定性。 點此地址瞭解更多Sentinelhtml

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 參數.net

-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、現有的問題

  1. 規則的推送目前採用的是以http接口的形式進行數據處理,當發佈規則時,須要採用遍歷全部的客戶端,以http的形式進行數據推送,此方式的問題在於服務部署數量愈來愈多,發佈規則也就愈來愈慢,愈來愈困難。
  2. Sentinel的熔斷限流統計則是以異常發生數爲依據,真正使用過程當中還須要排除業務異常。
  3. 監控數據目前的作法是遍歷全部的客戶端採用http進行批量遠程讀取,並存儲入庫,且實時監控僅能查看5分鐘內的metric數據。
  4. 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、項目推薦

樓主本身改造了一個版本,目前已實現的功能以下:

  1. 新增dubbo的filter將異常包裝成統一返回體,將異常狀態碼定義爲>=500的值(與HttpStatus相對應),修改SentinelResourceAspect實現,判斷返回的狀態碼是否爲>=500,若是是則進行熔斷統計。
  2. 並新增sentinel-dubbo-starter,進行自動配置化。
  3. Sentinel Dashboard改造:控制檯規則 -> 配置中心 -> 客戶端。

歡迎start,若有問題,歡迎指出,共同進步:

相關文章
相關標籤/搜索