【Spring Cloud Alibaba】【Hoxton】Sentinel 熱點規則-@SentinelResource-熔斷-持久化(二)

1 Nacos 入門-配置中心-集羣
2 Sentinel 入門-限流-降級(一)
3 Sentinel 熱點規則-@SentinelResource-熔斷-持久化(二)
4 Seata從入門到實戰

1 熱點參數限流

何爲熱點?熱點即經常訪問的數據。很多時候我們希望統計某個熱點數據中訪問頻次最高的 Top K 數據,並對其訪問進行限制。比如:

  • 商品 ID 爲參數,統計一段時間內最常購買的商品 ID 並進行限制
  • 用戶 ID 爲參數,針對一段時間內頻繁訪問的用戶 ID 進行限制
    熱點參數限流會統計傳入參數中的熱點參數,並根據配置的限流閾值與模式,對包含熱點參數的資源調用進行限流。熱點參數限流可以看做是一種特殊的流量控制,僅對包含熱點參數的資源調用生效。
    在這裏插入圖片描述

1.1 新建Controller

@RestController
public class HotkeyController {
    /**
     * SentinelResource: sentinel相關配置,value唯一,blockHandler回調方法
     */
    @GetMapping("/hotkey")
    @SentinelResource(value = "hotkey",blockHandler = "dealHotkey")
    public String hotkey(@RequestParam(value = "key",required = false) String key){
        return "hello hotkey,  O(∩_∩)O";
    }
    public String dealHotkey(String key, BlockException e){
        return "調用失敗,   o(╥﹏╥)o";
    }
}

1.2 新建熱點規則

解釋:資源名爲@SentinelResource的value值,閾值是qp的值,統計時長是發生後1秒內降級。
在這裏插入圖片描述

1.3 測試

隨便調用:http://localhost:9004/hotkey
在這裏插入圖片描述
調用http://localhost:9004/hotkey?key=sentinel頻繁時:
在這裏插入圖片描述

1.4 參數例外項

期望當key爲phone時qps爲100,剩下的爲1
在這裏插入圖片描述

狂點後仍然返回正確的行爲:
在這裏插入圖片描述

2 @SentinelResource

2.1 按資源名稱添加流控規則

(1) 創建Controller

@RestController
public class SentinelResourceController {
    @GetMapping("/resource")
    @SentinelResource(value = "resource",blockHandler = "handleException")
    public String resource(){
        return "SentinelResourceController invoke resource success";
    }
    public String handleException(BlockException e){
        return "SentinelResourceController invoke handleException";
    }
}

(2) 新建流控規則
在這裏插入圖片描述
(3) 刷新頻繁會出現
在這裏插入圖片描述

2.2 自定義異常返回類

(1) 自定義handler

public class ZrsBlockHandler {
    public static String handler1Exception(BlockException exception){
        return  "ZrsBlockHandler invoke handler【1】Exception";
    }
    public static String handler2Exception(BlockException exception){
        return  "ZrsBlockHandler invoke handler【2】Exception";
    }
}

(2) 修改SentinelResourceController


@RestController
public class SentinelResourceController {
    @GetMapping("/resource")
    @SentinelResource(value = "resource",blockHandler = "handleException")
    public String resource(){
        return "SentinelResourceController invoke resource success";
    }
    public String handleException(BlockException e){
        return "SentinelResourceController invoke handleException";
    }
    @GetMapping("/handler1")
    @SentinelResource(value = "handler1Exception",blockHandlerClass = ZrsBlockHandler.class,
    blockHandler = "handler1Exception")
    public String handler1(){
        return "SentinelResourceController invoke resource success";
    }

    @GetMapping("/handler2")
    @SentinelResource(value = "handler2Exception",blockHandlerClass = ZrsBlockHandler.class,
            blockHandler = "handler2Exception")
    public String handler2(){
        return "SentinelResourceController invoke resource success";
    }
}

(3) 啓動服務

http://localhost:9004/handler1
http://localhost:9004/handler2

(4) 添加流控規則
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
(5) 頻繁訪問
在這裏插入圖片描述

在這裏插入圖片描述

3 熔斷

3.1 環境準備

(1) 初始化環境

