SentinelResource
在定义了资源点之后,我们可以通过Dashboard控制台页面来设置限流和降级策略来对资源点进行保护。同时还能通过[**@SentinelResource**](/SentinelResource)****注解来制定出现异常时的处理策略
1、属性说明
- value
资源名称、必须项、因为需要通过resource name找到对应的规则,这个是必须配置的。
- blockHandler
blockHandler对应处理BlockException的函数名称,可选项。blockHandler函数访问范围需要是public,返回的类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException。
- fallback
fallback函数名称,可选项,用于在抛出异常的时候提供fallback处理逻辑。fallBack函数可以针对所有类型的异常(Throwable)
- blockHandlerClass
blockHandler函数默认需要和原生方法在同一个类中,如果希望使用其他类的函数,则需要指定blockhandlerClass为对应的类的Class对象,注意对应的函数必须为static函数,否则无法解析。
- fallbackClass
fallBackClass的应用和blockHandlerClass类似,fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass为对应的类的Class对象,注意对应的函数必须为static函数,否则无法解析。
2、自定义处理限流和业务异常
@GetMapping("/hello4")
@SentinelResource(value ="hel1o4",blockHandler ="blockHandler",fallback ="fallbackHandler")
public string hello4(Integer age){int i = 10 / age;return "hello4";
}
// hel13Handler方法的参数和返回值要和原方法一直,BlockException用来接收原方法的异常
public string blockHandler(Integer age,BlockException e){return"资源被限流”;
}
//hel13Handler方法的参数和返回值要和原方法一直,Throwable用来接收原方法的异常(这里必须是Throwable用来接收原方法的异常,不能是exception)
public string fallbackHandler(Integer age,Throwable e) {return"资源出现异常";
}
以上这种方式可以处理资源中的限流和业务异常了,但是发现异常处理类和业务代码耦合了,而且还没办法复用。
3、处理异常类和业务类解耦
@RestController
@slf4j
public class HelloController f@GetMapping("/hel1o4")@SentinelResource(value = "hello4",blockHandlerClass = MyBlockHandlerClass.class,blockHandler ="blockHandler",fallbackClass = FallbackHandler.class,fallback ="fallbackHandler")public string hello4(Integer age) {int i = 18 / age;return "hel1o4";}
}
public class FallbackHandler {// 这里的方法必须是静态的,方法参数和返回值要和原方法一致public static string fallbackHandler(Integer age,Throwable e) {return"资源出现异常"}
}
public class MyBlockHandlerClass f// 这里的方法必须是静态的,方法参数和返回值要和原方法一致public static string blockHandler(Integer age,BlockException e) {System.out.println("bolockHanlder age ="+ age +",e="+e);return"资源被限流”;}
}
Feign整合Sentinel实现降级
Feign整合Sentinel后不同异常调用不同的处理器来解决异常。
流控异常调用:blockHandler
服务运行时异常调用:fallback
feign调用异常调用:feign降级
1、导入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactIdx
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、FeignFallbackFactory
@Component
public class FeignFallbackFactory implements FallbackFactory<HelloService>(@Autowiredprivate HelloServiceImpl helloService;@Overridepublic HelloService create(Throwable throwable) {System.out.println(throwable);return helloService;}
}
3、Feign接口
@FeignClient(value = "provider-1",fallbackFactory = FeignFallbackFactory.class)
public interface HelloService {@RequestMapping("/hello")public string hello();
}
4、开启sentinel
feign:sentinel:enabled: true
5、版本问题
SpringCloud版本和SpringCloudAlibaba版本冲突的问题。
Caused by:at feien.FeignsBuilder.com.alibaba.cloud.sentinel.feign,sentinelcontractHolder.parseAndvalidateMetadajava .lang.AbstractMethoderror:lane/class;)Liava/util/list:
at feignReflectiveFeigsParseHandlersByllame,apply(Reflectivefeign.java:151) feign-(ore-10.7,4,jar:na
at feign,ReflectiveFein,newinstance(ReflectiveFeign.java:49) [feign-core-10.7.4jar:na)
target(feien.ia
core-18.7.4.ar;na7
at or3.sorineframework.coudopenfeien.-strixtareter.tareetHystrixtmeter, ava:33) sorine-cloud-enfee-ore-2.2.2,RELEASE,m2.2.2RELEASE
at r.trmewo.cou.ttr da ertat -
at org.sprineframevwork,cIod.0pfeignFegclietactoryBen-gtTretFeclitFto Bean av282 gprn-coud-Efe-0re-2-22RELEASE.ar:2.2.2ELEASEam.Co.0 it B- tat 2----S22S
t org.pringframework.beans.atory, support.Fto Beamegistryuprt,0etbjectfrnFtr Ben (to Beamepistry supprtaa71)re-ns-52.4ELEASE5.2.4ELEASE
... 67 common frames omitted
解决方式
自定义一个SentinelContractHolder类,包名和源码保持一致。
packagecom.alibaba.cloud.sentinel.feign;
import feign.Contract;
import feign.MethodMetadata;
import java.util.HashMap;import
import java.util.List;import
import java.util.Map;
public class SentinelContractHolder implements Contract {private final Contract delegate;/* map key is constructed by ClassFullName + configkey. configkey is constructed by* (@link feign.Feign#configKey}*/public final static Map<String, MethodMetadata> METADATA MAP = new HashMap<>();public SentinelContractHolder(Contract delegate) {this.delegate = delegate!}@Overridepublic List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {List<MethodMetadata> metadatas = delegate.parseAndValidateMetadata(targetType);metadatas.forEach(metadata -> METADATA MAP.put(targetType.getName() + metadata.configkey(), metadata));return metadatas;}
}
Feign调用服务过程中,服务出现故障,如果服务中存在全局异常管理器,会认为这个故障已经被服务处理了,然后返回一个空的对象,feign不会调用自己的降级方法。
sentinel持久化
1、sentinel工作模式
在Sentinel客户端(微服务)中用代码写的配置,在启动后,当有第一次流量进来的时候,会推送给Sentinel-Dashboard;在Sentinel-Dashboard中的配置,会被推送到Sentinel客户端(微服务);默认情况下,不论 Sentinel-Dashboard中的配置还是Sentinel客户端中的配置,都是在内存中的,一点重启,这些变化过的规则就全部消失了。
2、semtinel持久化
在此将规则持久化到nacos中,在nacos中添加规则,然后同步到dashboard中。
1、导入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2、在yml中配置nacos信息
spring:application:name: sentinel-servercloud:nacos:discovery:server-addr: 192.168.147.11.8848sentinel:transport:dashboard: 192.168.147.11:8080port: 8719eager: truedatasource:sentinel1:nacos:serverAddr: 192.168.147.11:8848dataId: ${spring.application.name}groupId: DEFAULT_GROUPdata-type: jsonrule-type: flow
3、在nacos中添加规则
[{"resource":"he11o4","limitApp":"default","grade": 1,"count": 5,"strategy": 0,"controlBehavior":0,'clusterMode": false}
]
- resource: 资源名称
- limitApp: 来源应用
- grade: 阈值类型, 0-线程数 1-qps
- count: 单机阈值
- strategy: 流控模式, 0-直接 1-关联 2-链路
- controlBehavior:流控效果、0-快速失败,1-warm up,2-排队等待
- clusterMode: 是否集群
4、测试
服务启动后,当有第一次流量进来的时候,Sentinel-Dashboard会从nacos中拉取流控信息。