Spring Cloud Alibaba系列(六)sentinel的實際應用

来源:https://www.cnblogs.com/zhixie/archive/2020/07/06/13253166.html
-Advertisement-
Play Games

一、sentinel的持久化配置 上一章中我們通過Dashboard來為Sentinel客戶端設置各種各樣的規則,但是這些規則預設是存放在記憶體中,極不穩定,無法用於生成環境,所以需要將其持久化。 DataSource 擴展常見的實現方式有: 拉模式:客戶端主動向某個規則管理中心定期輪詢拉取規則,這個 ...


一、sentinel的持久化配置

上一章中我們通過Dashboard來為Sentinel客戶端設置各種各樣的規則,但是這些規則預設是存放在記憶體中,極不穩定,無法用於生成環境,所以需要將其持久化。

DataSource 擴展常見的實現方式有:

  • 拉模式:客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS、文件,甚至是 VCS 等。這樣做的方式是簡單,缺點是無法及時獲取變更;
  • 推模式:規則中心統一推送,客戶端通過註冊監聽器的方式時刻監聽變化,比如使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。

Sentinel 目前支持以下數據源擴展:

生產環境中一般常用的就是推模式。這裡我們使用Nacos存儲規則。推送模式的正確做法應該是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 數據源 → Sentinel

1.1 sentinel同步nacos配置

  1. 增加sentinel的依賴和nacos存儲擴展依賴
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. 添加nacos相關配置
spring:
  cloud:
    sentinel:
      datasource:
        # 名稱隨意
        javatrip:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-rules
            groupId: SENTINEL_GROUP
            # 規則類型,取值見:
            # org.springframework.cloud.alibaba.sentinel.datasource.RuleType
            rule-type: flow
  1. 提供介面用於測試限流
@RestController
class test{

    @RequestMapping("/test")
    public String test(){
        return "Java旅途";
    }
}
  1. nacos中增加限流規則的配置

  • resource:資源名,即限流規則的作用對象
  • limitApp:流控針對的調用來源,若為 default 則不區分調用來源
  • grade:限流閾值類型(QPS 或併發線程數);0代表根據併發數量來限流,1代表根據QPS來進行流量控制
  • count:限流閾值
  • strategy:調用關係限流策略
  • controlBehavior:流量控制效果(直接拒絕、Warm Up、勻速排隊)
  • clusterMode:是否為集群模式
  1. 測試,訪問test介面,發現sentinel-dashboard中出現了一條流控規則

1.2 sentinel-dashboard中修改規則同步到nacos

要想實現在sentinel-dashboard中修改規則並同步到nacos,我們就需要修改sentinel服務。首先我們去官網下載Sentinel。

  1. 修改pom文件
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <scope>test</scope>
</dependency>

test註釋掉,因為這個是作用與test目錄下的。

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <!--<scope>test</scope>-->
</dependency>
  1. 找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目錄,將整個目錄拷貝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/
  2. 找到 com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2 ,將預設動態規則修改為nacos動態規則。
@Autowired
@Qualifier("flowRuleDefaultProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleDefaultPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

修改為:

@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
  1. 找到 sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html

將以下內容註釋去掉

<!--<li ui-sref-active="active" ng-if="entry.appType==0">-->
    <!--<a ui-sref="dashboard.flow({app: entry.app})">-->
    	<!--<i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控規則 V1</a>-->
<!--</li>-->
  1. 重新編譯打包,運行打包後的sentinel-dashboard.jar。

  2. 測試,我們刪除nacos中的流量規則配置

  • 在sentinel-dashboard——>流量規則V1中新增一個規則。

  • 刷新nacos,發現多了一個配置

  • 在nacos中修改這個配置,將閥值改為1

  • 刷新sentinel-dashboard,流量閥值修改為1了。

  • 重啟服務,重啟sentinel-dashboard,發現流控規則依然存在。

註意:以上只是演示了流控規則的持久化,sentinel還支持其他規則,如果想實現哪種規則都可以採用相同的方式實現!

二、Gateway網關限流

限流:就是請求多了,對請求進行定製的快速響應處理,應用在服務提供者本身。

從 1.6.0 版本開始,Sentinel 提供了 Spring Cloud Gateway 的適配模塊,可以提供兩種資源維度的限流:

  • route 維度:即在 Spring 配置文件中配置的路由條目,資源名為對應的 routeId
  • 自定義 API 維度:用戶可以利用 Sentinel 提供的 API 來自定義一些 API 分組
  1. 添加依賴
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>x.y.z</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
  1. 註入對應的 SentinelGatewayFilter 實例以及 SentinelGatewayBlockExceptionHandler 實例。
@Configuration
public class GatewayConfiguration {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers=viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new MySentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
}
  1. 自定義異常處理
public class MySentinelGatewayBlockExceptionHandler extends SentinelGatewayBlockExceptionHandler {

    private List<ViewResolver> viewResolvers;
    private List<HttpMessageWriter<?>> messageWriters;
    public MySentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
        super(viewResolvers,serverCodecConfigurer);
        this.viewResolvers = viewResolvers;
        this.messageWriters = serverCodecConfigurer.getWriters();
    }
    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {

        if(serverWebExchange.getResponse().isCommitted()){
            return Mono.error(throwable);
        }
        if(!BlockException.isBlockException(throwable)){
            return Mono.error(throwable);
        }
        return handleBlockedRequest(serverWebExchange, throwable).flatMap(response -> writeResponse(response, serverWebExchange));
    }
    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) {
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }

    private final Supplier<ServerResponse.Context> contextSupplier = () -> new ServerResponse.Context() {
        @Override
        public List<HttpMessageWriter<?>> messageWriters() {
            return MySentinelGatewayBlockExceptionHandler.this.messageWriters;
        }

        @Override
        public List<ViewResolver> viewResolvers() {
            return MySentinelGatewayBlockExceptionHandler.this.viewResolvers;
        }
     };

    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
        ServerHttpResponse resp = exchange.getResponse();
        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        String json = "{\"code\": -1, \"data\": null, \"msg\": \"訪問量過大,請稍後再試\"}";
        DataBuffer buffer = resp.bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Mono.just(buffer));
    }
}
  1. 配置路由
