1. 概述
轻量级的流量控制、熔断降级JAVA库,比Hystrix更强大
- 服务雪崩
- 服务降级
- 服务熔断
- 服务限流
2. 官网
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
下载地址
https://github.com/alibaba/Sentinel/releases
java -jar sentinel-dashboard.jar
http://localhost:8080
账号/密码:sentinel/sentinel
3. 核心组成
<a name="nViO8"></a>
## 4.2. YAML配置
```yaml
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: localhost:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: localhost:8080
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
# 取消Sentinel控制台懒加载
# eager: true
management:
endpoints:
web:
exposure:
include: '*'
4.3 主启动类
@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401
{
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}
4.4 业务类
@RestController
public class FlowLimitController
{
@GetMapping("/testA")
public String testA()
{
return "------testA";
}
@GetMapping("/testB")
public String testB()
{
return "------testB";
}
}
4.5 启动
- 启动Sentinel8080
- 启动微服务8401
- 启动8401微服务后查看sentienl控制台
- Sentinel采用的懒加载机制,执行一次访问即可,也可使用如下配置取消懒加载(参考:4.2 YAML配置放开第19行)
- sentinel8080正在监控微服务8401
5. 流量控制
5.1 基本介绍
5.2 流控模式
5.2.1 直接-快速失败
系统默认,如下图进行解读: 表示1秒钟内查询1次就是OK,若超过次数1,就直接-快速失败,报默认错误 测试:
- 快速点击访问http://localhost:8401/testA
- 结果:Blocked by Sentinel (flow limiting)
5.2.2 关联-快速失败
当关联的资源达到阈值时,就限流自己 当与A关联的资源B达到阀值后,就限流A自己 B惹事,A挂了 如下图,进行解读: 当关联资源/testB的qps阀值超过1时,就限流/testA的Rest访问地址,当关联资源到阈值后限制配置好的资源名
测试
:
- postman模拟并发密集访问testB
- 访问testB成功
- postman里新建多线程集合组
- 将访问地址添加进新新线程组
- Run
- 大批量线程高并发访问B,导致A失效了
- 点击访问http://localhost:8401/testA
- 结果:Blocked by Sentinel (flow limiting)
5.2.3 链路-快速失败
多个请求调用了同一个微服务
5.3 流控效果
5.3.1 直接-快速失败
同5.2.1,默认的流控处理,直接失败,抛出异常,Blocked by Sentinel (flow limiting)
源码
:com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
5.3.2 直接-预热(warm up)
作用
:限流、冷启动公式
:初始化阈值=单机阈值/coldFactor(默认值为**3**)
,经过预热时长后才会达到阈值 默认coldFactor为3, 即预热时长=threshold / 3
,经预热时长逐渐升至设定的 QPS 阈值。官网
:https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81—-%E5%86%B7%E5%90%AF%E5%8A%A8源码
:com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController 如下图,进行解读 案例,阀值为10,预热时长设置5秒,codeFactor为3。 系统初始化的阀值为10 / 3 约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10测试
:
- 多次点击http://localhost:8401/testB
- 刚开始不行,后续慢慢OK
- 应用场景如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
5.3.3 直接-排队等待
匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。
源码
:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController设置含义
:/testB每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒。测试
:
6. 降级规则
6.1 官网
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
6.2 配置说明
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如:调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。 注意:Sentinel的断路器是没有半开状态的,这点不同于Hystrix(参考:十一、HyStrix———熔断器 4. 服务熔断)
- 半开状态系统自动去检测是否请求有异常
- 没有异常就关闭断路器恢复使用
- 有异常则继续打开断路器不可用。
RT(平均响应时间,秒级)
- 平均响应时间超出阈值 且 在时间窗口内通过的请求>=5,两个条件同时满足后触发降级
- 窗口期过后关闭断路器
RT最大4900,超出都按4900算(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
异常比列(秒级)
异常比例(秒级统计)超过阈值时 且 QPS >= 5,触发降级;时间窗口结束后,关闭降级
异常数(分钟级)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级
6.3 RT
6.3.1 测试
6.3.1.1 业务类
@GetMapping("/testD")
public String testD()
{
//暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("testD 测试RT");
return "------testD";
}
6.3.1.2 配置
6.3.1.3 jmeter压测
6.3.1.4 结论
按照上述配置,永远一秒钟打进来10个线程(大于5个了)调用testD,我们希望200毫秒处理完本次任务,如果超过200毫秒还没处理完,在未来1秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闸断电了。 后续停止jmeter,没有这么大的访问量了,断路器关闭(保险丝恢复),微服务恢复OK
6.4 异常比例
6.4.1 业务类
@GetMapping("/testD")
public String testD()
{
log.info("testD 测试RT");
int age = 10/0;
return "------testD";
}
6.4.2 配置
6.4.3 Jmeter
6.4.4 结论
按照上述配置,单独访问一次,必然来一次报错一次(int age = 10/0),调一次错一次; 开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了。 断路器开启(保险丝跳闸),微服务不可用了,不再报错error而是服务降级了。
6.5 异常数
时间窗口一定要大于等于60秒。异常数是按照分钟统计的
6.5.1 业务类
@GetMapping("/testE")
public String testE()
{
log.info("testE 测试异常比例");
int age = 10/0;
return "------testE 测试异常比例";
}
6.5.2 配置
6.5.3 jmeter
6.5.4 结论
http://localhost:8401/testE,第一次访问绝对报错,因为除数不能为零, 我们看到error窗口,但是达到5次报错后,进入熔断后降级。
7. 热点Key规则
热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作
7.1 @SentinelResource预热(详细参考:9. @SentinelResource)
兜底方法 分为系统默认和用户自定义,两种
之前的case,限流出问题后,都是用sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
我们能不能自定义?类似hystrix,某个方法出问题了,就找对应的兜底降级方法?
结论 从
@HystrixCommand
到@SentinelResource
@SentinelResource 处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;
RuntimeException int age = 10/0,这个是java运行时报出的运行时异常RunTimeException,@SentinelResource不管
总结:@SentinelResource主管配置出错,运行出错该走异常走异常
7.2 案例
7.2.1 业务类
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2){
return "------testHotKey";
}
// com.alibaba.csp.sentinel.slots.block.BlockException
public String dealHandler_testHotKey(String p1,String p2,BlockException exception)
{
return "-----dealHandler_testHotKey";
}
7.2.2 配置
限流模式只支持QPS模式,固定写死了。(这才叫热点) @SentinelResource注解标识的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推 单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。 上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。 如果不加 blockHandler 属性,默认使用sentinel自带的返回提示
Blocked by Sentinel (flow limiting)
7.2.3 测试
多次发送 ❌http://localhost:8401/testHotKey?p1=abc ❌http://localhost:8401/testHotKey?p1=abc&p2=33 ✅http://localhost:8401/testHotKey?p2=abc
7.2.4 参数例外项
热点参数的注意点,参数必须是基本类型或者String 上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流 我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样,假如当p1的值等于5时,它的阈值可以达到200
测试
: 多次点击
- ✅http://localhost:8401/testHotKey?p1=5
- ❌http://localhost:8401/testHotKey?p1=3
- 当p1等于5的时候,阈值变为200,当p1不等于5的时候,阈值就是平常的1
8. 系统规则
配置全局QPS
8.1 官网
https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81
8.2 各项配置参数说明
9. @SentinelResource
9.1 按资源名称限流+后续处理
9.1.1 业务类
@RestController
public class RateLimitController
{
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource()
{
return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
}
public CommonResult handleException(BlockException exception)
{
return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
}
9.1.2 配置流控规则
按资源就不加
/
表示1秒钟内查询次数大于1,就跑到我们自定义的处理限流
9.2 按照Url地址限流+后续处理
按URL就加
/
通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息
9.2.1 业务类
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl",blockHandler = "handleException")
public CommonResult byUrl()
{
return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
}
9.2.2 配置
9.3 自定义限流后续处理
上面兜底方案面临的问题:
- 系统默认的,没有体现我们自己的业务要求。
- 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
- 每个业务方法都添加一个兜底的,那代码膨胀加剧。
- 全局统一的处理方法没有体现
9.3.1 案例
9.3.1.1 创建CustomerBlockHandler类用于自定义限流处理逻辑
public class CustomerBlockHandler
{
public static CommonResult handlerException(BlockException exception)
{
return new CommonResult(4444,"按客戶自定义,global handlerException----1");
}
public static CommonResult handlerException2(BlockException exception)
{
return new CommonResult(4444,"按客戶自定义,global handlerException----2");
}
}
9.3.1.2 业务类
/**
* 自定义通用的限流处理逻辑,
* blockHandlerClass = CustomerBlockHandler.class
* blockHandler = handleException
* 上述配置:找CustomerBlockHandler类里的handleException2方法进行兜底处理
*/
/**
* 自定义通用的限流处理逻辑
*/
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult customerBlockHandler()
{
return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
9.3.1.3 配置
9.3.1.4 测试
测试结果出现自定义返回
9.3.2 更多注解说明
9.3.3 硬编码方式
所有的代码都要用try-catch-finally方式进行处理 Sentinel主要有三个核心Api:
SphU
定义资源Tracer
定义统计ContextUtil
定义了上下文
10. 服务熔断
sentinel整合ribbon+openFeign+fallback
10.1 Ribbon系列
10.1.1 提供者
新建cloudalibaba-provider-payment9003/9004两个一样的做法
10.1.1.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.atguigu.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-provider-payment9003</artifactId>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot整合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>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
10.1.1.2 YML
server:
# 还有一个9004
port: 9003
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'
10.1.1.2 主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003
{
public static void main(String[] args) {
SpringApplication.run(PaymentMain9003.class, args);
}
}
10.1.1.4 业务类
@RestController
public class PaymentController
{
@Value("${server.port}")
private String serverPort;
public static HashMap<Long,Payment> hashMap = new HashMap<>();
static
{
hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
}
@GetMapping(value = "/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;
}
}
10.1.2 消费者
新建cloudalibaba-consumer-nacos-order84
10.1.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.atguigu.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-consumer-nacos-order84</artifactId>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot整合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>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
10.1.2.2 YML
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: localhost:8080
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-payment-provider
10.1.2.3 主启动类
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain84
{
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class, args);
}
}
10.1.2.4 业务类
10.1.2.4.1 ApplicationContextConfig
@Configuration
public class ApplicationContextConfig
{
@Bean
@LoadBalanced
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
10.1.2.4.2 CircleBreakerController
@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback") //没有配置,给客户error页面,不友好
// @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
// @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
// @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
// exceptionsToIgnore = {IllegalArgumentException.class}) // 被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。
public CommonResult<Payment> fallback(@PathVariable Long id)
{
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
//本例是fallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
}
//本例是blockHandler
public CommonResult blockHandler(@PathVariable Long id,BlockException blockException) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment);
}
10.1.3 结论
fallback管运行异常,blockHandler管配置违规,只有fallback时不用在sentinel进行配置 @SentinelResource(value = “fallback”) //没有配置,给客户error页面,不友好 @SentinelResource(value = “fallback”,fallback = “handlerFallback”) //fallback只负责业务异常 @SentinelResource(value = “fallback”,blockHandler = “blockHandler”) //blockHandler只负责sentinel控制台配置违规 @SentinelResource(value = “fallback”,fallback = “handlerFallback”,blockHandler = “blockHandler”, exceptionsToIgnore = {IllegalArgumentException.class}) // 被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。exceptionsToIgnore 忽略某个异常,将信息直接打在页面
10.2 Feign系列
10.2.1 提供者
同上例10.1.1
10.2.2 消费者
修改84模块
10.2.2.1 POM增加
<!--增加SpringCloud openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
10.2.2.2 YML增加
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
10.2.2.3 业务类
10.2.2.3.1 带@FeignClient注解的业务接口
//调用中关闭9003服务提供者
/**
* 使用 fallback 方式是无法获取异常信息的,
* 如果想要获取异常信息,可以使用 fallbackFactory参数
*/
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
@GetMapping(value = "/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
10.2.2.3.2 fallback = PaymentFallbackService.class
@Component
public class PaymentFallbackService implements PaymentService
{
@Override
public CommonResult<Payment> paymentSQL(Long id)
{
return new CommonResult<>(444,"服务降级返回,没有该流水信息",new Payment(id, "errorSerial......"));
}
}
10.2.2.3.3 Controller
//==================OpenFeign==================
@Resource
private PaymentService paymentService;
@GetMapping(value = "/consumer/openfeign/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
{
if(id == 4)
{
throw new RuntimeException("没有该id");
}
return paymentService.paymentSQL(id);
}
10.2.2.4 主启动类
//添加启动Feign的功能
@EnableFeignClients
10.2.3 结论
测试84调用9003,此时故意关闭9003微服务提供者,看84消费侧自动降级,不会被耗死
10.3 熔断框架比较
11. 规则持久化
问题:一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化 解决:将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效
11.1 步骤
11.1.1 POM
<!--SpringCloud ailibaba sentinel-datasource-nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
11.1.2 YML
spring:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow