SpringCloud Alibaba之Sentinel集成Ribbon/OpenFeign案例演示

所有代碼都在github上:https://github.com/demonruin/cloud2020/tree/master

Sentinel集成Ribbon:

1、準備服務提供者cloudalibaba-nacos-provider-payment9001,cloudalibaba-nacos-provider-payment9002,主要是端口不一樣,其他一致,下面附上pom、yml和主業務類代碼,這裏自己建module即可

       <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </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>
server:
  port: 9001

spring:
  application:
    name: nacos-provider-payment
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

#暴露所有端點,和actuator監控有關
management:
  endpoints:
    web:
      exposure:
        exclude: "*"
package com.king.springcloud.controller;

import com.king.springcloud.entities.CommonResult;
import com.king.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

/**
 * created by king on 2020/5/8 12:38 下午
 */
@RestController
@Slf4j
public class PaymentController {

    @Value("${server.port}")
    private String serverPort;


    /**
     * 此方法與接口是爲了測試sentinel的fallback服務降級
     * @param id
     * @return
     */
    public static HashMap<Integer, Payment> hashMap = new HashMap();

    static {
        hashMap.put(1, new Payment(1L, "28a8c1e3bc2742d8848569891fb42181"));
        hashMap.put(2, new Payment(2L, "bba8c1e3bc2742d8848569891ac32182"));
        hashMap.put(3, new Payment(3L, "6ua8c1e3bc2742d8848569891xt92183"));
    }

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


}

主啓動類就是正常的主啓動類

package com.king.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * created by king on 2020/5/8 12:08 下午
 */
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderPaymentMain9001 {
    public static void main(String[] args) {
            SpringApplication.run(NacosProviderPaymentMain9001.class,args);
        }
}

2、主要是構建服務消費者微服務,這裏pom中添加nacos/sentinel/openFeing等依賴,yml中添加nacos和sentinel的配置,再有測試業務類

 <!--SpringCloud openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--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>
        <!-- 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>
        <dependency>
            <groupId>com.king.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
server:
  port: 83

spring:
  application:
    name: nacos-consumer-order
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
package com.king.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * created by king on 2020/5/8 4:01 下午
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NacosConsumerOrderMain83 {
    public static void main(String[] args) {
        SpringApplication.run(NacosConsumerOrderMain83.class, args);
    }
}

業務類CircleBreakerController

package com.king.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.king.springcloud.entities.CommonResult;
import com.king.springcloud.entities.Payment;
import com.king.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * created by king on 2020/5/29 11:19 上午
 */
@RestController
@Slf4j
public class CircleBreakerController {
    private static  String SERVICE_URL="http://nacos-provider-payment/";
    @Resource
    private RestTemplate restTemplate;



    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback") //沒有配置
    //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
    //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
//    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
//            exceptionsToIgnore = {IllegalArgumentException.class})
    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
    public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底異常handlerFallback,exception內容  "+e.getMessage(),payment);
    }
    //本例是blockHandler
    public CommonResult blockHandler(@PathVariable  Long id, BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,無此流水: blockException  "+blockException.getMessage(),payment);
    }

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

    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        return paymentService.paymentSQL(id);
    }

}

3、此時測試代碼準備完畢,進行測試

  • 當@SentinelResource(value = "fallback") //沒有其他任何配置的時候,根據代碼處理,
    • 當我們id=1或2或3時,是能正常響應的
    • 當我們id=4時,會IllegalArgumentException,非法參數異常....
    • 當我們id=5時,會NullPointerException,該ID沒有對應記錄,空指針異常

  • 當@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
    • 當我們id=1或2或3時,是能正常響應的
    • 當我們id=4時,會有 handlerFallback來處理異常
    • 當我們id=5時,會有 handlerFallback來處理異常

  • 當@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
    • 當我們id=1或2或3時,1qps是能正常響應的,快速訪問會觸發流控規則,返回自定義的處理方法結果
    • 當我們id=4時,1qps是能正常響應的,快速訪問會觸發流控規則,返回自定義的處理方法結果
    • 當我們id=5時,1qps是能正常響應的,快速訪問會觸發流控規則,返回自定義的處理方法結果

我們對@SentinelResource的value值進行流控限制

  • 當@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class})
    • 當我們id=1或2或3時,1qps是能正常響應的,快速訪問會觸發流控規則,返回自定義的處理方法結果
    • 當我們id=4時,因爲exceptionsToIgnore = {IllegalArgumentException.class},忽略了這個異常,所以1qps訪問還是會正常報錯頁面的,快速訪問會觸發流控規則,返回自定義的處理方法結果
    • 當我們id=5時,1qps是能正常響應的,快速訪問會觸發流控規則,返回自定義的處理方法結果

 

對了,多次刷新訪問id=1的時候,會有Ribbon的輪訓功能,會輪訓請求9001和9002端口的服務~~~~~~~

至此是Sentinel集成Ribbon的案例,及@SentinelResource的fallback演示~~

 

Sentinel集成OpenFeign

1、在上述基礎上,添加feign調用接口代碼:

帶@FeignClient註解的業務接口 :PaymentService接口

package com.king.springcloud.service;

import com.king.springcloud.entities.CommonResult;
import com.king.springcloud.entities.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * created by king on 2020/5/29 1:30 下午
 */
@FeignClient(value = "nacos-provider-payment", fallback = PaymentServiceFallback.class)
public interface PaymentService {
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

fallback = PaymentServiceFallback.class  :PaymentServiceFallback處理方法:注意加@Component註解

package com.king.springcloud.service;

import com.king.springcloud.entities.CommonResult;
import com.king.springcloud.entities.Payment;
import org.springframework.stereotype.Component;

/**
 * created by king on 2020/5/29 1:33 下午
 */
@Component
public class PaymentServiceFallback implements PaymentService{
    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(44444,"服務降級返回,---PaymentFallbackService",new Payment(id,"errorSerial"));
    }
}

controller中的fengin代碼上面已經粘貼了,現在附上主要代碼

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

    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        return paymentService.paymentSQL(id);
    }

在yml文件中添加  激活Sentinel對Feign的支持


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

2、進行測試~~

①、正常請求接口,能正常訪問,返回結果

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

此時調用了服務降級,說明OpenFeign的fallback處理邏輯生效了~~

至此Sentinel對OpenFeign的集成案例演示完畢~~

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章