1.安装
1.1 docker安装
docker run --name sentinel -d -p 8858:8858 -p 8719:8719 -d bladex/sentinel-dashboard
1.2 jar 安装
java -jar sentinel-dashboard-1.8.4.jar
1.3 登录
账号和密码都是sentinel
2.集成
Sentinel控制台修改规则:仅存在于服务的内存中,不会修改Nacos中配置值,重启后恢复原来的值 Nacos控制台修改规则:Nacos持久化规则,服务的内存也同步更新
2.1 pom 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.lys.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-sentinel-service</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<!--<version>2.2.1.RELEASE</version>-->
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- SpringCloud alibaba sentinel-datasource-nacos,后续做持久化用到 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
</project>
2.2 bootstrap.yml
规则没有持久化,需要自行配置
server:
port: 8002
nacos:
config:
bootstrap:
log:
enable: true
spring:
application:
name: nacos-sentinel-service
cloud:
nacos:
discovery:
server-addr: 10.6.8.238:8848 #Nacos作为服务注册中心地址
config:
server-addr: 10.6.8.238:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: DEFAULT_GROUP #指定在哪个group里
namespace:
# {spring.application.name}-{spring.profiles.active}.{spring.cloud.nacos.config.file-extension}
# 实际访问的配置nacos-payment-provider.yaml
sentinel:
filter:
url-patterns: /**
transport:
#配置sentinel,dashboard地址
dashboard: 10.6.8.238:8858
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#clientIp: 10.7.0.25
规则持久化配置
server:
port: 8002
nacos:
config:
bootstrap:
log:
enable: true
spring:
application:
name: nacos-sentinel-service
cloud:
nacos:
discovery:
server-addr: 10.6.8.238:8848 #Nacos作为服务注册中心地址
config:
server-addr: 10.6.8.238:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: DEFAULT_GROUP #指定在哪个group里
namespace:
# {spring.application.name}-{spring.profiles.active}.{spring.cloud.nacos.config.file-extension}
# 实际访问的配置nacos-payment-provider.yaml
sentinel:
filter:
url-patterns: /**
transport:
#配置sentinel,dashboard地址
dashboard: 10.6.8.238:8858
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#clientIp: 10.7.0.25
# 下面为持久化到nacos
datasource:
# 这里的flow名字随便取 流控规则
flow:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
groupId: DEFAULT_GROUP
dataId: ${spring.application.name}-flow-rules
rule-type: flow
data-type: json
# 授权规则
authority:
nacos:
server-addr: ${spring.cloud.nacos.config.server-addr}
dataId: ${spring.application.name}-authority-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: authority
# 降级规则
degrade:
nacos:
server-addr: ${spring.cloud.nacos.config.server-addr}
dataId: ${spring.application.name}-degrade-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: degrade
# 热点规则
param-flow:
nacos:
server-addr: ${spring.cloud.nacos.config.server-addr}
dataId: ${spring.application.name}-param-flow-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: param-flow
# 系统规则
system:
nacos:
server-addr: ${spring.cloud.nacos.config.server-addr}
dataId: ${spring.application.name}-system-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: system
nacos 增加对应的规则如:nacos-sentinel-service-flow-rules.json
[
{
"resource": "/testA",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
},
{
"resource": "/testB",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
resource:资源名称;
IimitApp:来源应用;
grade:國值类型,0表示线程数,1表示QPS;
count:单机阈值
strategy:流控模式,0表示直接,1表示关联,2表示链路
controlbehavior:流控效果,0表示快速失败,1表示 Warm Up,2表示排队等待;
cluster Mode:是否集群。
2.3 FlowLimitController
package com.lys.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* @Auther: liuysh
* @Date: 2022/7/20 21:55
* @Description:
*/
@RestController
@Slf4j
public class FlowLimitController {
@GetMapping("/testA")
public String testA() {
return "testA";
}
@GetMapping("/testB")
public String testB() {
return "testB";
}
@GetMapping("/testC")
public String testC() {
try {
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e) {
e.printStackTrace();
}
log.info("testC,测试RT");
return "testC";
}
@GetMapping("/testD")
public String testD() {
log.info("testD测试,异常比例");
int age = 10/0;
return "testD";
}
@GetMapping("/testE")
public String testE() {
log.info("testE测试,异常数");
int age = 10/0;
return "testE";
}
@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 "testHotKey的兜底方法deal_testHotKey执行";
}
}
3.sentinel与hystrix对比
功能 | Sentinel | Hystrix | 总结 | |
---|---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流)(模拟信号量) | 线程池隔离/信号量隔离 | Sentinel不创建线程依赖tomcat或jetty容器的线程池,存在的问题就是运行容器的线程数量限制了sentinel设置值的上限可能设置不准。比如tomcat线程池为10,sentinel设置100是没有意义的,同时隔离性不好hystrix使用自己创建的线程池,隔离性会更好 | |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 快速失败的本质功能 | |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | ||
动态规则配置 | 支持多种数据源 | 支持多种数据源 | ||
扩展性 | 多个扩展点 | 插件的形式 | ||
基于注解的支持 | 支持 | 支持 | ||
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持(并发线程数或信号量大小) | 快速失败的本质功能 | |
流量整形 | 支持预热模式、匀速器模式、预热排队模式 | 不支持(排队) | 支持排队好吧 | |
系统自适应保护 | 支持(仅对linux生效) | 不支持 | 所谓的自适应就是设置一个服务器最大允许处理量的阈值。(有比没有强,但是要知道最大负载量是多少。) | |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 | 简单的监控查看接近实时数据 | 控制台是非常有竞争力的功能,因为能集中配置限制数据更方便,但是展示数据和实时性没有hystrix直观。 | |
配置持久化 | ZooKeeper, Apollo, Nacos | Git/svn/本地文件 | Sentinel客户端采用直接链接持久化存储,应用客户端引用了更多的依赖,同样的存储链接可能有多个配置 | |
动态配置 | 支持 | 支持 | hystrix可能需要手动触发,sentinel增加了额外的端口进行配置文件控制,应该也支持spring boot动态配置 | |
黑白名单 | 支持 | 不支持 | 个人觉得这个功能用的不是很多 | |
springcloud集成 | 高 | 非常高 | Spring boot使用hystrix会更方便 | |
整体优势 | 集中配置设置及监控+更细的控制规则 | 漂亮的界面+接近实时的统计结果 | 集中配置可能更有吸引力,但是配置值是多少以及让谁控制依然是很头疼的事情。运维控制可能不知道哪个应该优先哪个不优先,应该调整到多大。什么时候更适合使用sentinel?个人认为docker容器化部署之后sentinel可能更会发挥作用,但是会有另外的竞品出现做选型。 |
- sentinel本身支持qps(qps:每秒可以进来的请求数,只是进来,不管是否进来之后服务走完。只管进来不管出去。),不会创建线程池,比较轻;而远程调用服务的时候,hystrix调用一个方法就会创建一个线程池,所以hystrix特别重;
- sentinel本身支持有qps,远程调用不会创建线程池,如果qps大,后面的服务处理不过来,所以就要进行限流降级处理;信号量隔离
- hystrix远程调用会创建线程池,并且该线程池是依赖tomcat的,不会比tomcat线程多,即使多了也没意义。线程池隔离
- 限流方案:qps 、线程数