server:
  port: 7003
spring:
  application:
    name: alibaba-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      enabled: true
      discovery:
        locator:
          enabled: true # 開啟從註冊中心動態創建路由的功能,利用微服務名稱進行路由
      routes:
      - id: sentinel-nacos # 路由id,建議配合服務名
        uri: lb://sentinel-nacos #匹配路由名
        predicates:
          - Path=/sentinel/** # 斷言,路徑相匹配的進行路由
        filters:
          - StripPrefix=1
  1. 添加啟動參數
-Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8081 -Dproject.name=alibaba-gateway

  1. 訪問介面,查看效果

三、feign調用實現熔斷降級

降級:就是服務崩潰了,所以降級邏輯應該應用在消費者(調用者)那裡,加在服務提供者本身是毫無意義的,因為服務已經斷開了。

我們根據實際需求在sentinel-dashboard中配置降級規則,然後編寫代碼。

  1. 定義介面
@RequestMapping("/test")
public String test(){
    return "Java旅途";
}
  1. 定義遠程服務調用介面
@FeignClient(name = "nacos-sentinel",fallback = RmoteTestFallback.class)
interface RemoteTest{
    @RequestMapping("/test")
    public String test();
}

為了簡寫fallback,我們更傾向於用fallbackFactory = RmoteTestFallbackFactory.class

@FeignClient(name = "nacos-sentinel",fallbackFactory = RmoteTestFallbackFactory.class)
interface RemoteTest{
    @RequestMapping("/test")
    public String test();
}
  1. 服務降級處理fallback
@Component
class RmoteTestFallback implements RemoteTest{
    @Override
    public String test() {
        return null;
    }
}
  1. 服務降級處理fallbackFactory
@Component
class RmoteTestFallbackFactory implements FallbackFactory<RemoteTest> {
    @Override
    public RemoteTest create(Throwable throwable) {
        return null;
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天看見徒弟寫個css屬性這麼慢,是在是看不下去了,就問了他有沒有用過一些輔助工具,他說沒有,額。。。我也是很無語,沒辦法,誰叫我是他師傅呢。還是要盡到一個師傅的責任。所以就利用休息時間給他講了19個輔助工具,滿滿的乾貨呀。我這也是第一次給別人說這麼多,這麼詳細,想想還不錯,教給別人東西的感覺是不一 ...
  • 2020年是充滿機遇與挑戰的一年,這一年註定不平凡。隨著5G商用、傳統產業數字化轉型加快,我們完全可以想象到互聯網行業即將迎來自己的“高光時刻”,因此,現在學習web前端正當時。 那麼,對於零基礎小白而言,如何才能快速學習web前端呢?下麵,就為大家分享2020年web前端學習路線。 很多對於web ...
  • 本文將介紹 CSS 中一個非常有意思的屬性 mask 。 顧名思義,mask 譯為遮罩。在 CSS 中,mask 屬性允許使用者通過遮罩或者裁切特定區域的圖片的方式來隱藏一個元素的部分或者全部可見區域。 其實 mask 的出現已經有一段時間了,只是沒有特別多實用的場景,在實戰中使用的非常少,本文將羅 ...
  • 背景 我是一名程式員,從事前端開發,一個月15K,在北京雖是月光族但日子也還可以過下去;女朋友就沒有這麼幸運了,受疫情的影響,公司裁員。。。從4月開始就一直在找工作,但都不順利,不是工資低到可憐就是面試後沒有下文; 身邊的朋友都開玩笑的說,你也可以和你男朋友一樣從事前端開發呀!!! 我天。。。反對。 ...
  • 上次成功搭建了vue + electron的helloworld程式,這次將electron應用打包及自動升級的流程梳理了一下。 1. 應用打包 使用electron builder打包只需要在vue.config.js中配置即可,這裡需要註意的是,預設情況下electron builder打包出來 ...
  • 消息隊列 基本概述 MQ,Message Queue,基於TCP協議構建的簡單協議,區別於具體的通信協議。 基於通信協議定義和抽象的更高層次的通信模型,一般都是生產者和消費者模型,又或者說服務端和客戶端模型。 生產者/消費者模型:一般通過定義生產者和消費者實現消息通信從而屏蔽複雜的底層通信協議。應用 ...
  • 【本文完善中...】 無論是http介面,還是rpc介面,防重覆提交(介面防重)都是繞不過的話題。 重覆提交與冪等,既有區別,又有聯繫。冪等的意思是,對資源的一次請求與多次請求,作用是相同的。HTTP的POST方法是非冪等的。如果程式處理不好,重覆提交會導致非冪等,引起系統數據故障。防重覆提交,要通 ...
  • 1.模型管理 :web線上流程設計器、預覽流程xml、導出xml、部署流程 2.流程管理 :導入導出流程資源文件、查看流程圖、根據流程實例反射出流程模型、激活掛起 、自由跳轉 3.運行中流程:查看流程信息、當前任務節點、當前流程圖、作廢暫停流程、指派待辦人 4.歷史的流程:查看流程信息、流程用時、流 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...