本文最后更新于:2022年6月27日 下午
目的
开发人员进行本地开发时,经常会出现接口调到k8s容器内的服务上,我们本地和k8s共用一个nacos服务.
根据调研,打算使用dubbo的自定义路由实现.本地服务调接口时,使用路由过滤掉k8s内部的provider地址,从而实现,本地consumer能够一直本地provider服务.
由于过滤了k8s内部实例的ip,因此需要,将此路由只能在本地生效,在k8s环境内失效,通过spring.profiles实现.
实现自定义路由
继承AbstractRouter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors;
@Slf4j public class IpRouter extends AbstractRouter {
public IpRouter(URL url) { super(url); }
@Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
if (!SpringContextUtil.isLocal()) { return invokers; } log.info(" before route :{},{}", invokers.size(), invokers); if (invokers.size() <= 1) { return invokers; }
Predicate<Invoker<T>> useLocalIP = str -> !str.getUrl().toServiceString().contains("10.0.80.9"); List<Invoker<T>> collect = invokers.stream().filter(useLocalIP).collect(Collectors.toList());
log.info(" after route:{},{}", collect.size(), collect); return collect; } }
|
实现RouterFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.cluster.Router; import org.apache.dubbo.rpc.cluster.RouterFactory;
@Activate(group = "consumer") public class IpRouterFactory implements RouterFactory {
@Override public Router getRouter(URL url) { return new IpRouter(url); } }
|
加载RouterFactory
在resources 目录下创建目录META-INF\dubbo
创建文件:org.apache.dubbo.rpc.cluster.RouterFactory,
值为:ip=com.wtt.demo.app.route.IpRouterFactory
解决只在本地生效
创建SpringContextUtil工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Service;
import java.util.Arrays; import java.util.function.Predicate;
@Slf4j @Service public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext context = null;
public static String[] getActiveProfileList() { return context.getEnvironment().getActiveProfiles(); }
public static Boolean isLocal() { String[] activeProfileList = getActiveProfileList(); Predicate<String> containsLocalProfile = m -> m.contains("local"); return Arrays.stream(activeProfileList).anyMatch(containsLocalProfile); }
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } }
|
reference