如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化

芊寶寶最可愛發表於2019-11-01

Nepxion Discovery框架在實現灰度釋出和路由功能前提下,結合Nacos和Sentinel,對流量再實施一層防護措施,更能達到企業級的流量安全控制的目的。它的功能包括:

  • 封裝遠端配置中心和本地規則檔案的讀取邏輯,即優先讀取遠端配置,如果不存在或者規則錯誤,則讀取本地規則檔案。動態實現遠端配置中心對於規則的熱重新整理
  • 封裝NacosDataSource和ApolloDataSource,支援Nacos和Apollo兩個遠端配置中心,零程式碼實現Sentinel功能。更多的遠端配置中心,請參照Sentinel官方的DataSource並自行整合
  • 支援原生的流控規則、降級規則、授權規則、系統規則、熱點引數流控規則
  • 支援擴充套件LimitApp的機制,透過動態的Http Header方式實現組合式防護機制,包括基於服務名、基於灰度組、基於灰度版本、基於灰度區域、基於機器地址和埠等防護機制,支援自定義任意的業務引數組合實現該功能,例如,根據傳入的微服務灰度版本號+使用者名稱,組合在一起進行熔斷
  • 支援微服務側Actuator、Swagger和Rest三種方式的規則寫入
  • 支援控制檯側基於微服務名的Actuator、Swagger和Rest三種方式的批次規則寫入
  • 支援開關關閉上述功能spring.application.strategy.sentinel.enabled=true,預設是關閉的

[ Nacos] 阿里巴巴中介軟體部門開發的新一代集服務註冊發現中心和配置中心為一體的中介軟體。它是構建以“服務”為中心的現代應用架構 (例如微服務正規化、雲原生正規化) 的服務基礎設施,支援幾乎所有主流型別的“服務”的發現、配置和管理,更敏捷和容易地構建、交付和管理微服務平臺

[ Sentinel] 阿里巴巴中介軟體部門開發的新一代以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性的分散式系統的流量防衛兵。它承接了阿里巴巴近10年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、訊息削峰填谷、叢集流量控制、實時熔斷下游不可用應用等

環境搭建及依賴引入

服務端在Discovery框架原有依賴的基礎上,再引入如下依賴

<dependency>
    <groupId>com.nepxion</groupId>
    <artifactId>discovery-plugin-strategy-starter-service-sentinel</artifactId>
    <version>${discovery.version}</version>
</dependency>
<dependency>
    <groupId>com.nepxion</groupId>
    <artifactId>discovery-plugin-strategy-sentinel-starter-nacos</artifactId>
    <!-- <artifactId>discovery-plugin-strategy-sentinel-starter-apollo</artifactId> -->
    <version>${discovery.version}</version>
</dependency>

原生Sentinel註解

參照下面程式碼,為介面方法增加@SentinelResource註解,value為sentinel-resource,blockHandler和fallback是防護其作用後需要執行的方法

@RestController
@ConditionalOnProperty(name = DiscoveryConstant.SPRING_APPLICATION_NAME, havingValue = "discovery-guide-service-b")
public class BFeignImpl extends AbstractFeignImpl implements BFeign {
    private static final Logger LOG = LoggerFactory.getLogger(BFeignImpl.class);
    @Override
    @SentinelResource(value = "sentinel-resource", blockHandler = "handleBlock", fallback = "handleFallback")
    public String invoke(@PathVariable(value = "value") String value) {
        value = doInvoke(value);
        LOG.info("呼叫路徑:{}", value);
        return value;
    }
    public String handleBlock(String value, BlockException e) {
        return value + "-> B server sentinel block, cause=" + e.getClass().getName() + ", rule=" + e.getRule() + ", limitApp=" + e.getRuleLimitApp();
    }
    public String handleFallback(String value) {
        return value + "-> B server sentinel fallback";
    }
}

原生Sentinel規則

Sentinel在配置中心訂閱的Key格式,如下:

1. Nacos的Key格式:Group為後設資料中配置的[組名],Data Id為[服務名]-[規則型別]
2. Apollo的Key格式:[組名]-[服務名]-[規則型別]

Sentinel規則的用法,請參照Sentinel官方文件

流控規則

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-flow,規則內容如下:

[
    {
        "resource": "sentinel-resource",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "refResource": null,
        "controlBehavior": 0,
        "warmUpPeriodSec": 10,
        "maxQueueingTimeMs": 500,
        "clusterMode": false,
        "clusterConfig": null
    }
]

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


降級規則

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-degrade,規則內容如下:

[
    {
        "resource": "sentinel-resource",
        "limitApp": "default",
        "count": 2,
        "timeWindow": 10,
        "grade": 0,
        "passCount": 0
    }
]

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


授權規則

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下:

[
    {
        "resource": "sentinel-resource",
        "limitApp": "discovery-guide-service-a",
        "strategy": 0
    }
]

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


系統規則

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-system,規則內容如下:

[
    {
        "resource": null,
        "limitApp": null,
        "highestSystemLoad": -1.0,
        "highestCpuUsage": -1.0,
        "qps": 200.0,
        "avgRt": -1,
        "maxThread": -1
    }
]

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


熱點引數流控規則

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-param-flow,規則內容如下:

