天天看點

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

目錄

1、Sentinel服務熔斷功能

        一、Ribbon系列

        (一)提供者9003/9004

        (二)消費者84 

        二、OpenFeign系列

        三、熔斷架構比較

2、規則持久化

1、Sentinel服務熔斷功能

一、Ribbon系列

(一)提供者9003/9004

建立cloudalibaba-provider-payment9003/9004兩個一樣的做法

Pom

<dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定義的api通用包,可以使用Payment支付Entity -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web元件 -->
        <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>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
           

YML

server:
  port: 9003 #9004

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos位址

management:
  endpoints:
    web:
      exposure:
        include: '*'
           

 主啟動

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

業務類

@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    public static HashMap<Long,Payment> hashMap = new HashMap<>();
    static
    {
        hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
        hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
        hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
    }

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
        return result;
    }



}
           

 測試位址:http://localhost:9003/paymentSQL/1

(二)消費者84 

建立cloudalibaba-consumer-nacos-order84

POM

<dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- 引入自己定義的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web元件 -->
        <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>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
           

YML

server:
  port: 84


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard位址
        dashboard: localhost:8080
        #預設8719端口,假如被占用會自動從8719開始依次+1掃描,直至找到未被占用的端口
        port: 8719


#消費者将要去通路的微服務名稱(注冊成功進nacos的微服務提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider
 
           

主啟動

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

 業務類

ApplicationContextConfig

@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}
           

CircleBreakerController 

@RestController
@Slf4j
public class CircleBreakerController
{
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback") 
     public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法參數異常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,該ID沒有對應記錄,空指針異常");
        }

        return result;
    }
}
           

隻配置fallback

@RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback", fallback = "handlerFallback")
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法參數異常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,該ID沒有對應記錄,空指針異常");
        }

        return result;
    }

    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底異常handlerFallback,exception内容  "+e.getMessage(),payment);
    }
           

如果在自定義的異常之前就出現了異常,那麼輸出的就會是那個異常

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

 隻配置blockhandler

@RequestMapping("/consumer/fallback/{id}")
//    @SentinelResource(value = "fallback", fallback = "handlerFallback")
    @SentinelResource(value = "fallback", blockHandler = "blockHandler")
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法參數異常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,該ID沒有對應記錄,空指針異常");
        }

        return result;
    }

    public CommonResult blockHandler(@PathVariable  Long id, BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,無此流水: blockException  "+blockException.getMessage(),payment);
    }
           

異常超過2次後,斷路器打開,斷電跳閘,系統被保護 

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

 配置fallback和blockhandler

@RequestMapping("/consumer/fallback/{id}")
//    @SentinelResource(value = "fallback", fallback = "handlerFallback")
//    @SentinelResource(value = "fallback", blockHandler = "blockHandler")
    @SentinelResource(value = "fallback", fallback = "handlerFallback",blockHandler = "blockHandler")
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法參數異常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,該ID沒有對應記錄,空指針異常");
        }

        return result;
    }

    public CommonResult blockHandler(@PathVariable  Long id, BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,無此流水: blockException  "+blockException.getMessage(),payment);
    }

    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底異常handlerFallback,exception内容  "+e.getMessage(),payment);
    }
           
Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

如果次數沒有超過sentinel配置的流控規則的時候出現異常,那麼是調用了fallback方法。

當超過次數後無論是否出現異常,都是調用blockhandler。

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化
Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

二、OpenFeign系列

修改84子產品,Feign元件一般是用于消費側

POM檔案添加依賴

<!--SpringCloud openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
           

激活Sentinel對Feign的支援

# 激活Sentinel對Feign的支援
feign:
  sentinel:
    enabled: true 
        
           

 帶@FeignClient注解的業務接口

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//調用中關閉9003服務提供者
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
           

PaymentFallbackService

@Component
public class PaymentFallbackService implements PaymentService
{
    @Override
    public CommonResult<Payment> paymentSQL(Long id)
    {
        return new CommonResult<>(444,"服務降級傳回,沒有該流水資訊",new Payment(id, "errorSerial......"));
    }
}
           

 Controller

//==================OpenFeign
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/consumer/openfeign/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        if(id == 4)
        {
            throw new RuntimeException("沒有該id");
        }
        return paymentService.paymentSQL(id);
    }
           

主啟動類上添加@EnableFeignClients

 測試84調用9003,此時故意關閉9003微服務提供者,看84消費側自動降級,不會被耗死

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

 三、熔斷架構比較

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化

2、規則持久化

一旦我們重新開機應用,sentinel規則将消失,生産環境需要将配置規則進行持久化

将限流配置規則持久化進Nacos儲存,隻要重新整理8401某個rest位址,sentinel控制台

的流控規則就能看到,隻要Nacos裡面的配置不删除,針對8401上sentinel上的流控規則持續有效

修改cloudalibaba-sentinel-service8401

POM檔案添加依賴

<!--SpringCloud ailibaba sentinel-datasource-nacos -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
           

YML

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服務注冊中心位址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard位址
        port: 8719
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

management:
  endpoints:
    web:
      exposure:
        include: '*'

feign:
  sentinel:
    enabled: true # 激活Sentinel對Feign的支援
           

即添加了添加Nacos資料源配置

spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow
           

添加Nacos業務規則配置

Sentinel服務熔斷功能(sentinel整合ribbon+openFeign+fallback)1、Sentinel服務熔斷功能一、Ribbon系列二、OpenFeign系列 三、熔斷架構比較2、規則持久化
[
    {
        "resource": "/rateLimit/byUrl",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]
resource:資源名稱;
limitApp:來源應用;
grade:門檻值類型,0表示線程數,1表示QPS;
count:單機門檻值;
strategy:流控模式,0表示直接,1表示關聯,2表示鍊路;
controlBehavior:流控效果,0表示快速失敗,1表示Warm Up,2表示排隊等待;
clusterMode:是否叢集。
           

此時停止8401服務後再次啟動後就能看到流控規則了,但可能需要先通路幾次網址,流控規則才會出現在sentinel控制台