Просмотр исходного кода

【新增】原数据路由策略功能

zhuzhoutong 5 лет назад
Родитель
Сommit
cf61161673

+ 34 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/config/MetaFilterAutoConfiguration.java

@@ -0,0 +1,34 @@
+package com.mrxu.framework.boot.config;
+
+import com.mrxu.framework.boot.irule.MetadataAwareRule;
+import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 功能概要:[原信息过滤配置] <br>
+ *
+ * @author zzt
+ * @date 2020/10/15
+ */
+@Configuration
+@ConditionalOnClass(DiscoveryEnabledNIWSServerList.class)
+@AutoConfigureBefore(RibbonClientConfiguration.class)
+@ConditionalOnProperty(value = "spring.application.metadata.enabled", matchIfMissing = true)
+public class MetaFilterAutoConfiguration {
+
+    /**
+     * 配置全局的路由策略
+     * @return 路由策略
+     */
+    @Bean
+    @ConditionalOnMissingBean
+    public MetadataAwareRule metadataAwareRule() {
+        return new MetadataAwareRule();
+    }
+}

+ 10 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/config/WebMvcConfig.java

@@ -1,6 +1,7 @@
 package com.mrxu.framework.boot.config;
 
 import com.mrxu.framework.boot.handle.UserInfoHandler;
+import com.mrxu.framework.boot.util.SpringApplicationContextUtil;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@@ -24,6 +25,15 @@ public class WebMvcConfig implements WebMvcConfigurer {
         return new UserInfoHandler();
     }
 
