欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

程序员文章站 2022-06-13 22:28:43
...

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

官网:https://github.com/alibaba/Sentinel/wiki
下载地址:https://github.com/alibaba/Sentinel/releases

下载完成后,启动sentinel。在你放sentinel-dashboard.jar的文件处打开cmd,输入java -jar sentinel-dashboard.jar,启动完成后。访问localhost:8080,出现以下页面证明成功。账号密码都是sentinel/sentinel
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
现在我们改造一下payment9001,首先我们在pom.xml加上Sentinel的坐标

<!--   sentinel     -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

改造application.yml,改造后的yml文件如下:

server:
  port: 9001
spring:
  application:
    name: nacos-payment-provider   #本服务的名称
  cloud:                           #注册到nacos
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
management:
  endpoints:
    web:
      exposure:
        include: "*"

创建SentinelController

@RestController
public class SentinelController {

    @GetMapping(value = "/SentinelA")
    public String SentinelA(){
        return "SentinelA";
    }

    @GetMapping(value = "/SentinelB/{id}")
    public String SentinelB(@PathVariable Integer id){
        return "SentinelB---"+id;
    }
}

启动9001。

现在我们登录上sentinel,登录后查看首页

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
此时发现并没有我们刚才启动的服务。现在我们访问localhost:9001/ SentinelA,访问成功后,再次查看Sentinel控制台。

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
我们会发现出现了我们启动的服务,可以看出来Sentinel是懒加载。

接下来点击服务,查看菜单
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
当我们使用QPS为阈值类型时,并设置阈值为1,定义资源,其他默认,则表示一秒内,只需要通过1次请求,其他的均失败。其他的选项我就不一个一个实例了,有兴趣的可以查查资料。

刷新快一点,观察情况
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

Sentinel会帮你给一个友好的错误提示,但是也可以自己定义处理方法。

改造SentinelController

@RestController
public class SentinelController {

    @GetMapping(value = "/SentinelA")
    @SentinelResource(value = "SentinelA",blockHandler = "aaa")
    public String SentinelA(){
        return "SentinelA";
    }

    public String aaa(BlockException e){
        return "被限流了!o(╥﹏╥)o";
    }

    @GetMapping(value = "/SentinelB/{id}")
    public String SentinelB(@PathVariable Integer id){
        return "SentinelB---"+id;
    }
}

重启项目,重新设置限流,快速刷新,观察情况。
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

这里注意一下,自定义的方法要跟原接口的返回类型和请求参数一模一样(参数需要多一个BlockException)。

这里还可以写一个处理类,把各个接口的处理方法写进去,创建handler包ControllerHandler类

/**
 * 注意都是静态方法
 */
public class ControllerHandler {

    public static String SentinelAhandler(BlockException e){
        return "SentinelA被限流!"+e.getMessage();
    }

    public static String SentinelBhandler(Integer id,BlockException e){
        return "SentinelB被限流!"+e.getMessage();
    }
}

注意都是静态方法。SentinelController改造如下

@RestController
public class SentinelController {

    @GetMapping(value = "/SentinelA")
    @SentinelResource(value = "SentinelA",blockHandlerClass = ControllerHandler.class,blockHandler = "SentinelAhandler")
    public String SentinelA(){
        return "SentinelA";
    }

//    public String aaa(BlockException e){
//        return "被限流了!o(╥﹏╥)o";
//    }

    @GetMapping(value = "/SentinelB/{id}")
    @SentinelResource(value = "SentinelB",blockHandlerClass = ControllerHandler.class,blockHandler = "SentinelBhandler")
    public String SentinelB(@PathVariable Integer id){
        return "SentinelB---"+id;
    }
}

启动9001,访问A和B

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

写到这里会不会有人发现,每次重启服务之后,我们之前配置的规则都不见了。这样对我们来说很不方便,关于sentinel持久化有多种方法,详情见https://www.jianshu.com/p/609961eb6a6e。下面来说一下用nacos的方法

首先pom.xml添加

<!--sentinel持久化-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

application.yml

server:
  port: 9001
spring:
  application:
    name: nacos-payment-provider   #本服务的名称
  cloud:                           #注册到nacos
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848   #nacos地址
            dataID: nacos-payment-provider
            groupId: DEFAULT_GROUP
            data-type: json      #注意是json类型
            rule-type: flow
management:
  endpoints:
    web:
      exposure:
        include: "*"

然后打开nacos
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
点击发布。其中内容规则如下

[
    {
        "resource": "SentinelA",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]
resource:资源名
limitApp:流控针对的调用来源,default不区分来源
grade:限流阈值类型(0-根据并发数量来限流 1-根据QPS来进行流量控制)
count:限流阈值
strategy:调用关系限流策略
controlBehavior:流量控制效果(直接拒绝、WarmUP、匀速排队)
clusterMode:是否集群模式

重启9001,访问一下SentinelA,连续点击会发现已经有流控规则了。也可以看Sentinel是否已经有流控规则了。

defaultFallback

现在我们修改一下SentinelA里面的代码

@GetMapping(value = "/SentinelA")
@SentinelResource(value = "SentinelA",blockHandlerClass = ControllerHandler.class,blockHandler = "SentinelAhandler" )
public String SentinelA(){
    int i = 10/0;
    return "SentinelA";
}

这个运行肯定会报错,看一下是不是进入我们自定义的方法。
使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

直接报错,并没有进入我们自定义的方法。这里注意一下blockHandler方法只能用例流控规则,代码自身出问题是处理不了的。要处理代码自身问题的话需要用defaultFallback,看一下示例

@GetMapping(value = "/SentinelA")
@SentinelResource(value = "SentinelA",blockHandlerClass = ControllerHandler.class,blockHandler = "SentinelAhandler",defaultFallback ="bbb" )
public String SentinelA(){
    int i = 10/0;
    return "SentinelA";
}

public String bbb(){
    return "系统出错了!";
}

再次访问:使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel
这个也有类似blockHandler自定义一个类的写法,这里不做演示了,两个类似。