Sentinel 服务熔断降级 及 整合openfeign

1.启动sentinel dashboard 及nacos

在这里sentinel 我使用的是 1.7.0的windows版本

在文件目录下 启动cmd 输入命令java -jar sentinel-dashboard-1.7.0.jar

访问 http://localhost:8080 登录即可(默认账户密码都是sentinel

启动nacos ,我使用的是1.1.4 的windos版本 运行bin目录下的startup.cmd

访问 http://localhost:8848/nacos/ 登录即可(默认账户密码都是nacos

2.熔断降级

要使用熔断降级,必须先了解@SentinelResource注解

2.1 @SentinelResource

该注解通常用在服务熔断降级的业务方法上(为了方便代码演示,我写在了接口上)

参数:

  • value:自定义资源名
  • blockHandler:请求触发sentinel配置规则时,调用的方法
  • blockHandlerClassblockHandler单独集中配置的类
  • fallbackHandler:java代码发生运行时异常时,调用的方法
  • fallbackHandlerClass:将fallbackHandler:单独集中配置的类
  • exceptionsToIgnore: 忽略的异常类型(出现了该异常不会调用fallbackHandler以及blockHandler)

2.2创建订单微服务84

pom

在这里springcloud-alibaba使用的是2.1.0.RELEASE版本,spring-boot使用的是2.2.2.RELEASE版本

    <dependencies>
        <!--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>
    </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


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

主启动类

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

/**
 * @author Xkuna
 * @date 2020/8/17 20:29.
 */
@SpringBootApplication
@EnableDiscoveryClient //nacos
@EnableFeignClients  //feign
public class OrderNacosMain84 {
    public static void main(String[] args) {
        SpringApplication.run(OrderNacosMain84.class, args) ;
    }
}

创建controller

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;


/**
 * @author Xkuna
 * @date 2020/8/17 20:32.
 */
@RestController
public class OrderController {
    @GetMapping("/fallback/{id}")
    @SentinelResource(value = "fallback", blockHandler = "blockHandler1",fallback = "fallbackHandler",
        exceptionsToIgnore = IllegalArgumentException.class
    )
    public String fallback(@PathVariable("id") Long id){
        if(id == 4){
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if(id > 4){
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }else{
            return "ok-------id: " + id ;
        }
    }
    public String blockHandler1(@PathVariable("id") Long id, BlockException blockException){
        return "---blockHandler" ;
    }

    public String fallbackHandler(@PathVariable Long id){
        return "----fallbackHandler" ;
    }
}

解释下上面配置的接口:

​ 接口传入一个Lone类型的id,id < 4,正常访问,id =4 会报IllegalArgumentException,但是 exceptionsToIgnore配置了这个异常,所以我们传入id =4 时,那么会直接出现 errorPage而不会调用fallbackhandler, 如果id > 4,会调用 fallbackHandler

启动 订单服务84,进行测试:

​ 访问 http://localhost:84/fallback/3

image-20200818133759138

访问 http://localhost:84/fallback/4

image-20200818133825867

访问 http://localhost:84/fallback/5

image-20200818133843611

以上是我们还没有配置降级规则,接下来我们在sentinel控制台配置 降级规则(如果不显示服务,先多次访问下 http://localhost:84/fallback/3)

降级规则: RT 异常比例 异常数

  1. RT

image-20200818134846650

image-20200818134853508

  1. 异常比率

image-20200818134944215

image-20200818134948104

  1. 异常数

image-20200818135002764

image-20200818135006452

在这里我们只演示下异常比例

image-20200818135134544

这里我们配置含义是:

​ 当一秒内请求数 >= 5,且出现异常的请求 >= 30 %,那么在5s内 发生降级(返回blockHandler),5s后恢复,但是在异常请求达到30%之前,不会触发降级规则,所以如果未配置fallbackHandler,则会出现errorpage(这里就不演示了)

我们快速多次访问 http://localhost:84/fallback/3

image-20200818135743672

快速多次访问 http://localhost:84/fallback/4

image-20200818135805231

因为我们id=4时报的异常我们已经忽略了,所以blockHandlerfallbackHandler 都不会返回

image-20200818135937720

快速多次访问 http://localhost:84/fallback/5

会发现前几次返回的是 fallbackHandler 然后慢慢的变为blockHandler 大约5

s后再次变为 fallbackHandler ,这就证明了我们上面的结论

3.Sentinel整合OpenFeign

在这里我们创建两个支付微服务,订单服务通过OpenFeign调用订单微服务 并且实现负载均衡(在这里就不写支付微服的sentinel熔断降级了)

3.1 创建支付微服务 9003

pom

<dependencies>
        <!--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>
        <!--日常通用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

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

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

主启动类

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

/**
 * @author Xkuna
 * @date 2020/8/17 20:59.
 */
@SpringBootApplication
@EnableDiscoveryClient //nacos
public class PaymentMain9003 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9003.class, args) ;
    }
}

