当前位置:网站首页>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
边栏推荐
- Fashion classification case based on keras
- Build openstack platform
- cv_ Solution of mismatch between bridge and opencv
- Go file operation
- [UDS unified diagnostic service] (Supplement) v. detailed explanation of ECU bootloader development points (1)
- mysql自动启动设置用Systemctl start mysqld启动
- Tensorflow tensor introduction
- From source code to executable file
- Docker installation MySQL
- 【ACM】509. 斐波那契数(dp五部曲)
猜你喜欢
Implementation of k8s redis one master multi slave dynamic capacity expansion
From introduction to mastery of MATLAB (2)
Win1远程出现“这可能是由于credssp加密oracle修正”解决办法
ArcGIS license error -15 solution
YOLOv4剪枝【附代码】
MATLAB小技巧(6)七种滤波方法比较
k8s之实现redis一主多从动态扩缩容
Robocode tutorial 8 - advanced robot
A few lines of code teach you to crawl lol skin pictures
C language loop structure program
随机推荐
QTableWidget使用讲解
Resolves the interface method that allows annotation requests to be written in postman
Crawler for querying nicknames and avatars based on qqwebapi
Solving the problem of displaying too many unique values in ArcGIS partition statistics failed
登录和发布文章功能测试
Docker 安裝 Redis
C [file operation] read TXT text by line
Install pyshp Library
Resolve the error Max virtual memory areas VM max_ map_ count [65530] is too low, increase to at least [262144]
Jenkspy package installation
k8s之实现redis一主多从动态扩缩容
Flash - Middleware
Rust: how to implement a thread pool?
Svn simple operation command
Identification verification code
Realization of consumer gray scale
Implementation of object detection case based on SSD
Gst-launch-1.0 usage notes
Win1远程出现“这可能是由于credssp加密oracle修正”解决办法
Pyppeter crawler