当前位置:网站首页>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
边栏推荐
- Array rotation
- C network related operations
- Pointers in rust: box, RC, cell, refcell
- 【ACM】509. 斐波那契数(dp五部曲)
- Deep learning classic network analysis and target detection (I): r-cnn
- According to the result set queried by SQL statement, it is encapsulated as JSON
- Cells in rust share variable pointers
- Docker 安装 Redis
- 【ACM】70. 爬楼梯
- C language array processing batch data
猜你喜欢

idea中安装YapiUpload 插件将api接口上传到yapi文档上

C#的随机数生成

【ACM】455. Distribute Biscuits (1. Give priority to big biscuits to big appetite; 2. Traverse two arrays with only one for loop (use subscript index -- to traverse another array))

Batch export ArcGIS attribute table

re正則錶達式

mysql自动启动设置用Systemctl start mysqld启动

C language loop structure program

Robocode Tutorial 4 - robocode's game physics

Robocode tutorial 3 - Robo machine analysis

Visualization of residential house prices
随机推荐
re正則錶達式
From source code to executable file
ArcGIS license error -15 solution
Dock installation redis
proxy server
C language loop structure program
SSD硬盘SATA接口和M.2接口区别(详细)总结
Classification of cifar100 data set based on convolutional neural network
The difference between deep copy and shallow copy
【ACM】70. 爬楼梯
QT reading and writing XML files (including source code + comments)
Rust: a simple example of TCP server and client
According to the result set queried by SQL statement, it is encapsulated as JSON
Logic regression principle and code implementation
The vivado project corresponding to the board is generated by TCL script
powerdesigner各种字体设置;preview字体设置;sql字体设置
Docker 安装 Redis
ROS package NMEA_ navsat_ Driver reads GPS and Beidou Positioning Information Notes
Go language JSON package usage
Stanford machine learning course summary