#代碼爲【Spring Cloud Alibaba】【Hoxton】Nacos 入門-配置中心-集羣。文章中的代碼,或者直接訪問該文章底部的github
#文章機票爲https://blog.csdn.net/qq_34125999/article/details/104934796
provider,服務名provider,註冊到nacos
provider-slave,服務名provider,註冊到nacos
customer,服務名customer去nacos消費服務

在這裏插入圖片描述
(2)啓動環境
在這裏插入圖片描述
(3) 測試
在這裏插入圖片描述

在這裏插入圖片描述

3.2 修改customer程序

(1) 修改pom


<dependencies>
    <!--sentinel nacos-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    <!--sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!--spring cloud alibaba-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!--devtools熱部署-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
        <scope>true</scope>
    </dependency>
</dependencies>

(2) 修改application.yml

server:
  port: 9002
spring:
  application:
    name: customer
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.0.39:8848
    sentinel:
      transport:
        #配置sentinel地址,端口
        dashboard: 192.168.0.39:8080
        port: 8719
        #客戶端IP
        client-ip: 192.168.0.100

(3) 修改CustomerController

@RestController
@RequestMapping("/customer")
public class CustomerController {
    @Autowired
    private RestTemplate restTemplate;

    private final String SERVER_URL="http://provider"

    @GetMapping(value = "/hello")
    @SentinelResource(value = "hello")
    public String hello(){
        return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
    }
}

(4) 啓動主程序後訪問

http://localhost:9002/customer/hello

(5) 查看sentinel頁面
在這裏插入圖片描述

3.3 fallback

(1) 修改CustomerController

@RestController
@RequestMapping("/customer")
public class CustomerController {
    @Autowired
    private RestTemplate restTemplate;

    private final String SERVER_URL="http://provider";

    @GetMapping(value = "/hello/{id}")
    @SentinelResource(value = "hello",fallback = "fallbackHandler")
    public String hello(@PathVariable("id") String id){
        if (id.equals("1")){
            throw new RuntimeException("id不能爲1");
        }
        return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
    }

    public String fallbackHandler(@PathVariable("id") String id ,Throwable e){
        return "CustomerController invoke fallbackHandler";
    }
}

(2) 測試
在這裏插入圖片描述

在這裏插入圖片描述

3.4 blockHandler

(1) 修改CustomerController,僅配置blockHandler

@RestController
@RequestMapping("/customer")
public class CustomerController {

    @Autowired
    private RestTemplate restTemplate;

    private final String SERVER_URL="http://provider";

    /**
     *  blockHandler:僅負責sentinel違規
     */
    @GetMapping(value = "/hello/{id}")
    @SentinelResource(value = "hello",blockHandler = "helloBlockHandler")
    public String hello(@PathVariable("id") String id){
        if (id.equals("1")){
            throw new RuntimeException("id不能爲1");
        }
        return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
    }
    public String fallbackHandler(@PathVariable("id") String id ,Throwable e){
        return "CustomerController invoke fallbackHandler";
    }
    public String helloBlockHandler(String id,BlockException e){
        return "CustomerController invoke blockHandler";
    }
}

(2) sentinel配置
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
(3) 測試

#訪問1時直接報錯,java沒有對應fallback處理
http://localhost:9002/customer/hello/1
#當頻繁訪問,出現限流響應
http://localhost:9002/customer/hello/2

在這裏插入圖片描述
在這裏插入圖片描述

3.5 fallback、blockHandler同時配置

(1) 修改CustomerController

@RestController
@RequestMapping("/customer")
public class CustomerController {

    @Autowired
    private RestTemplate restTemplate;

    private final String SERVER_URL="http://provider";

    /**
     *  blockHandler:僅負責sentinel違規
     */
    @GetMapping(value = "/hello/{id}")
    @SentinelResource(value = "hello",blockHandler = "helloBlockHandler",fallback = "fallbackHandler")
    public String hello(@PathVariable("id") String id){
        System.out.println(id);
        if (id.equals("1")){
            throw new RuntimeException("id不能爲1");
        }
        return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
    }


    public String fallbackHandler(@PathVariable("id") String id ,Throwable e){
        return "CustomerController invoke fallbackHandler";
    }


    public String helloBlockHandler(String id,BlockException e){
        return "CustomerController invoke blockHandler";
    }


}

