sentinel笔记学习—springcloudalibaba

1.sentinel简介

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。

2.sentinel的安装和运行

1.下载sentinel.jar包

image.png

2.启动并运行

使用java -jar命令运行jar包,启动:


image.png

sentinel资源保护规则

sentinel支持多种保护规则:流量控制规则,熔断降级规则,系统保护规则,来源访问控制规则,热点参数规则。

sentinel流量控制统计有两种类型:

  • 并发线程数:指当前请求的上下文线程数量,如果超出阈值,新的请求就会被拒绝
  • QPS:表示每秒查询的数量,表示一台服务器每秒能相应的次数。

QPS流控行为

  • 直接拒绝
  • Warm Up ,冷启动
  • 匀速排队
image.png

直接拒绝

@GetMapping("/testA")
    public String testA() {
      System.out.println(Thread.currentThread().getName()+"\t线程"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
        return "----A";
    }

服务器请求testA,配置流控规则,阈值是1秒,当一秒查询数量超过每秒一次以后就会报错


image.png
image.png

Warm Up

它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的n/3(冷加载因子默认为3),然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。


image.png

刚启动服务时,最开始的阈值时10/3=3,然后再5秒内请求慢慢达到最大阈值10

匀速排队

匀速排队的方式会严格控制请求通过的时间间隔,让请求以匀速的速度通过。


image.png

一秒中只允许一个请求通过,超时时间设置为20秒

这里使用postman做测试

这里设置有10个线程,每500毫秒通过一次,运行查看控制台的输出。


image.png

可以看到每秒只允许通过一个进程。


image.png

QPS的流控模式

  • 直接
  • 关联
  • 链路

直接:当每秒超过一个进程,就会显示错误信息

image.png

关联:服务间的互相关联,当关联资源被请求量过高,则主资源被限制访问。

image.png

使用postman做测试,每隔300毫秒发送一次请求,/testA就会拒绝访问,等过了20秒以后才可以访问。


image.png

sentinel服务降级常见方案

  • 平均相应时间:比如1s内持续进入5个请求,对应时刻的平均响应时间均超过阈值,那么接下来在一个时间窗口期内,对这个方法的访问都会自动返回。
  • 异常比例:当某个方法每秒调用所获得的异常总数的比例超过设定的时间阈值,该资源会自动进入降级状态。
  • 异常数量:和异常比例相似,当某个方法在指定时间窗口内获得的异常数量超过阈值时会触发熔断。

平均响应时间

设置1秒内发送10个请求,我们希望200ms完成此次请求,如果超过200ms没有完成处理完,在未来的1s的时间窗口,断路器打开,微服务不可用。


image.png
  @GetMapping("/testB")
    public String testB() throws InterruptedException {
        //System.out.println(Thread.currentThread().getName()+"\t线程"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
        TimeUnit.SECONDS.sleep(1);
        return "----B";
    }

异常比例

当异常的比例超过20%,微服务就不可用。


image.png

异常数量

在请求窗口期内,如果异常数超过5个,服务就会报错


image.png
   @GetMapping("/testB")
    public String testB() throws InterruptedException {
        //System.out.println(Thread.currentThread().getName()+"\t线程"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
        //TimeUnit.SECONDS.sleep(1);
        int a=10/0;
        return "----B";
    }

sentinel服务熔断

导入依赖

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

application.yml配置

server:
  port: 84

spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719

server-url:
  nacos-user-service: http://nacos-payment-provider

#激活Sentinel对Feign的依赖
feign:
  sentinel:
    enabled: true
 @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1",required = false)String p1,
                             @RequestParam(value = "p2",required = false)String p2){
        return "-----testHotKey";
    }

    public String deal_testHotKey(String p1, String p2, BlockException exception){
        return "-----deal_testHotKey";
    }

这里先创建一个微服务9003模拟数据库存储信息,当访问id不存在的时候(没有配置fallback和blockHandler时),页面报出异常。

blockHandler:负责控制台配置违规
fallback:负责业务异常

9003服务

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

    public static HashMap<Long, Payment> hashMap=new HashMap<>();
    static {
        hashMap.put(1L,new Payment(1L,"aaa"));
        hashMap.put(2L,new Payment(2L,"bbb"));
        hashMap.put(3L,new Payment(3L,"ccc"));
    }

    @GetMapping("/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;
    }

84服务

@Value("${server-url.nacos-user-service}")
    private String serverURL;
    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
   //@SentinelResource(value = "fallback1")//没有配置
 //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
   @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责控制台配置违规
    //@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
                                              //exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult<Payment> fallback(@PathVariable Long id)  {
        CommonResult<Payment> result=restTemplate.getForObject(serverURL+"/paymentSQL/"+id,CommonResult.class,id);
        if(id==4){
            throw new IllegalArgumentException("非法参数异常");
        }else if(result.getData()==null){
            throw new 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);
    }

    public CommonResult blockHandler(@PathVariable Long id, BlockException e){
        Payment payment=new Payment(id,"null");
        return new CommonResult(445,"限流blockHandler异常,exception内容"+e.getMessage(),payment);
    }

image.png

在配置fallback参数后

 @SentinelResource(value = "fallback",fallback = "handlerFallback") 
image.png

只配置blockHandler参数

 @SentinelResource(value = "fallback",blockHandler = "blockHandler")

没有处理blockHandler方法,因为blockHandler不负责业务异常,当sentinel控制台配置服务出现异常才会调用这个方法。


image.png

我们配置一个降级规则


image.png

当在浏览器上输入请求,第一次会有错误,等异常数超过2个,就会调用异常方法。
image.png

exceptionsToIgnore参数,忽略此异常

@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
                                              exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult<Payment> fallback(@PathVariable Long id)  {
        CommonResult<Payment> result=restTemplate.getForObject(serverURL+"/paymentSQL/"+id,CommonResult.class,id);
        if(id==4){
            throw new IllegalArgumentException("非法参数异常");
        }else if(result.getData()==null){
            throw new 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);
    }

当配置此参数后,当出现IllegalArgumentException异常后,不会调用handlerFallback方法。

使用OpenFeign调用远程服务

在接口上配置value参数指提供微服务名称,这里值9003微服务名称,fallback参数表示此微服务出错后调用的方法。

//    OpenFeign
    @Resource
    private PaymentService paymentService;

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

service方法

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {
    @GetMapping("/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id")Long id);

}
@Component
public class PaymentFallbackService implements PaymentService {
    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(444,"服务降级返回--payment service",new Payment(id,"null"));
    }
}

此时如果关闭9003服务,再发送请求就会调用PaymentFallbackService里面的 paymentSQL方法。

image.png

总结

之前我以为服务降级和熔断只能在消费微服务端,或者在提供微服务端,但其实消费端与服务端是相互的,就比如使用openfeign调用远程微服务9003,此时84端是消费端,9003是提供方,但是当其他微服务请求84微服务的时候,这时候84微服务就是提供方,所有我们在84端配置的服务降级和服务熔断,在9003微服务中的方法也能够实现服务降级和熔断。
在9003服务端controller里面的 paymentSQL添加 @SentinelResource(value = "9003payment")注解,在浏览器上发送http://localhost:84/consumer/paymentSQL/1请求,可以看到sentinel控制台有此服务,表示当前方法也能够配置降级和熔断。

以下内容均是自己学习总结,如有不完善请指正,谢谢。

image.png
@GetMapping("/paymentSQL/{id}")
    @SentinelResource(value = "9003payment")
    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;
    }
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349