创建controller

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Xkuna
 * @date 2020/8/17 21:01.
 */
@RestController
public class PaymentController {
    @Value("${server.port}")
    private String port ;

    @GetMapping("/port")
    public String getPort(){
        return port ;
    }
}

3.2 创建支付微服务 9004

copy 支付微服务9003 修改端口为9004 即可

3.3修改订单微服务

创建 openfeign调用接口以及fallback实现类

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author Xkuna
 * @date 2020/8/17 21:09.
 */
@Service
@FeignClient(value = "nacos-payment-provider", fallback = PaymentServiceImpl.class)
public interface PaymentService {
    @GetMapping("/port")
    public String getPort() ;
}
import org.springframework.stereotype.Component;

/**
 * @author Xkuna
 * @date 2020/8/17 21:10.
 */
@Component //注意注入ioc容器
public class PaymentServiceImpl implements PaymentService{
    @Override
    public String getPort() {
        return "支付服务 fallback";
    }
}

修改controller(在下面添加了一个接口和fallbackHandler blockHandler

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import top.xkuna.springboot.service.PaymentService;

import javax.annotation.Resource;

/**
 * @author Xkuna
 * @date 2020/8/17 20:32.
 */
@RestController
public class OrderController {
    @GetMapping("/fallback/{id}")
    @SentinelResource(value = "fallback", blockHandler = "blockHandler1",fallback = "fallbackHandler",
        exceptionsToIgnore = IllegalArgumentException.class
    )
    public String fallback(@PathVariable("id") Long id){
        if(id == 4){
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if(id > 4){
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }else{
            return "ok-------id: " + id ;
        }
    }
    public String blockHandler1(@PathVariable("id") Long id, BlockException blockException){
        return "---blockHandler" ;
    }

    public String fallbackHandler(@PathVariable Long id){
        return "----fallbackHandler" ;
    }


    //---openfeign

    @Resource
    private PaymentService paymentService ;

    @GetMapping("/getPaymentPort")
    @SentinelResource(value = "getPaymentPort", blockHandler = "blockHandler2",fallback = "fallbackHandle2")
    public String getPaymentPort(){
        return paymentService.getPort() ;
    }

    public String blockHandler2(BlockException blockException){
        return "调用payment---blockHandler" ;
    }

    public String fallbackHandler2(){
        return "调用payment----fallbackHandler" ;
    }

}

注意在yml中开启feign支持sentinel的熔断降级(上面在搭建的时候已经配置了)

image-20200818142651539

此时启动 支付微服务9003 9004

3.4测试

访问 http://localhost:84/getPaymentPort

image-20200818142233397

image-20200818142242381

多刷新几次发现,实现了负载均衡

那么此时我们停掉 9004

多次访问 http://localhost:84/getPaymentPort

image-20200818142344649

发现都是 9003,访问正常

我们再停掉 9003(此时支付微服务全部下线)

image-20200818142444342

说明我们配置openfeign接口的实现类成功 😄

4.修改openfeign调用时限

​ 使用过openfeign的小伙伴都知道在用它调用其他微服务的时候,默认的超时时长是 1s;如何修改这个时长呢?

​ 在hystrix与openfeign整合的时候,需要调用端要开启feign对hystrix的支持,设置调用端hystrix的超时时长,还要设置ribbon的超时时长

​ 在sentinel中,调用者要修改openfeign的默认超时时长,需要两点

  • 开启feign对sentinel的支持
  • 设置ribbon的超时时长

image-20200819084159683

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值