(2) 測試

#java異常fallback->fallbackHandler
http://localhost:9002/customer/hello/1
#限流控制->helloBlockHandler
http://localhost:9002/customer/hello/2

在這裏插入圖片描述

在這裏插入圖片描述

3.6 OpenFegin

(1) 創建工程
在這裏插入圖片描述

(2) pom

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--sentinel nacos-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    <!--sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!--spring cloud alibaba-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!--devtools熱部署-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
        <scope>true</scope>
    </dependency>
</dependencies>

(3) application.yml

server:
  port: 9005
spring:
  application:
    name: customer-fegin
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.0.39:8848
    sentinel:
      transport:
        #配置sentinel地址,端口
        dashboard: 192.168.0.39:8080
        port: 8719
        #客戶端IP
        client-ip: 192.168.0.100
#開啓sentinel 對fegin的支持
feign:
  sentinel:
    enabled: true

(4) 主啓動類

@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
public class FeginApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeginApplication.class);
    }
}

(5) 降級類

@Service
public class ProviderServiceFallback implements ProviderService {
    @Override
    public String hello() {
        return "ProviderServiceFallback invoke hello";
    }
}

(6) Fegin服務類


@FeignClient(value = "provider",path = "/provider",fallback = ProviderServiceFallback.class)
@Service
public interface ProviderService {
    @GetMapping("/hello")
    String hello();
}

(7) Controller

@RestController
@RequestMapping("/fegin")
public class FeginController {

    @Autowired
    private ProviderService providerService;

    @GetMapping("/hello")
    @SentinelResource(value = "hello")
    public String hello(){
        return providerService.hello();
    }
}

(8) 啓動主程序

#報錯
com.alibaba.cloud.sentinel.feign.SentinelContractHolder.parseAndValidateMetadata(Ljava/lang/Class;)
#解決辦法,修改父pomspringcloud版本爲Hoxton.SR1。- -,BUG。期待後續解決 - -!!!,修改後重啓解決
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>

在這裏插入圖片描述
在這裏插入圖片描述
(9) 測試
在這裏插入圖片描述

在這裏插入圖片描述

4 持久化配置

當關閉FeginApplication時,打開sentinel頁面
在這裏插入圖片描述

4.1 修改customer-fegin的application.yml

server:
  port: 9005
spring:
  application:
    name: customer-fegin
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.0.39:8848
    sentinel:
      transport:
        dashboard: 192.168.0.39:8080
        port: 8719
        client-ip: 192.168.0.100
      datasource:
        na:
          nacos:
            server-addr: 192.168.0.39:8848
            groupId: DEFAULT_GROUP
            dataId: customer-fegin
            rule-type: flow
#開啓sentinel 對fegin的支持
feign:
  sentinel:
    enabled: true

4.2 nacos添加配置

(1) 新建配置
在這裏插入圖片描述
(2) json串

 [{
    "resource": "hello",
    "limitApp": "default",
    "grade": 1,
    "count": 1,
    "strategy": 0,
    "controlBehavior": 0,
    "clusterMode": false
}]

(3) 參數解析

resource:資源名稱;
IimitApp:來源應用;
grade:國值類型,0表示線程數,1表示QPS;
count:單機閾值
strategy:流控模式,0表示直接,1表示關聯,2表示鏈路
controlbehavior:流控效果,0表示快速失敗,1表示 Warm Up,2表示排隊等待;
cluster Mode:是否集羣。

(4) 查看列表
在這裏插入圖片描述

4.3 修改Controller

@RestController
@RequestMapping("/fegin")
public class FeginController {
    @Autowired
    private ProviderService providerService;

    @GetMapping("/hello")
    @SentinelResource(value = "hello",blockHandler = "helloBlockHandler")
    public String hello(){
        return  providerService.hello();
    }

    public String helloBlockHandler(BlockException e){
        return "CustomerController invoke blockHandler";
    }
}

4.3 啓動主程序

#訪問後,查看sentinelhttp://localhost:9005/fegin/hello

在這裏插入圖片描述

頻繁訪問後:
在這裏插入圖片描述

LAST GITHUB

#分支Sentinel-release-v1.0
https://github.com/zhurongsheng666/spring-cloud-alibaba
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章