[
    {
        "resource": "sentinel-resource",
        "limitApp": "default",
        "grade": 1,
        "paramIdx": 0,
        "count": 1,
        "controlBehavior": 0,
        "maxQueueingTimeMs": 0,
        "burstCount": 0,
        "durationInSec": 1,
        "paramFlowItemList": [],
        "clusterMode": false
    }
]

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


基於灰度路由和Sentinel-LimitApp擴充套件的防護機制

該方式對於上面5種規則都有效,這裡以授權規則展開闡述

授權規則中,limitApp,如果有多個,可以透過“,”分隔。"strategy": 0 表示白名單,"strategy": 1 表示黑名單

基於服務名的防護機制

修改配置項Sentinel Request Origin Key為服務名的Header名稱,修改授權規則中limitApp為對應的服務名,可實現基於服務名的防護機制

配置項,該配置項預設為n-d-service-id,可以不配置

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-id

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下,表示所有discovery-guide-service-a服務允許訪問discovery-guide-service-b服務

[
    {
        "resource": "sentinel-resource",
        "limitApp": "discovery-guide-service-a",
        "strategy": 0
    }
]

基於灰度組的防護機制

修改配置項Sentinel Request Origin Key為灰度組的Header名稱,修改授權規則中limitApp為對應的組名,可實現基於組名的防護機制

配置項

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-group

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下,表示隸屬my-group組的所有服務都允許訪問服務discovery-guide-service-b

[
    {
        "resource": "sentinel-resource",
        "limitApp": "my-group",
        "strategy": 0
    }
]

基於灰度版本的防護機制

修改配置項Sentinel Request Origin Key為灰度版本的Header名稱,修改授權規則中limitApp為對應的版本,可實現基於版本的防護機制

配置項

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-version

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下,表示版本為1.0的所有服務都允許訪問服務discovery-guide-service-b

[
    {
        "resource": "sentinel-resource",
        "limitApp": "1.0",
        "strategy": 0
    }
]

基於灰度區域的防護機制

修改配置項Sentinel Request Origin Key為灰度區域的Header名稱,修改授權規則中limitApp為對應的區域,可實現基於區域的防護機制

配置項

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-region

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下,表示區域為dev的所有服務都允許訪問服務discovery-guide-service-b

[
    {
        "resource": "sentinel-resource",
        "limitApp": "dev",
        "strategy": 0
    }
]

基於機器地址和埠的防護機制

修改配置項Sentinel Request Origin Key為灰度區域的Header名稱,修改授權規則中limitApp為對應的區域值,可實現基於機器地址和埠的防護機制

配置項

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-address

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下,表示地址和埠為192.168.0.88:8081和192.168.0.88:8082的服務都允許訪問服務discovery-guide-service-b

[
    {
        "resource": "sentinel-resource",
        "limitApp": "192.168.0.88:8081,192.168.0.88:8082",
        "strategy": 0
    }
]

自定義業務引數的組合式防護機制

透過適配類實現自定義業務引數的組合式防護機制

// 版本號+使用者名稱,實現組合式熔斷
public class MyServiceSentinelRequestOriginAdapter extends DefaultServiceSentinelRequestOriginAdapter {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String version = request.getHeader(DiscoveryConstant.N_D_SERVICE_VERSION);
        String user = request.getHeader("user");
        return version + "&" + user;
    }
}

在配置類裡@Bean方式進行適配類建立

@Bean
public ServiceSentinelRequestOriginAdapter ServiceSentinelRequestOriginAdapter() {
    return new MyServiceSentinelRequestOriginAdapter();
}

增加服務discovery-guide-service-b的規則,Group為discovery-guide-group,Data Id為discovery-guide-service-b-sentinel-authority,規則內容如下,表示版本為1.0且傳入的Http Header的user=zhangsan,同時滿足這兩個條件下的所有服務都允許訪問服務discovery-guide-service-b

[
    {
        "resource": "sentinel-resource",
        "limitApp": "1.0&zhangsan",
        "strategy": 0
    }
]

執行效果

  • 當傳遞的Http Header中user=zhangsan,當全鏈路呼叫中,API閘道器負載均衡discovery-guide-service-a服務到1.0版本後再去呼叫discovery-guide-service-b服務,最終呼叫成功

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


  • 當傳遞的Http Header中user=lisi,不滿足條件,最終呼叫在discovery-guide-service-b服務端被拒絕掉

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


  • 當傳遞的Http Header中user=zhangsan,滿足條件之一,當全鏈路呼叫中,API閘道器負載均衡discovery-guide-service-a服務到1.1版本後再去呼叫discovery-guide-service-b服務,不滿足version=1.0的條件,最終呼叫在discovery-guide-service-b服務端被拒絕掉

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


基於Swagger的Sentinel規則推送

分為基於單個服務例項和基於服務名對應的多個服務例項的Sentinel規則推送

基於單個服務例項的Sentinel規則推送

直接訪問該服務例項的Swagger主頁即可

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


基於服務名對應的多個服務例項的Sentinel規則推送

需要開啟discovery-console服務,並訪問其Swagger主頁即可

如圖所示

如何基於 Nacos 和 Sentinel ,實現灰度路由和流量防護一體化


原文連結

本文為雲棲社群原創內容,未經允許不得轉載。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69949601/viewspace-2662291/,如需轉載,請註明出處,否則將追究法律責任。

相關文章