当前位置:网站首页>Dynamically add default fusing rules to feign client based on sentinel + Nacos
Dynamically add default fusing rules to feign client based on sentinel + Nacos
2022-04-23 18:10:00 【dawnsun001】
As the business grows , Micro service is imperative ; Recently took over an old project to use sentinel+nacos Fusing and current limiting , The fuse rules are configured the same , I feel a little redundant , Inefficient development . Think about upgrading , Because the service depends on the interface, it is through feignClient Called , Yes feignClient Call interface , Automatic scanning and dynamic realization of fuse rules .
One 、 Home page scanning feignClient Dependent interface , Dynamically generate fusing rules , push nacos

-
Realization ApplicationRunner Interface , rewrite run Method , according to EnableFeignClients Specify the package to load feignClient Class collection
@Override public void run(ApplicationArguments args) { Class<?> mainClass = deduceMainApplicationClass(); log.info(" Start loading default rules ,mainClass:{}", mainClass); if (mainClass == null) { throw new RuntimeException("can not fount main class"); } EnableFeignClients enableFeignClientsAnnotation = mainClass.getAnnotation(EnableFeignClients.class); if (enableFeignClientsAnnotation != null) { String[] feignClientPackages; String[] feignClientDeclaredPackages = enableFeignClientsAnnotation.basePackages(); // The statement feignClient The package name if (feignClientDeclaredPackages.length == 0) { feignClientPackages = new String[]{ mainClass.getPackage().getName()}; } else { feignClientPackages = feignClientDeclaredPackages; } // Initialize demotion rule initDeGradeRule(feignClientPackages); } log.info(" The default degradation rule processing is completed "); } -
according to feignClient Class collection , Initialize the fusing rule , And push nacos
private void initDeGradeRule(String[] feignClientPackages) { List<DegradeRule> localDegradeRuleList = new ArrayList<>(); Set<Class> feignClientClass = getFeignClientClass(feignClientPackages); for (Class clientClass : feignClientClass) { List<DegradeRule> rules = initRules(clientClass); localDegradeRuleList.addAll(rules); } List<DegradeRule> remoteDegradeRuleList = fetchRemoteRules(); // long-range nacos There are no rules , Then use local rules directly if (remoteDegradeRuleList == null || remoteDegradeRuleList.isEmpty()) { pushRules(localDegradeRuleList); return; } // Local rules Merge Remote rule policy proess(localDegradeRuleList, remoteDegradeRuleList); // Push local rules , To nacos pushRules(localDegradeRuleList); } -
obtain FeignClient class set
private Set<Class> getFeignClientClass(String[] packageNames) { ClassScanner classScanner = new ClassScanner(); Set<Class> feignClientClass = new HashSet<>(); for (String packageName : packageNames) { feignClientClass.addAll(classScanner.scan(packageName, FeignClient.class)); } return feignClientClass; } -
according to feignClient class object , Extract request mapping
private final static String HTTP_PROTOCOL_PREFIX = "http://"; private final static String ANNOTATION_VALUE_PREFIX = "${"; private final static String ANNOTATION_VALUE_SUFFIX = "}"; public List<DegradeRule> initRules(Class cla) { List<DegradeRule> degradeRuleList = new ArrayList<>(); FeignClient feignClient = (FeignClient) cla.getAnnotation(FeignClient.class); String classRequestMappingUrl = ""; RequestMapping classRequestMapping = (RequestMapping) cla.getAnnotation(RequestMapping.class); if (null != classRequestMapping) { classRequestMappingUrl = classRequestMapping.value()[0]; } String serviceName = feignClient.name(); if (serviceName.startsWith(ANNOTATION_VALUE_PREFIX) && serviceName.endsWith(ANNOTATION_VALUE_SUFFIX)) { serviceName = this.environment.resolvePlaceholders(serviceName); } Method[] methods = cla.getDeclaredMethods(); for (Method method : methods) { degradeRuleList.add(buildDegradeRule(getResourceName(classRequestMappingUrl, serviceName, method))); } DegradeRuleManager.loadRules(degradeRuleList); return degradeRuleList; -
Map on request , Splice resource identification
private String getResourceName(String crmu, String serviceName, Method method) { crmu = crmu.startsWith("/") ? crmu : "/" + crmu; String resourceName = ""; RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class); if (null != methodRequestMapping) { String mrm = methodRequestMapping.value()[0]; resourceName = HTTP_PROTOCOL_PREFIX + serviceName + crmu + (mrm.startsWith("/") ? mrm : "/" + mrm); } PostMapping methodPostMapping = method.getAnnotation(PostMapping.class); if (null != methodPostMapping) { String mpm = methodPostMapping.value()[0]; resourceName = HTTP_PROTOCOL_PREFIX + serviceName + crmu + (mpm.startsWith("/") ? mpm : "/" + mpm); } return resourceName; } -
Use resource identification , Build default rules
private DegradeRule buildDegradeRule(String resourceName) { DegradeRule rule = new DegradeRule(); // Set resource name rule.setResource(resourceName); // Set degradation rules TR 10 ms rule.setCount(200); // Type of rule RT rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // Window time rule.setTimeWindow(10); rule.setMinRequestAmount(3); rule.setStatIntervalMs(30000); rule.setSlowRatioThreshold(0.6); return rule; } -
Get remote nacos To configure
private List<DegradeRule> fetchRemoteRules() { return JSONObject.parseArray(nacosService.getConfig(dataId, groupId), DegradeRule.class); } -
Local rules Merge Remote rule policy
private void proess(List<DegradeRule> localDegradeRuleList, List<DegradeRule> remoteDegradeRuleList) { for (DegradeRule rule : remoteDegradeRuleList) { if (localDegradeRuleList.contains(rule)) { DegradeRule ldr = localDegradeRuleList.get(localDegradeRuleList.indexOf(rule)); if (ldr.equals(rule)) { continue; } localDegradeRuleList.remove(ldr); localDegradeRuleList.add(rule); } else { localDegradeRuleList.add(rule); } } } -
Push the fusing rule to nacos
private void pushRules(List<DegradeRule> localDegradeRuleList) { SerializeConfig serializeConfig = new SerializeConfig(); serializeConfig.propertyNamingStrategy = PropertyNamingStrategy.CamelCase; String contentStr = JSON.toJSONString(localDegradeRuleList, serializeConfig, SerializerFeature.PrettyFormat); nacosService.publish(dataId, groupId, contentStr, ConfigType.JSON.getType()); }
Two 、 Use AOP cut feign call , Dynamically add fuse logic execution

10. Reference resources Sentinel Of SentinelResourceAspect Inherit AbstractSentinelAspectSupport Realization feign Call interception
@Aspect
@Slf4j
@Component
public class FeignMethodAspect extends AbstractSentinelAspectSupport {
@Around("within(feign.Client+)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
log.info("within(feign.Client+) pjp {}, args:{}", pjp, pjp.getArgs());
String resourceName = pjp.getArgs()[0].toString().split(" ")[1];
Entry entry = null;
try {
Object var18;
try {
entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON, EntryType.OUT, pjp.getArgs());
Object result = pjp.proceed();
var18 = result;
return var18;
} catch (BlockException var15) {
String resource = var15.getRule().getResource();
log.error("FeignClient Interface triggers resource:{} The rules , The interface has been “ Current limiting / Fuse / Downgrade ”, The business system returns the default null value , Abnormal information :{}", resource, var15);
return null;
} catch (Throwable var16) {
this.traceException(var16);
}
} finally {
if (entry != null) {
entry.exit(1, pjp.getArgs());
}
}
return null;
}
}
- Configuration and use JDK A dynamic proxy , Otherwise intercept feignClient The call fails
spring:
aop:
proxy-target-class: false
- push nacosService rely on NacosConfigManager
public Boolean publish(String dataId, String group, String content, String type) {
try {
return nacosConfigManager.getConfigService().publishConfig(dataId, group, content, type);
} catch (NacosException e) {
log.error("NacosService publish e:{}", e);
}
return false;
}
- obtain nacos To configure
public String getConfig(String dataId, String group) {
try {
return nacosConfigManager.getConfigService().getConfig(dataId, group, 10000l);
} catch (NacosException e) {
log.error("NacosService publish e:{}", e);
}
return Strings.EMPTY;
}
Seeing your letters is like seeing you in person. , Thank you for your patience in reading , I hope it will be of some help to you , Praise is a virtue , I wish you every success in your work Promoting to a higher position !
版权声明
本文为[dawnsun001]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230544289080.html
边栏推荐
- How to install jsonpath package
- Qt读写XML文件(含源码+注释)
- String function in MySQL
- 深度学习经典网络解析目标检测篇(一):R-CNN
- Flash operates on multiple databases
- Installation du docker redis
- From introduction to mastery of MATLAB (2)
- 纳米技术+AI赋能蛋白质组学|珞米生命科技完成近千万美元融资
- Robocode tutorial 3 - Robo machine analysis
- Reptile efficiency improvement method
猜你喜欢
随机推荐
Robocode Tutorial 4 - robocode's game physics
Queue solving Joseph problem
Transfer learning of five categories of pictures based on VGg
Resolves the interface method that allows annotation requests to be written in postman
Multi thread safe reference arc of rust
Rust: a simple example of TCP server and client
解决报错max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
Docker 安裝 Redis
Stanford machine learning course summary
Clion installation tutorial
Build openstack platform
Generate verification code
消费者灰度实现思路
.105Location
How to read literature
Arcpy adds fields and loop assignments to vector data
MySQL 中的字符串函数
纳米技术+AI赋能蛋白质组学|珞米生命科技完成近千万美元融资
MySQL_ 01_ Simple data retrieval
Auto.js 自定义对话框








![解决报错max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]](/img/5f/a80951777a0473fcaa685cd6a8e5dd.png)
