概述
一、Sentinel 描叙
1、Sentinel作用
Sentinel,中文翻译为哨兵,是为微服务提供流量控制、熔断降级的功能,它和Hystrix提供的功能一样,可以有效的解决微服务调用产生的“雪崩”效应,为微服务系统提供了稳定性的解决方案。随着Hytrxi进入了维护期,不再提供新功能,Sentinel是一个不错的替代方案。通常情况,Hystrix采用线程池对服务的调用进行隔离,Sentinel才用了用户线程对接口进行隔离,二者相比,Hystrxi是服务级别的隔离,Sentinel提供了接口级别的隔离,Sentinel隔离级别更加精细,另外Sentinel直接使用用户线程进行限制,相比Hystrix的线程池隔离,减少了线程切换的开销。另外Sentinel的DashBoard提供了在线更改限流规则的配置,也更加的优化。
2、Sentinel 具有以下特征
从官方文档的介绍,Sentinel 具有以下特征:
丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。
3、如何在Spring Cloud中使用Sentinel
Sentinel的使用分为两部分:
sentinel-dashboard:与hystrix-dashboard类似,但是它更为强大一些。除了与hystrix-dashboard一样提供实时监控之外,还提供了流控规则、熔断规则的在线维护等功能。
客户端整合:每个微服务客户端都需要整合sentinel的客户端封装与配置,才能将监控信息上报给dashboard展示以及实时的更改限流或熔断规则等。
4、Sentinel 和 hytrix的区别
二、Sentinel 控制台 Sentinel DashBoard
Sentinel DashBoard
Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能.
1、下载
Sentinel DashBoard下载地址:https://github.com/alibaba/Sentinel/releases
下载 jar 文件即可
2、启动
下载完成后,以以下的命令启动
java -jar sentinel-dashboard-1.6.1.jar
启动端口为8080,启动修改端口添加命令 -Dserver.port=8081
3、访问
访问:http://localhost:8080
默认账号密码:sentinel / sentinel
登录成功展示如下,默认没有任何内容的
其他启动指定:
-Dsentinel.dashboard.auth.username=sentinel: 用于指定控制台的登录用户名为 sentinel;
-Dsentinel.dashboard.auth.password=123456: 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel
-Dserver.servlet.session.timeout=7200: 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
三、springboot 整合 Sentinel
Sentinel 有两种配置方式
1、使用代码+注解配置(看7)
2、使用控制台配置(看6)
3.1、pom.xml 依赖
<!-- sentinel -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
3.2、application.yml
- 在工程的配置文件application.yml文件中配置,需要新增2个配置:
- spring.cloud.sentinel.transport.port: 8719 ,这个端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了1个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。
- spring.cloud.sentinel.transport.dashboard: 8080,这个是Sentinel DashBoard的地址。
## 在工程的配置文件application.yml文件中配置,需要新增2个配置:
## spring.cloud.sentinel.transport.port: 8719 ,这个端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了1个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。
## spring.cloud.sentinel.transport.dashboard: 8080,这个是Sentinel DashBoard的地址。
server:
port: 8090
spring:
application:
name: alibaba-alibaba-sentinel
cloud:
nacos:
discovery:
server-addr: 192.168.177.128:8848
###
sentinel:
transport:
### 当前项目Http Server ip,主要主要是和Sentinel 的DashBoard控制台系统进行通讯
port: 8719
### Sentinel 控制台DashBoard的地址
dashboard: http://localhost:8080
3.4、测试接口1(指定方法,不介意,代码都在一个地方)
关于@SentinelResource注解最主要的两个用法:限流控制和熔断降级的具体使用案例介绍完了。另外,该注解还有一些其他更精细化的配置,比如忽略某些异常的配置、默认降级函数等等
package com.example.alibabasentinel.service;
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.RestController;
/**
* TODO 服务熔断/限流/降级(指定方法)
* @author 王松
* @mail 1720696548@qq.com
* @date 2020/1/22 0022 20:35
*/
@RestController
public class TestService1Impl {
/**
* TODO 测试方法(当前类处理-服务降级)
* getName :限流名称,控制台添加一定要选择该值,勿添加为 /getName 默认名,否则exceptionHandler 参数无效
* exceptionHandler : 服务限流降级后执行的方法
*/
@GetMapping("/getName")
@SentinelResource(value = "getName", blockHandler = "exceptionHandler")
public String getName() {
return "wangsong";
}
/**
* TODO 处理限流与阻塞(服务降级返回友好提示),方法名对应 blockHandler的参数,服务限流降级后执行的方法
*
*/
public String exceptionHandler(BlockException ex) {
System.out.println("====" + ex);
return "当前访问人数过多,请稍后再试";
}
}
参考返回值:
1、当前访问人数过多,请稍后再试
2、正在排队中…
3.5、测试接口2(指定Handler类的方法)
添加测试方法
package com.example.alibabasentinel.service;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.example.alibabasentinel.handler.MyBlockHandlerClass;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* TODO 服务熔断/限流/降级(指定Handler类的方法)
* @author 王松
* @mail 1720696548@qq.com
* @date 2020/1/22 0022 20:40
*/
@RestController
public class TestService2Impl {
/**
* TODO 测试方法(指定Handler类处理-服务降级),blockHandlerClass = MyBlockHandlerClass.class
* getName :限流名称,控制台添加一定要选择该值,勿添加为 /getName2 默认名,否则exceptionHandler 参数无效
* blockHandlerClass :服务限流/异常等指定类执行降级方法
* blockHandler: 服务限流执行的降级方法
* fallback : 服务异常执行的降级方法
*/
@GetMapping("/getName2")
@SentinelResource(value = "getName2", blockHandlerClass = MyBlockHandlerClass.class, blockHandler = "blockHandlerFunc", fallback = "fallbackFunc")
public String getName2(String a) {
return "wangsong2";
}
}
添加 MyBlockHandlerClass 类 处理服务熔断降级
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyBlockHandlerClass {
// 处理限流与阻塞(服务降级返回友好提示)
public static String blockHandlerFunc(String a, BlockException e){
log.warn("限流了==="+a,e);
return "当前访问人数过多,请稍后再试";
}
// 服务异常(降级处理)
public static String fallbackFunc(String a){
log.warn("异常==="+a);
return "";
}
}
3.6、控制台添加流控并测试
qbs:阈值 = 每秒能调用该接口多少次
线程数:阈值 = 请求最多有多少个线程池来处理(默认1)
项目启动后等一下下,控制台在会出现当前服务信息
先访问接口 /getName 几次,控制台才会出现该接口信息,
3.6.1、添加流控(接口到达阈值自动熔断)
getName = @SentinelResource注解的value 值,如果流控添加到 /getName ,将无法使用服务降级功能
添加流控qbs,设置阈值为2
qbs:阈值 = 每秒能调用该接口多少次
线程数:阈值 = 请求最多有多少个线程池来处理(默认1)
3.6.2、访问接口(服务降级)
正常访问接口返回响应数据,如当前:wangsong
到达阈值上限 ,返回:Blocked by Sentinel (flow limiting)
设置 blockHandle, 到达阈值上限,返回如下:
如:@SentinelResource(value=“getName”, blockHandler = “exceptionHandler”),
四、@SentinelResource 注解说明
注解key | 支持版本 | 注解value 说明 |
---|---|---|
value | 资源名称,必需项(不能为空) | |
entryType | entry 类型,可选项(默认为 EntryType.OUT) | |
blockHandler / blockHandlerClass | blockHandler对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析 | |
fallback | fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求: 返回值类型必须与原函数返回值类型一致; 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。 | |
defaultFallback | since 1.6.0 | :默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:返回值类型必须与原函数返回值类型一致; 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。 |
defaultFallback | 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。 | |
exceptionsToIgnore | since 1.6.0 | 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。 |
五、java 代码手动添加流控配置
pom 依赖,yml配置,看 3.1, 3.2
定义限流的接口添加注解看 3.4, 3.5
测试看 3.6
// 流控接口
private static final String GETORDER_KEY = "getOrder";
// 调用接口方式添加流控
@RequestMapping("/initFlowQpsRule")
public String initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(GETORDER_KEY);
// 设置QPS控制在2以内
rule1.setCount(1);
// 限流规则QPS
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
// 添加流控集
FlowRuleManager.loadRules(rules);
return "....限流配置初始化成功..";
}
六、Sentinel 数据持久化
1、pom.xml 依赖添加sentinel-datasource-nacos
<!-- sentinel ,可需启动dashboard 查看配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
<!-- sentinel 数据持久化到nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.5.2</version>
</dependency>
2、nacos 添加 sentinel 配置
创建服务对应的 sentinel 配置文件,使用 json
选择json,添加数据
[
{
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
- resource:资源名,即限流规则的作用对象
- limitApp:流控针对的调用来源,若为 default 则不区分调用来源
- grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
- count:限流阈值
- strategy:调用关系限流策略
- controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
- clusterMode:是否为集群模式
这里我们只做简单的配置解释,以便于理解这里的配置作用。实际上这里还有非常多可配置选项和规则,更复杂的配置后面我们单独开一篇来深入学习。
3、application.yml 完整配置
# 在工程的配置文件application.yml文件中配置,需要新增2个配置:
# spring.cloud.sentinel.transport.port: 8719 ,这个端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了1个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。
# spring.cloud.sentinel.transport.dashboard: 8080,这个是Sentinel DashBoard的地址。
server:
port: 8090
spring:
application:
name: spring-cloud-alibaba-sentinel
cloud:
### nacos 注册中心
nacos:
discovery:
server-addr: 192.168.177.132:8848
sentinel:
### 和 Sentinel控制台DashBoard通讯,|| port:当前项目Http Server ip地址,|| dashboard:Sentinel 控制台DashBoard的地址
transport:
port: 8719
dashboard: http://localhost:8080
### 配置数据源,支持file本地,nacos,zk,阿波罗,配置数据库0,读取 nacos 配置数据
datasource:
ds0:
nacos:
server-addr: 192.168.177.132:8848
dataId: spring-cloud-alibaba-sentinel.json
groupId: DEFAULT_GROUP
rule-type: flow
### 文件类型
data-type: json
sentinel 部分
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: http://localhost:8080
datasource:
ds0:
nacos:
server-addr: 192.168.177.132:8848
dataId: spring-cloud-alibaba-sentinel.json
groupId: DEFAULT_GROUP
rule-type: flow
data-type: json
4、查看是否配置成功
启动项目发现启动日志: [Sentinel Starter] DataSource ds0-sentinel-nacos-datasource load 1 FlowRule
表示配置成功了
进入Sentinel 控制台–> 流控规则,发现已经存在配置规则了,配置成功
- 1、如是重新启动项目, 访问任意接口在等待几秒刷新
- 2、配置了nacos 尽量从来nacos 添加和修改规则,Sentinel 控制台修改的下次重新启动项目将失效
七、gateway 整合 Sentinel 实现服务限流
1、添加sentinel 限流核心配置
package com.gateway.sentinel;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;
import java.util.Collections;
import java.util.List;
/**
* TODO sentinel 限流核心配置
* @author ws
* @mail 1720696548@qq.com
* @date 2020/2/17 0017 14:08
*/
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
}
2、添加sentinel 限流规则
此配置可以配置到nacos,动态配置限流规则
package com.gateway.sentinel;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
/**
* TODO 限流规则配置
*
* @author ws
* @mail 1720696548@qq.com
* @date 2020/2/17 0017 14:09
*/
@Slf4j
@Component
public class SentinelApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
initGatewayRules();
}
/**
* 配置限流规则
*/
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("test")
// 限流阈值
.setCount(1)
// 统计时间窗口,单位是秒,默认是 1 秒
.setIntervalSec(1)
);
GatewayRuleManager.loadRules(rules);
}
}
3、配置自定义返回信息(如果配置了全局异常看四)
package com.gateway.sentinel;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* TODO 限流错误返回信息
* @author ws
* @mail 1720696548@qq.com
* @date 2020/2/17 0017 14:13
*/
public class JsonSentinelGatewayBlockExceptionHandler implements WebExceptionHandler {
public JsonSentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
}
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
ServerHttpResponse serverHttpResponse = exchange.getResponse();
serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
byte[] datas = "{"code":403,"msg":"API接口被限流"}".getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);
return serverHttpResponse.writeWith(Mono.just(buffer));
}
}
4、全局异常返回自定义信息
全局异常配置暂不做说明
本文参考文章1:https://blog.csdn.net/u013184307/article/details/95973022
本文参考文章2:https://blog.csdn.net/a772304419/article/details/99689562
数据持久化参考:http://blog.didispace.com/spring-cloud-alibaba-sentinel-2-1/
创作不易感谢大家的观看!
最后
以上就是魔幻蜻蜓为你收集整理的SpringCloudAlibaba 六、Sentinel 服务保护 ( 服务降级/ 熔断/ 数据持久化 / gateway 整合 Sentinel )的全部内容,希望文章能够帮你解决SpringCloudAlibaba 六、Sentinel 服务保护 ( 服务降级/ 熔断/ 数据持久化 / gateway 整合 Sentinel )所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复