分布式系统的流量防卫兵:随着微服务的普及,服务调用的稳定性变得越来越重要。Sentinel以“流量”为切入点,在流量控制、断路、负载保护等多个领域开展工作,保障服务可靠性。
分布式系统面临着这样的问题,有时候一个请求会调用多个微服务,服务之间存在着复杂的依赖关系,假设A调用B和C,B和C又调用其他的微服务,这就是所谓的扇出。
如果扇出的某个链路上某个微服务调用的响应时间过程或者不可用,微服务A的调用就用占用越来越多的系统资源,从而引起系统崩溃,就叫做是服务雪崩。
sentinel通过熔断降级来来实现断路器:
向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法出的异常,这样就保证了服务调用方的不会被长时间、不必要的占用,从而避免了服务雪崩。
下载地址
我下载的是1.8.2的版本
去到下载的文件夹中,执行命令
注意要有jdk环境!
java -jar sentinel-dashboard-1.8.2.jar
然后,访问网站localhost:8080
用户名和密码都是sentinel,登录后如图所示:
至此,sentinel安装完毕。
由于之前学习了Nacos,所以这边将Nacos和Sentinel一起使用。
在之前的父项目里新建一个子项目,名为cloudalibaba-sentinel-service,具体参考前面的笔记Spring cloud alibaba ——Nacos(一)
需要添加的依赖如下:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
配置文件application.yml如下:
server:
port: 8401
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
# sentinel控制台地址
dashboard: localhost:8080
# sentinel运行端口,默认为8719,如果被占用会一直+1,直至找到未被占用的端口
port: 8719
application:
name: sentinel-service
# 所有的端口暴露给微服务
management:
endpoints:
web:
exposure:
include: '*'
启动类记得需要添加@EnableDiscoveryClient注解。
控制器层写两侧测试接口
package com.cloud.cloudalibabasentinelservice.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("flow")
public class FLowLimitController {
@GetMapping("testA")
public String testA(){
return "------testA";
}
@GetMapping("testB")
public String testB(){
return "-----testB";
}
}
服务启动后,并不能在sentinel控制台检测到,原因是Sentinel本身采用的是懒加载机制,所以我们需要首先访问服务对应的接口,Sentinel才能工作。
访问接口:localhost:8401/flow/testA和localhost:8401/flow/testB
进入操作太后,发现sentinel开始工作了:
前文有介绍过,sentinel的作用就是可以控制服务被访问的流量,进入控制台–>簇点链路–>+流控–>新增流控规则
其中,阈值类型对应的QPS和并发线程数,代表了两种不同的限流规则,具体区别如下:当单机阈值设置为2时:
根据定义路径来确定流控对象,例如定义的流控路径是:/flow/testA,那么针对所有此路径的请求做流量控制
例如A接口关联到B接口,当B接口的流量达到阈值后,A接口会被限流,但是B接口自身不会被限流,可以一直访问。
测试
使用postman向接口B发起访问,访问的频率达到阈值
此时访问A接口是,出现流控效果
注意:
关联这种流控模式针对的是你所关联的接口,例如,将下单接口关联到支付接口,当支付接口达到流量阈值时,支付接口本身并不会被约束,约束的是下单接口。这种“别人流量超了,但是我来买单”的模式,才是关联模式。
从某个接口过来的资源达到限流条件时,开启限流。来源是上级的微服务,链路是对接口层的控制,特点是粒度更细,控制范围更小。
** 使用**
Service层代码:
package com.cloud.cloudalibabasentinelservice.service;
import org.springframework.stereotype.Service;
@Service
public class FlowService {
@SentinelResource("common")
public String flowMethod(){
return "flow method";
}
}
Controller层代码:
package com.cloud.cloudalibabasentinelservice.controller;
import com.cloud.cloudalibabasentinelservice.service.FlowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("flow")
public class FLowLimitController {
@Autowired
private FlowService flowService;
@GetMapping("testA")
public String testA(){
return "------testA" + flowService.flowMethod();
}
@GetMapping("testB")
public String testB(){
return "-----testB" + flowService.flowMethod() ;
}
}
添加yml配置:
spring:
sentinel:
# 使用链路时必须打开此开关
web-context-unify: false
在控制台添加相关的流控设置:
注意:
资源名需要和@SentinelResource(“common”)中的值一样。
此时访问flow/testB时,会出现流控效果。
当流量达到阈值时,直接失败,抛出异常。
预热针对的是这样的场景,某个接口的流量长期处于低水平线,流量瞬间暴增,达到极高的水平线,这样的暴增可能会把服务压垮,所以,Warm Up的效果可以让流量平稳地缓慢增加,给冷系统一个预热时间,避免冷系统被压垮。
例如秒杀系统,瞬间爆炸型的流量访问到服务。
预热公式:阈值/coldFactor(默认值为3),第一次访问时,流量不能超过这个值,后面经过预热时长,慢慢提升到阈值。
让请求以均匀的速度通过,主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求(削峰填谷)。
使用排队等待时,阈值类型必须选择QPS,否则无效。