举个栗子,淘宝在双十一的时候会出现很多的访问请求,这无疑会让服务器流量暴涨,轻则导致网页无法显示、重则服务器宕机,为了让我们的服务正常运转,我们可以在系统负载过高时,采用sentinel,使用限流、降级、熔断三种措施来保护系统。流量控制的中间件sentinel就此出现
起到一个监视的作用,观察者模式
sentinel是阿里开源的一套用于服务容错的综合性解决方案,他是以流量为切入点,从流量控制、熔断、系统负载等多个维度来保护服务的稳定性。
Sentinel的核心主要分为两个:
核心库:JAVA客户端
控制台:基于sringBoot开发的项目,就是个项目,打完包直接用
下载JAR ——在存放jar的对应目录下运行cmd并且启动运行sentinel ——
java -Dserver.port=8180 -Dcsp.sentinel.dashboard.server=localhost:8180 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
记得再idea配置时,要去指定JDK的位置,从而调用java方法
workspace记得要去指定sentinel.jar的文件夹
(与nacos一样,最好配置到idea中,更便捷)
默认用户名与密码都是sentinel
服务端口号(服务) - 8719(通讯端口,会自增) -8180(sentinel)
sentinel三种限流效果:
1.快速失败 2.预热 3.排队
客户端发起请求,之后就要通过interceptor进行拦截,sentinel用的是AbstractSentinellnterceptor(实现了HandlerInterceptor)进行拦截的,拦截后执行perHandle方法,在其进行校验(其在sentinel中拿流控规则),请求次数与阈值符合时放行,否则就会抛出异常FlowException,之后再进行BlockExceptionHandler进行异常处理
sentinel中这个AbstractSentinellnterceptor拦截器离不开sentinel的依赖,阿里写的
拦截器拦截的是controller,restController
举个栗子:生活中,拦截器相当于坐地铁要看健康码,绿码放行,红码抓起来统一处理
举个栗子,我们的数据库连接池与线程池,nginx的瞬时并发等在使用的时候都会有一个限定的值,设定流量的上限这就是个限流操作。
限流的目的是为了防止恶意请求流量、恶意攻击、或者防止流量超过系统峰值。
首先老步骤,先去把pom文件把依赖导入
spring-cloud-starter-alibaba-sentinel
然后打开提(就是要进行限流操作的服务)供方resource中的bootstrap.yml(与application.yml的区别是啥?),对sentinel进行配置,sentinel与nacos平级,在spring.cloud下
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8180 #也就是要指定sentinel的控制台地址
配置完之后,通过浏览器,进入localhost:8180 进入sentinel的控制台地址,对交给到sentinel的服务进行管理
还有个eager(立刻):true 默认为false ,被sentinel监控的服务不被请求也会显示在控制台
开始限流:
在簇点链路中,找到对应的服务,点击流控
Sentinel的限流模式:
qps是个啥:qps每秒请求数,达到设的单机阈值就会限流 (主要倾向使用)
线程数:就是当发起这个请求的线程达到单机阈值的时候就会限流 (不准确)
成功创建规则后,在流控规则就可以找到对应请求服务的限流规则
知识点:sentinel是阿里出的,相同的还有hystrix(微服务产品),怎么进行限流的?sentinel依赖里面有拦截器,对请求进行拦截,为的是监控,也就是看单位时间的请求是否超出了阈值。
限流算法:计数器,令牌桶,漏斗算法,滑动窗口算法(默认的)
令牌桶算法:设定桶里面有100个令牌,当有请求的时候,经过桶,之后就拿一个令牌出去,请求走完,把令牌扔回桶里,循环使用,澡堂子手牌发完了,就得等一会,洗完澡还得把手牌放回手牌桶
滑动窗口算法:把一段时间平分成几段,有一个指针,每有一个请求,指针都向一个方向移动一段,当无法再移动的时候,就会被限流,分成几段就是由你设定的阈值进行划分
流控模式三种
直接:就是对资源链路本身进行限流,sentinel默认的就是直接+快速失败
关联:把A资源关联给B资源,当B资源的访问达到了设计好的单机阈值时就会限制A资源
举个栗子:查订单与下订单 下订单是我们的主要盈利业务,很重要,当遇到大型促销活动,虽说查订单也是一个业务,相比较下订单业务等级,等级没有他高,就可以将这两个业务进行关联,限流下来的性能腾给下订单业务用(限流的根本原因是硬件跟不上,若硬件特别猛的时候,不需要限流)
链路:链路可以理解为一个请求路径例如 /provider/sentinel03
举个栗子:当A链路与B链路都要去访问同一个资源的时候,我们设定放行A链路,而B链路达到我们设定的限制值就进行限流操作(报500) 这样只需要把资源的流控模式设为链路,把B的链路填到入口资源即可
设置链路模式的时候,要在被访问资源上添加@SentinelResource注解
注意:若是sentinel1.7.2以后的版本会默认把服务都聚合在sentinel_spring_web_context入口下,要手动在yml文件进行设置
sentinel:
web-context-unify: false #其不会有聚拢效果了,单独入口
@ SentinelResource 此方法是一个sentinel资源方法,这个方法同时也是切入点方法,执行被他注释的方法需要先执行一些切入点方法(也就是限流规则,其切面类为 SentinelResourceAspect 里面有限流方法)
@ SentinelResource(
value =【链路节点名,就是在sentinel看到的节点名字】,
blockHandlerClass =【异常处理类】,
blockHandler = 【异常处理方法】)
异常处理类要交给spring容器进行管理,异常处理方法对应的是异常处理类的方法名,
注意:
异常处理方法的
方法修饰符为public
返回值类型与@SentinelResource标识的资源的返回值要相同,参数列表要匹配要为BlockExcepcation类型(例如热点要穿ID,先把ID参数放在前面,最后放BlockExcepation参数)
方法必须为static
1.写一个类例如TimeInterceptor,该类要继承HandlerInterceptor
(拦截器的接口祖宗,里面有三个默认方法)
2.根据你要实现的业务思路,去选择实现的方法 ,完善对应方法即可
ps:preHandle方法返回true就是放行,返回false就是拦截,抛异常也可以拦截,抛出异常我们还可以进行try-catch操作
3.写完拦截器这个类之后要去进行注册拦截器,写一个配置类交给Spring容器进行管理(加一个@Configuration),这个配置类要去实现WebMvcConfigurer,拦截器都放在一个容器当中,通过实现WebMvcConfigurer接口,去实现其中的addInterceptors方法,参数为InterceptorRegistry registry,这个对象是用来负责注册拦截器的,执行该方法会把你写好的拦截器放到对应的容器中,容器的拦截器们是有顺序的。
4.当拦截时先执行的拦截器,放行返回后会后执行
啥是降级:就是对调用链路中不稳定的资源进行熔断降级,也是保障高可用的重要措施
啥是熔断:弃卒保帅
①资源名:对那一个资源进行添加降级规则
②熔断策略:设置熔断的策略 三种
慢调用: 就是服务调用的过慢,就会对其进行降级熔断
异常比例: 服务出现的异常占单位时间内的请求比例
异常数:调用服务出现异常的总数
③ 最大RT:就是判断你的服务响应时间,要在你设定的值以内不会触发,以外会触发
④ 比例阈值:抛出异常的百分比,超过你设置的比例就要熔断
⑤ 熔断时长:熔断持续的时长,熔断后的多少秒内该服务不能再被调用
⑥ 最小请求数: 发起的最小请求数,也就是当你的请求数小于这个值的时候,就算超过了比例阈值,也不会熔断
⑦ 统计时长:也就是1秒钟的请求要大于最小请求数
当我们想让限流或者熔断后显示我们自定义的信息时,我们就可以自己定义一个BlockExceptionHandler异常处理类,首先这个类要去实现BlockExceptionHandler这个接口,并且要交给spring 容器进行管理其生命周期,重写其handle方法,具体实现如下:(一般这个处理类只有一个)
注意: 里面的FlowException 是限流时抛出的异常,DegradeExpection是降级熔断时抛出的异常
知识点:当我们自己创建了sentinel异常处理类,为什么就不去使用默认的?因为在默认的异常处理类上有
@ConditionalOnMissingBean 意义是 当容器中已经存在标识的bean那么就不会再去新建bean,所以默认处理类在我们写完处理类就失效了。
@Primary spring创建bean的时候优先创建这个注解标识的
举个栗子:
当有一个惊天大瓜在微博发布出来,网名都想去查看这篇博文,造成服务器收到大量的并发请求,当服务器扛不住的时候就会宕机,那么这篇博文(资源),也就是咱们说的热点资源 ,我们要对其进行限制
例如有个无聊的人,一秒请求我们的网站20w次,那这个用户就是我们的热点用户,要对他进行处理,给她限流
模拟热点资源进行测试:步骤如下
1.先新建立一个虚拟的热点资源,因为要根据ID进行热点规则的设计,所以传一个id
2.在Controller层中的方法中去调用资源服务
3.在sentinel进行热点规则的限制,找到资源的服务
4.新增热点规则
5.建立完热点规则后可以进行高级设置,让粒度更细,例如只把id=100的进行限流,在左边栏的热点规则中继续编辑
知识点:spring 默认AOP的都是CGlib代理,可以在yml文件中进行设置
spring.aop.proxy-target-class=true(默认的CGBLIB无论是不是接口都用他,False为JDK)CGlib实际上是产生一个子类对象
啥是系统规则:就是全局性的限流规则,不用去设置某个链路,而是全局都有效,相当于去监控系统的信息与硬件使用率
阈值类型:
load:只在UNIX与LUNIX系统生效,负载
RT:响应时间
线程数:使用了多少线程
入口qps:每秒请求数
CPU使用率:本机CPU的使用率
啥是授权规则:首先授权规则也一种限流规则,通过白名单与黑名单进行对请求的放行与限流,
举个栗子:微信拉黑
授权规则是需要自己定义的,因此我们要求写一个RequestOriginParser接口的实现类, 法parseOrigin().这个方法返回的值会进行授权规则的应用
方法里的代码要根据业务决定,我们可以基于请求的对象获取到请求行,请求头,请求体,解析后返回的数据会与sentinel定义的授权规则定义的值进行一个比较,然后基于黑白名单进行限制
举个例子:业务实现,1.有token就可以访问资源,没有的不能访问 2.指定将某个IP限流