<!-- nacos配置--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>2.2.6.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.6.RELEASE</version> </dependency> <!-- sentinel配置--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.6.RELEASE</version> </dependency> <!-- sentinel 规则基于nacos存储--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.3</version> </dependency>
server: servlet: context-path: /sentinel-nacos-demospring: application: name: sentinel-nacos-demo profiles: active: local cloud: nacos: config: server-addr: xxx.xxx.xx.x:8848 #server-addr: xxx.xxx.xx.x:8848group: ${spring.application.name} file-extension: yaml # 配置中心使用单独namespacenamespace: "study" discovery: server-addr: xxx.xxx.xx.x:8848 namespace: "study" group: "sentinel-nocas-demo" sentinel: transport: dashboard: xxx.xxx.xx.x:8842 #启动本项目后需要请求一次才能向sentinel控制台注册port: 8719 #当一个服务器部署多个应用时要配置不同port,单个应用可忽略client-ip: 10.32.4.230 #指定本机ip地址,避免多个虚拟地址,导致数据获取失败datasource: ## 配置流程控制 ## rule-type 配置表示该数据源中的规则属于哪种类型的规则(flow流控,degrade熔断降级,authority授权,system系统保护, param-flow热点参数限流, gw-flow, gw-api-group)flow: nacos: server-addr: xxx.xxx.xx.x:8848 namespace: "study" data-id: ${spring.application.name}-sentinel-flow-rules group-id: sentinel-group data-type: json rule-type: flow ## 配置降级规则degrade: nacos: server-addr: xxx.xxx.xx.x:8848 namespace: "study" dataId: ${spring.application.name}-sentinel-degrade-rules groupId: sentinel-group data-type: json rule-type: degrade system: nacos: server-addr: xxx.xxx.xx.x:8848 namespace: "study" dataId: ${spring.application.name}-sentinel-system-rules groupId: sentinel-group data-type: json rule-type: system[ { "resource": "/sentinel/rule/flow", "limitApp": "default", "grade": 1, "count": 1, "strategy": 0, "controlBehavior": 0, "clusterMode": false }]
[ { "resource": "/sentinel/rule/degrade", "count": 1, "grade": 0, "timeWindow": 10, "minRequestAmount": 1, "statIntervalMs": 1000, "slowRatioThreshold": 0.1 }]
[ { "avgRt":1, "highestCpuUsage":-1, "highestSystemLoad":-1, "maxThread":-1, "qps":1000 }]
@Componentpublic static class MyBlockExceptionHandler implements BlockExceptionHandler { @Override public void handle(HttpServletRequest httpServletRequest, HttpServletResponse response, BlockException e) throws Exception { //Sentinel规则的详细信息 BaseResponse r = BaseResponse.error("sentinel-控制拦截"); if (e instanceof FlowException) { r = BaseResponse.error("接口限流了",e.toString()); } else if (e instanceof DegradeException) { r = BaseResponse.error( "服务降级了",e.toString()); } else if (e instanceof ParamFlowException) { r = BaseResponse.error("热点参数限流了",e.toString()); } else if (e instanceof SystemBlockException) { r = BaseResponse.error( "触发系统保护规则了",e.toString()); } else if (e instanceof AuthorityException) { r = BaseResponse.error( "授权规则不通过",e.toString()); } //返回json数据 response.setStatus(500); response.setCharacterEncoding("utf-8"); response.setContentType(MediaType.APPLICATION_JSON_VALUE); new ObjectMapper().writeValue(response.getWriter(), r); }}
sentinel: transport: dashboard: xxx.168.16.13:8842 #启动本项目后需要请求一次才能向sentinel控制台注册port: 8719 #当一个服务器部署多个应用时要配置不同port,单个应用可忽略client-ip: xx.xx.4.230 #指定本机ip地址,避免多个虚拟地址,导致数据获取失败
ProcessorSlot 作为 SPI 接口进行扩,使得 Slot Chain 具备了扩展的能力。开发人员可以自行加入自定义的 slot 并编排 slot 间的执行顺序,从而可以给 Sentinel 添加自定义的功能。1.定义实现类加载顺序@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)2.定义NodeSelectorSlot实现类继承自抽象类 public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> 3.定义抽象类实现接口public abstract class AbstractLinkedProcessorSlot<T> implements ProcessorSlot<T>4.定义链路顶层接口public interface ProcessorSlot<T>
ProcessorSlot 接口,是不能加入到责任链路中的。参考源码:public class DefaultSlotChainBuilder implements SlotChainBuilder { @Override public ProcessorSlotChain build() { ProcessorSlotChain chain = new DefaultProcessorSlotChain(); List<ProcessorSlot> sortedSlotList = SpiLoader.of(ProcessorSlot.class).loadInstanceListSorted(); for (ProcessorSlot slot : sortedSlotList) { if (!(slot instanceof AbstractLinkedProcessorSlot)) { RecordLog.warn("The ProcessorSlot(" + slot.getClass().getCanonicalName() + ") is not an instance of AbstractLinkedProcessorSlot, can't be added into ProcessorSlotChain"); continue; } chain.addLast((AbstractLinkedProcessorSlot<?>) slot); } return chain; }}
public abstract class ProcessorSlotChain extends AbstractLinkedProcessorSlot<Object> { /** * Add a processor to the head of this slot chain. * * @param protocolProcessor processor to be added. */public abstract void addFirst(AbstractLinkedProcessorSlot<?> protocolProcessor); /** * Add a processor to the tail of this slot chain. * * @param protocolProcessor processor to be added. */public abstract void addLast(AbstractLinkedProcessorSlot<?> protocolProcessor);}
/** * 编写一个自定义限流链路 * * @author wangling * @date 2022/07/05 */@Spi(order = -3000)public class TestMySlot extends AbstractLinkedProcessorSlot<DefaultNode> { @Override public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode obj, int count, boolean prioritized, Object... args) throws Throwable { try { fireEntry(context, resourceWrapper, obj, count, prioritized, args); throw new BusinessException("TestMySlot-测试"); } catch (Exception e) { throw e; } catch (Throwable e) { RecordLog.warn("Unexpected entry exception", e); } } @Override public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) { try { fireExit(context, resourceWrapper, count, args); } catch (Throwable e) { RecordLog.warn("Unexpected entry exit exception", e); } }}
微信赞赏
支付宝赞赏