天津做公司网站,河源网站设计,最好的手表网站,html页面能做成网站吗一、引言
1、了解服务可用性问题#xff0c;服务挂掉原因 缓存击穿、单点故障、流量激增、线程池爆满、CPU飙升、DB超时、缺乏容错机制或保护机制、负载不均、服务雪崩、异常没处理等。
服务雪崩效应#xff1a;因服务提供者的不可用导致服务调用者的不可用#xff0c;并将…一、引言
1、了解服务可用性问题服务挂掉原因 缓存击穿、单点故障、流量激增、线程池爆满、CPU飙升、DB超时、缺乏容错机制或保护机制、负载不均、服务雪崩、异常没处理等。
服务雪崩效应因服务提供者的不可用导致服务调用者的不可用并将 不可用逐渐放大的过程。
2、常见容错机制
超时机制。服务限流。隔离。服务线程访问数量隔离或信号隔离。服务熔断。远程服务不稳定或者网络抖动时暂时关闭当依赖服务大量超时没有必要再去请求直接返回一个异常信息。单服务熔断后需考虑服务降级处理。服务降级。有服务熔断避让有服务降级相当于兜底方案。当调用链路中某个资源出现不稳定例如表现为 timeout异常比例升高的时候则对这个资源的调用进行限制并让请求快速失败避免影响到其它的资源最终产生雪崩的效果。客户端自己创建一个方案比如备用接口、缓存、mock数据让服务可用需考虑业务场景。
主要为了解决因服务可用性的问题引入Sentinel。高可用防护/容错机制尤其是针对流量的防护。
二、Sentinel 介绍
Sentinel分布式系统的流量防卫兵阿里巴巴开源面向分布式服务架构的高可用防护组件。 随着微服务的流行服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 官方文档地址 https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel https://github.com/alibaba/Sentinel/wiki https://sentinelguard.io/zh-cn/ Sentinel和 Hystrix 对比 Hystrix地址 https://github.com/Netflix/Hystrix
三、如何使用
sentinel 的使用可以分为两个部分:
核心库Java 客户端不依赖任何框架/库不依赖 Dashboard但是结合 Dashboard 可以取得最好的效果。能够运行于Java 8 及以上的版本的运行时环境同时对 Dubbo / Spring Cloud 等框架也有较好的支持。控制台DashboardDashboard 主要负责管理推送规则、监控、管理机器信息等。
核心库的使用sentinel-core核心库在cloud中使用可可在单独的springboot项目中使用。 主要是学习各种规则的定义和使用。 定于规则和流控资源等看官网有案例 https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8 规则的种类
流量控制规则熔断降级规则系统保护规则访问控制规则热点规则 四、 springboot整合sentinel
以流控规则和熔断降级规则说明。
4.1 流控规则
我们先在一个单纯的springboot使用一下流控规则 方案一代码中写完成 1、首先添加依赖。
?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.2.RELEASE/versionrelativePath/ !-- lookup parent from repository --/parentmodelVersion4.0.0/modelVersionartifactIdsentinel-order/artifactIddependencies!--需依赖web--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--sentinel核心库--dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-core/artifactIdversion1.8.0/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.8/version/dependency/dependencies/project2、创建一个hello接口给一个对应的资源。然后给该资源设置一个流控的规则设置。
/*** Description: 流控测试1*/
RestController
Slf4j
public class HelloController {//资源名称private static final String RESOURCE_NAME hello;/*** 进行sentinel 流控* 对hello定义一个 RESOURCE_NAME 的资源名称进行流控* 通常资源名称会和接口名称保持一致**/RequestMapping(/get)public String hello(){Entry entry null;// 务必保证 finally 会被执行try{//sentinel针对资源进行限制// 资源名可使用任意有业务语义的字符串注意数目不能太多超过 1K超出几千请作为参数传入而不要直接作为资源名entry SphU.entry(RESOURCE_NAME);log.info(业务逻辑-----);return hello;} catch (BlockException e) {//资源访问阻止被限流或被降级//进行相应的操作log.info(Block);return 被流控了;} catch (Exception ex) {// 若需要配置降级规则需要通过这种方式记录业务异常Tracer.traceEntry(ex, entry);} finally {// 务必保证 exit务必保证每个 entry 与 exit 配对if (entry ! null) {entry.exit();}}return null;}/*** 定于规则。初始化时运行*/PostConstructprivate static void initFlowRules(){//流控规则ArrayListFlowRule rules new ArrayList();//流控FlowRule flowRule new FlowRule();//设置保护的资源对哪个资源进行流控规则flowRule.setResource(RESOURCE_NAME);//设置流控规则QPSflowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);//设置受保护的资源阈值 set limit QPS to 20//1秒只能访问一次如果超过就会进入上面的BlockException 中返回被流控flowRule.setCount(1);rules.add(flowRule);//加载配置好的规则FlowRuleManager.loadRules(rules);}}3、测试超过一秒一次请求就会被流控
这样写如果流控资源太多代码冗余使用注解的形式完成重复代码流控部分。 方案二使用注解形式。 1、依赖新增sentinel-annotation-aspectj的依赖
!--SentinelResource注解需依赖--
dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-annotation-aspectj/artifactIdversion1.8.0/version
/dependency2、需配置支持该注解的Bean
Component
public class SentinelResourceAspectConfig {Beanpublic SentinelResourceAspect sentinelResourceAspect(){return new SentinelResourceAspect();}
}3、重写一个接口来实现流控规则
/*** Description: 流控测试2注解形式*/
RestController
Slf4j
public class SentinelController {private static final String USER_RESOURCE_NAME sentinelApi;/*** SentinelResource 改善之前hello接口的资源定于和被流控降级的处理方法* value 定于资源* blockHandler 设置流控降级后的方法(默认该方法必须声明在同一类中)。* 如果不想在同一类中需添加一个参数指定类比如 blockHandlerClass User.class。但是blockHandler对应的方法需static修饰。fallback和这个一样* fallback 单接口出现异常就可以交给fallback指定的方法进行处理。还可以* blockHandler和fallback如果同时指定blockHandler优先级更高。* return*/GetMapping(/sentinelApi)SentinelResource(value USER_RESOURCE_NAME,//降级后的处理方法blockHandler blockHandlerBySentinelApi,//降级的方法不在同一类中可以用blockHandlerClass指定//blockHandlerClass User.class,//异常执行的方法fallback fallbackBySentinelApi//可以排除指定的异常不处理//exceptionsToIgnore {ArithmeticException.class})public User getUserResourceName(Integer id){int i 1 / id;return new User(tc);}/*** blockHandler 函数原方法调用被限流/降级/系统保护的时候调用* 注意* 1、一定要public* 2、入参的值和返回值一定要和源方法保持一致源方法设置SentinelResource中的blockHandler对应的calss* 3、可以在参数最后面添加BlockException* param ex* return*/public User blockHandlerBySentinelApi(Integer id,BlockException ex){ex.printStackTrace();return new User(哇哦被流控了);}public User fallbackBySentinelApi(Integer id,Throwable e){return new User(异常了执行异常方法);}/*** 定于规则。初始化时运行*/PostConstructprivate static void initFlowRules(){//流控规则ArrayListFlowRule rules new ArrayList();//流控FlowRule flowRule new FlowRule();//设置保护的资源对哪个资源进行流控规则flowRule.setResource(USER_RESOURCE_NAME);//设置流控规则QPSflowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);//设置受保护的资源阈值 set limit QPS to 20//1秒只能访问一次如果超过就会进入上面的BlockException 中返回被流控flowRule.setCount(1);rules.add(flowRule);//加载配置好的规则FlowRuleManager.loadRules(rules);}
}4、测试传参非0或0测试。
4.2 熔断降级规则 先看一下流控和降级区别。 流控是根据规则直接排除降级是根据规则进行降级方法处理。 流控一般设置在服务提供方。 降级一般设置在服务消费方。 熔断降级调用逻辑 比如A调用BB接口如果触发降级一旦触发降级就会进入时间窗口之内如果A再去请求B则会直接调用降级方法而不是调用B接口中的代码。如果时间窗口期过了就会调用B接口的代码如果第一次就异常则再次熔断流转。
/*** Description: 降级测试*/
RestController
Slf4j
public class Sentinel2Controller {private static final String DEGREDE_RESOURCE_NAME degrade;/*** 熔断降级规则处理测试接口* param id* return* throws InterruptedException*/GetMapping(degrade)SentinelResource(value DEGREDE_RESOURCE_NAME,entryType EntryType.IN,blockHandler blockHandlerForDg)public User degrade(Integer id ) throws InterruptedException{int i 1 / id;return new User(熔断降级规则处理测试接口);}public User blockHandlerForDg(Integer id,BlockException ex){return new User(熔断降级处理);}/*** 定于规则。初始化时运行*/PostConstructprivate static void initFlowRules(){
// //流控规则
// ArrayListFlowRule rules new ArrayList();
//
// //流控
// FlowRule flowRule new FlowRule();
// //设置保护的资源对哪个资源进行流控规则
// flowRule.setResource(USER_RESOURCE_NAME);
// //设置流控规则QPS
// flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// //设置受保护的资源阈值 set limit QPS to 20
// //1秒只能访问一次如果超过就会进入上面的BlockException 中返回被流控
// flowRule.setCount(1);
// rules.add(flowRule);
// //加载配置好的规则
// FlowRuleManager.loadRules(rules);//降级规则ArrayListDegradeRule degradeRules new ArrayList();DegradeRule degradeRule new DegradeRule();degradeRule.setResource(DEGREDE_RESOURCE_NAME);//设置降级规则异常数degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);//设置阈值 触发熔断异常数2。degradeRule.setCount(2);//触发熔断最小请求数 2。必须请求2次2次都异常才触发degradeRule.setMinRequestAmount(2);//统计时长多长时间内触发上面的异常次数单位msdegradeRule.setStatIntervalMs(60*1000);//三个设置结合就是//一分钟内执行了2次出现了2次异常就会触发熔断。其实源码是所有会多请求一次才熔断//熔断窗口期。单位s。进入熔断窗口后则直接走降级方法。//过了熔断窗口期,第一次调用还异常继续流转熔断降级处理。degradeRule.setTimeWindow(10);degradeRules.add(degradeRule);DegradeRuleManager.loadRules(degradeRules);}
}测试连续调用3次就会直接调用熔断降级处理不再执行接口中方法。
五、sentinel 控制台
告别上面的代码设置规则代码设置有助于了解API和帮助看源码有些属性需通过代码设置。 学习地址
https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B01、下载Sentinel 控制台 获取 Sentinel 控制台地址 https://github.com/alibaba/Sentinel/releases 根据springcloud下载对应版本我们下载1.8.0版本。
2、启动 注意启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。 从 Sentinel 1.6.0 起Sentinel 控制台引入基本的登录功能默认用户名和密码都是 sentinel。可以参考鉴权模块文档 配置用户名和密码。 注若您的应用为 Spring Boot 或 Spring Cloud 应用您可以通过 Spring 配置文件来指定配置详情请参考 直接启动命令
java -jar sentinel-dashboard-1.8.0.jar
默认8080端口。用户可以通过如下参数进行配置修改端口、账号和密码
地址https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0#%E9%89%B4%E6%9D%83-Dserver.port8080 用于指定 Sentinel 控制台端口为 8080-Dsentinel.dashboard.auth.usernamesentinel 用于指定控制台的登录用户名为 sentinel-Dsentinel.dashboard.auth.password123456 用于指定控制台的登录密码为 123456如果省略这两个参数默认用户和密码均为 sentinel-Dserver.servlet.session.timeout7200 用于指定 Spring Boot 服务端 session 的过期时间如 7200 表示 7200 秒60m 表示 60 分钟默认为 30 分钟同样也可以直接在 Spring properties 文件中进行配置。
为方便启动可以创建.bat文件:
java -Dserver.port8858 -Dsentinel.dashboard.auth.usernametc -Dsentinel.dashboard.auth.password123456 -jar sentinel-dashboard-1.8.0.jar
pause访问页面http://localhost:8080/ 。修改后端口8858. 账号和密码默认sentinel。修改后账号tc,密码123456. 界面如图所示 3、客户端接入控制台 3.1 引入依赖 刚刚的spring-boot案例引入依赖
!--整合控制台--
dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-transport-simple-http/artifactIdversion1.8.0/version
/dependency3.2 配置启动参数 启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.serverconsoleIp:port 指定控制台地址和端口。若启动多个应用则需要通过 -Dcsp.sentinel.api.portxxxx 指定客户端监控 API 的端口默认是 8719。 IDEA可以在configurations设置。
3.3 重启启动项目 访问一下项目接口才会注册到Sentinel 控制台然后访问控制台就会发现注册了一个服务。
六、spring cloud Alibaba整合Sentinel
1、引入依赖
!--sentinel启动器--
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId
/dependency2、添加yml配置为微服务设置sentinel控制台地址。
spring:application:name: order-sentinelprofiles:# 环境配置active: devcloud:sentinel:transport:dashboard: 127.0.0.1:88583、访问一下接口让服务注册到sentinel查看sentinel控制台。
七、控制台页面配置
1、实时监控
监控接口时间节点的QPS、响应时间等。
2、簇点链路
显示所有能够进行流控、降级的资源。
3、流控规则
流控规则—flow control,其原理是监控应用流量的QPS或并发线程等指标单达到指定对的阈值时对流量进行控制以避免被瞬时的流量高峰冲垮从而保证应用的高可用性。 3.1 应用场景
应对洪峰流量秒杀、大促、下单、订单回流处理。消息型场景削峰填谷冷热启动。付费系统根据使用流量付费。 API GateWay:精准控制API流量。 3.2 流控模式
直接就是当前接口资源。关联 可以设置一个关联资源如果关联资源超过设定的限流则当前设置的资源就会受到影响。比如下单高峰每次下单会触发查询订单接口。则查询订单进行限流关联资源设置下单接口。可以通过JMeter工具进行测试。 链路入口资源当前接口进行限流受到影响的是入口资源。 比如test1和test2都调用了getUser对test2进行限流。
Autowired
OrderService orderService;//关联流控1
RequestMapping(test1)
public String test1(){return orderService.getUser();
}//关联流控2
RequestMapping(test2)
public String test2(){return orderService.getUser();
}public class OrderServiceImpl implements OrderService {SentinelResource(value getUser,blockHandler getUserBlockHandler)public String getUser() {return null;}public String getUserBlockHandler(BlockException e) {return 流控getUser;}
}测试会发现不生效需在配置文件中新增web-context-unify,原因是默认调用的一个链路被收敛了程序察觉不到调用结构。 cloud:sentinel:transport:dashboard: 127.0.0.1:8858web-context-unify: false #默认将调用链路收敛了配置后就会有这么一个调用链路 然后请求test2超过次数就会被流控。
3.3 流控效果
快速失败多余的流量直接决绝上面我们默认的就是快速失败。Warm Up预热可以设置一个预热时长访问流量进来默认开始访问为3,在预热时间内慢慢增大到阈值。场景可以配合缓存使用在缓存中慢慢补全之前没数据的缓存补全后流量慢慢递增。排队等待可以设置一个超时时间在激增流量之下超过阈值不会直接拒绝会在超时时间内处理之前的流量如果还有时间就去处理后续的流量。即把空余时间段充分利用起来需根据接口压测然后配置。
3.4 统一的异常处理。 上面我们都使用 SentinelResource注解定义每个接口的异常处理也可以使用统一的异常处理只是所有接口都走这个不是定制化异常处理接口不用加 SentinelResource注解。 后续接口都用这个全局处理进行测试。
/*** Description: 统一的异常注解* Date 2023/5/14 21:23*/
Component
public class myBlockExceptionHander implements BlockExceptionHandler {public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {System.out.println(BlockExceptionHandler 规则的详细信息e.getRule());Result r null;if(e instanceof FlowException){r Result.error(100,接口限流了);}else if(e instanceof DegradeException){r Result.error(101,服务降级了);}else if(e instanceof ParamFlowException){r Result.error(102,热点参数限流了);}else if(e instanceof SystemBlockException){r Result.error(103,触发系统保护规则了);}else if(e instanceof AuthorityException){r Result.error(104,授权规则不通过);}httpServletResponse.setStatus(500);httpServletResponse.setCharacterEncoding(utf-8);httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);new ObjectMapper().writeValue(httpServletResponse.getWriter(),r);}
}4、熔断降级策略
界面如下 界面配置说明 4.1 慢调用比例
最大RT毫秒接口处理时长超过设置的时间那就是慢调用。比例阈值0-1比如设置0.1表示10次请求中有一次慢调用就会进行熔断。最小请求数比如设置为5表示至少要请求5次。根据比例阈值配置比如比例为0.1最小请求数配置5表示请求5次有一次慢调用就熔断太草率了建议配置10调用10次有一次慢调用。熔断时长秒当满足熔断条件进入熔断持续的时长此时处于半开状态即过了熔断的持续时长第一次调用还是慢比例继续进入熔断时长。
4.2 异常比例 需配置的参数比例阈值、最小请求数、熔断时长和上面含义一致。 接口中需有异常。
RequestMapping(add)
public String add(){System.out.println(新增订单);int i 1 / 0;return 新增订单;
}4.3 异常比例 需配置的参数异常数异常的数量、最小请求数、熔断时长。。 最小请求数、熔断时长和第一个含义一致。
5、热点规则
热点经常访问的数据如热点商品。 使用场景热点商品访问/操作、用户/IP限制。 实现原理热点淘汰策略LRU token Bucket流控。 界面配置说明 getById的资源第一个参数一秒钟访问10次进行热点异常处理。如果参数值1一秒2次以上进行热点异常处理。
界面参数说明
资源名接口设置的对应的资源名称。参数索引接口中对应的第几个参数默认0开始。索引位。单机阈值根据QPS设置访问的数量。比如10。统计窗口时长几秒钟访问的QPS是多少个上面10个单机阈值。
参数例外项常用于设置热点参数。
参数类型什么类型的值。限流阈值比如设置为2.参数值值是多少,热点的参数。比如设置1,请求id为1的值请求2次就进行热点异常处理。
热点参数和普通参数也可以反着写多数是热点参数则配上面进行热点处理下面配置普通参数进行放流处理。
6、系统保护规则
系统保护规则基于容量评估不到位、机器Load、CPU飙升、负载均衡不均等引起系统雪崩能够对系统全局起到一个兜底防护。 在界面系统规则中新增
Load 自适应仅对Linux/unix-like机器生效):系统 Load1作为启发指标进自适应系统保护当系统Load1超过设定的启发值且系统当前的并发线数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQPs * minRt 估算得出。设定参考值一般是CPU cores * 2.5。 https://www.cnblogscom/gentlemanhai/p/8484839.htmlCPU 使用率 (1.5.0 版本): 当系统 CPU 使用率超过阈值即触发系统保护 (取值范围 0.0-1.0)比较灵敏。平均 RT:当单台机器上所有入口流量的平均 RT达到阈值即触发系统保护单位是毫秒。并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。入口QPS:当单台机器上所有入口流量的 QPS达到阈值即触发系统保护。
7、规则持久化
以上规则都是存储在内存中的重启后就没在了需要重新配置所有需要持久化。 推模式结合配置中心nacos、zookeeper进行推送到sentinel。 1、引入依赖
dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-datasource-nacos/artifactId
/dependency2、nacos配置中心配置流控规则 相关参数说明https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81 dataID: order-sentinel-flow-rule 配置相关的流控规则。 [{resource: getById,controlBehavior: 0,count: 2,grade: 1,limitApp: default,strategy: 0
}]3、项目yml配置新增
spring:application:name: order-sentinelprofiles:# 环境配置active: devcloud:sentinel:transport:dashboard: 127.0.0.1:8858web-context-unify: false #默认将调用链路收敛了datasource:flow-rule: #可以自定义nacos:#配置到nacos进行持久化server-addr: 127.0.0.1:8848username: nacospassword: nacosdataId: order-sentinel-flow-rulerule-type: flow可配置项可以点击配置参数跳转到源码查看例如datasource中nacos相关配置项
八、sentinel整合openFeign
主要是运用于服务提供者进行降级比如A调用者调用B服务提供者B异常对B服务进行降级处理。 即将之前学习的openFeign项目加入sentinel依赖再写降级的类。 1、依赖依赖
?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringcloud-demo/artifactIdgroupIdcom.tc/groupIdversion0.0.1-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdorder-openfeign-sentinel/artifactIddependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependency!--nacos的服务注册与发现无需写版本spring-cloud-alibaba-dependencies会自动维护--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--添加openfeign依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency!--sentinel启动器--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependency/dependencies/project2、添加一个降级处理openFeign的实现类实现调用的远程接口。openFeign的接口上需配置fallback 实现类.class
FeignClient(name stock-service,path /stock,//openFeign的接口上需配置fallback 实现类.classfallback StockFeignServiceFallback.class)
public interface StockFeignService {//声明需要调用的接口对应的方法RequestMapping(/reduce)public String reduce();
}//降级处理openFeign的实现类
Component
public class StockFeignServiceFallback implements StockFeignService{Overridepublic String reduce() {return 降级了;}
}RestController
RequestMapping(/order)
public class OrderController {Autowiredprivate StockFeignService stockFeignService;RequestMapping(/add)public String add(){System.out.println(新增订单);//扣减库存的远端接口同样写个异常测试String reduce stockFeignService.reduce();return openFeign远程调用reduce ---;}}3、配置文件新增下面的配置。然后重启项目测试即可。
feign:sentinel:#开启feign和sentinel的整合enabled: true