+    /**
+     * bean工具类
+     * @return
+     */
+    @Bean
+    public SpringApplicationContextUtil springApplicationContextUtil(){
+        return new SpringApplicationContextUtil();
+    }
+
     /**
      * 拦截器添加
      * @param registry

+ 8 - 9
framework-boot/src/main/java/com/mrxu/framework/boot/feign/FeignRequestInterceptor.java

@@ -19,18 +19,17 @@ public class FeignRequestInterceptor implements RequestInterceptor {
      */
     @Override
     public void apply(RequestTemplate requestTemplate) {
-        RpcRequestInfo requestInfo = RpcRequestInfo.get();
-        if(StringUtils.isNotBlank(requestInfo.getIp())){
-            requestTemplate.header(HeaderConstant.IP,requestInfo.getIp());
+        if(StringUtils.isNotBlank(RpcRequestInfo.getIp())){
+            requestTemplate.header(HeaderConstant.IP,RpcRequestInfo.getIp());
         }
-        if(StringUtils.isNotBlank(requestInfo.getMerchantId())){
-            requestTemplate.header(HeaderConstant.MERCHANT_ID,requestInfo.getMerchantId());
+        if(StringUtils.isNotBlank(RpcRequestInfo.getMerchantId())){
+            requestTemplate.header(HeaderConstant.MERCHANT_ID,RpcRequestInfo.getMerchantId());
         }
-        if(StringUtils.isNotBlank(requestInfo.getUsername())){
-            requestTemplate.header(HeaderConstant.USER_NAME,requestInfo.getUsername());
+        if(StringUtils.isNotBlank(RpcRequestInfo.getUsername())){
+            requestTemplate.header(HeaderConstant.USER_NAME,RpcRequestInfo.getUsername());
         }
-        if(StringUtils.isNotBlank(requestInfo.getTrackId())){
-            requestTemplate.header(HeaderConstant.TRACK_ID,requestInfo.getTrackId());
+        if(StringUtils.isNotBlank(RpcRequestInfo.getTrackId())){
+            requestTemplate.header(HeaderConstant.TRACK_ID,RpcRequestInfo.getTrackId());
         }
     }
 }

+ 65 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/irule/MetadataAwarePredicate.java

@@ -0,0 +1,65 @@
+package com.mrxu.framework.boot.irule;
+
+import com.mrxu.framework.boot.util.SpringApplicationContextUtil;
+import com.netflix.loadbalancer.AbstractServerPredicate;
+import com.netflix.loadbalancer.IRule;
+import com.netflix.loadbalancer.PredicateKey;
+import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 功能概要:[服务合法判断逻辑] <br>
+ *
+ * @author zzt
+ * @date 2020/10/15
+ */
+@Slf4j
+public class MetadataAwarePredicate extends AbstractServerPredicate {
+
+
+    public MetadataAwarePredicate(IRule iRule){
+        super(iRule);
+    }
+
+    /**
+     * 过滤原信息的逻辑
+     * @param input 被选中的潘德对象
+     * @return 是否合法
+     */
+    @Override
+    public boolean apply(PredicateKey input) {
+        if(input == null || !(input.getServer() instanceof DiscoveryEnabledServer)){
+            return false;
+        }
+        //是注册中心中的服务时,判断过滤逻辑
+        EurekaInstanceConfigBean eurekaInstanceConfigBean = SpringApplicationContextUtil.getBean(EurekaInstanceConfigBean.class);
+        if(eurekaInstanceConfigBean == null){
+            return false;
+        }
+        DiscoveryEnabledServer server = (DiscoveryEnabledServer) input.getServer();
+        Map<String, String> currentMetaDataInfo = eurekaInstanceConfigBean.getMetadataMap();
+        Map<String, String> metadata = server.getInstanceInfo().getMetadata();
+        if(currentMetaDataInfo==null||currentMetaDataInfo.size()<=0||metadata==null||metadata.size()<=0){
+            return false;
+        }
+        Set<Map.Entry<String, String>> curEntries = currentMetaDataInfo.entrySet();
+        Iterator<Map.Entry<String, String>> curit = curEntries.iterator();
+        while(curit.hasNext()){
+            Map.Entry<String, String> entry = curit.next();
+            if("management.port".equalsIgnoreCase(entry.getKey())){
+                continue;
+            }
+            String fetchValue = metadata.get(entry.getKey());
+            if(StringUtils.isBlank(fetchValue)||!fetchValue.equals(entry.getValue())){
+                return false;
+            }
+        }
+        return true;
+    }
+}

+ 50 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/irule/MetadataAwareRule.java

@@ -0,0 +1,50 @@
+package com.mrxu.framework.boot.irule;
+
+import com.netflix.loadbalancer.AbstractServerPredicate;
+import com.netflix.loadbalancer.AvailabilityPredicate;
+import com.netflix.loadbalancer.CompositePredicate;
+import com.netflix.loadbalancer.ZoneAvoidancePredicate;
+import com.netflix.loadbalancer.ZoneAvoidanceRule;
+
+/**
+ * 功能概要:[原信息过滤器,根据原信息过滤合法的服务,可用于开发调试和版本过滤] <br>
+ *
+ * @author zzt
+ * @date 2020/10/15
+ */
+public class MetadataAwareRule extends ZoneAvoidanceRule {
+
+    /**
+     * 过滤服务逻辑
+     */
+    private CompositePredicate compositePredicate;
+
+    public MetadataAwareRule() {
+        super();
+        ZoneAvoidancePredicate zonePredicate = new ZoneAvoidancePredicate(this,null);
+        AvailabilityPredicate availabilityPredicate = new AvailabilityPredicate(this,null);
+        MetadataAwarePredicate metadataAwarePredicate = new MetadataAwarePredicate(this);
+        compositePredicate = createCompositePredicate(metadataAwarePredicate,zonePredicate, availabilityPredicate);
+    }
+
+    @Override
+    public AbstractServerPredicate getPredicate() {
+        return compositePredicate;
+    }
+
+    /**
+     * 优先p0选择,再使用原始的选择逻辑
+     * @param p0 原信息选择
+     * @param p1 地区地域
+     * @param p2 可用服务
+     * @return 组合选择逻辑
+     */
+    private CompositePredicate createCompositePredicate(MetadataAwarePredicate p0,ZoneAvoidancePredicate p1, AvailabilityPredicate p2) {
+        return CompositePredicate.withPredicates(p0)
+                .addFallbackPredicate(CompositePredicate.withPredicates(p1,p2).build())
+                .addFallbackPredicate(p2)
+                .addFallbackPredicate(AbstractServerPredicate.alwaysTrue())
+                .build();
+    }
+
+}

+ 88 - 0
framework-boot/src/main/java/com/mrxu/framework/boot/util/SpringApplicationContextUtil.java

@@ -0,0 +1,88 @@
+package com.mrxu.framework.boot.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+/**
+ * 工具类获取bean对象
+ */
+@Component
+@Slf4j
+public class SpringApplicationContextUtil implements ServletContextListener,ApplicationContextAware{
+	
+	private static ApplicationContext springContext;
+	
+	public SpringApplicationContextUtil() {
+		super();
+	}
+	
+	@Override
+	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
+		if(springContext==null) {
+			springContext = arg0;
+		}
+	}
+
+	@Override
+	public void contextDestroyed(ServletContextEvent arg0) {
+		
+	}
+
+	@Override
+	public void contextInitialized(ServletContextEvent event) {
+		springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
+	}
+	
+	public static ApplicationContext getApplicationContext() {
+		return springContext;
+	}
+	
+	public static String getContextId() {
+		return springContext.getId();
+	}
+
+	public static String getApplicationName() {
+		String contextId = getContextId();
+		if(!StringUtils.isEmpty(contextId)) {
+			String[] splits = contextId.split(":");
+			if(splits.length>0) {
+				return splits[0];
+			}
+		}
+		return "";
+	}
+	
+	public static <T> T getBean(Class<T> clazz){
+		return springContext.getBean(clazz);
+	}
+	
+	@SuppressWarnings("unchecked")
+	public static <T> T getBean(String name) {
+		return (T) springContext.getBean(name);
+	}
+	
+	@SuppressWarnings("unchecked")
+	public static <T> T getBeanByClassName(String className) {
+		Class<T> clazz = null;
+		try {
+			clazz = (Class<T>) Class.forName(className);
+		}catch (Exception e) {
+			e.printStackTrace();
+			log.error("class not fount"+className);
+		}
+		return springContext.getBean(clazz);
+	}
+	
+	public static <T> T getBean(String string, Class<T> clazz) {
+		return (T)springContext.getBean(string, clazz);
+	}
+
+}

+ 2 - 1
framework-boot/src/main/resources/META-INF/spring.factories

@@ -1,4 +1,5 @@
 # Auto Configure
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 com.mrxu.framework.boot.config.FeignAutoConfiguration,\
-com.mrxu.framework.boot.config.WebMvcConfig
+com.mrxu.framework.boot.config.WebMvcConfig,\
+com.mrxu.framework.boot.config.MetaFilterAutoConfiguration