dubbo filter实现参数透传

在项目中转递参数通常是在接口中传递,然后在每个方法中接受这些参数处理。dubbo提供了rpc上下文可以实现设置和接受这些参数,实现我们的参数透传。(本文于2019年11在个人博客简书发表)

1.RpcContext

利用RpcContext实现consumer和provicer参数传递例如:

消费端: RpcContext.getContext().setAttachment("bizId", "小程序");  //调用dubbo activityAdminFacade.queryExchangeActivitiesByOption(option);  服务端: @Override     public PageResult<ExchangeActivityDTO> queryExchangeActivitiesByOption(ActivityQueryOption option) { 	String userInfo = RpcContext.getContext().getAttachment("bizId"); }

实际上rpcContext也是用到了dubbo filter 特性。ConsumerContextFilter attachment中参数会直接带到invocation对象,传递至provider端。finaly中RpcContext.getContext().clearAttachments(); 每次调用会直接清除。所以需要我们每次调用dubbo服务接口前都要设置setAttachment。

@Activate(group = Constants.CONSUMER, order = -10000) public class ConsumerContextFilter implements Filter {      public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {         RpcContext.getContext()                 .setInvoker(invoker)                 .setInvocation(invocation)                 .setLocalAddress(NetUtils.getLocalHost(), 0)                 .setRemoteAddress(invoker.getUrl().getHost(),                                    invoker.getUrl().getPort());         if (invocation instanceof RpcInvocation) {             ((RpcInvocation)invocation).setInvoker(invoker);         }         try {             return invoker.invoke(invocation);         } finally {             RpcContext.getContext().clearAttachments();         }     }  }

2.有的时候我们不想每次调用dubbo接口都要去设置RpcContext。所以需要我们自己去实现定义一个dubbo filter。当然我们也可以直接修改源码哈哈(不推荐)

2.1 范围:一个线程上下文内

public class BizIdUtils {       private static final ThreadLocal<String> Cache             = new ThreadLocal<String>();       public static String getBizId() {         return Cache.get();     }       public static void setBizId(String bizId) {         Cache.set(bizId);     }       public static void clear() {        Cache.remove();     }   }
package com.test.dubbo;   public class TraceIdFilter implements Filter {       @Override     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {         String traceId = RpcContext.getContext().getAttachment("BizId");         if ( !StringUtils.isEmpty(BizId) ) {             // *) 从RpcContext里获取bizId并保存             BizIdUtils.setBizId(bizId);         } else {             // *) 交互前重新设置traceId, 避免信息丢失             RpcContext.getContext().setAttachment("bizId", BizIdUtils.getBizId());         }         // *) 实际的rpc调用         return invoker.invoke(invocation);     } }

BizIdUtils ThreadLocal就是用来保存当前线程的变量值。所以在一个线程上下文中,只需要在第一次设置RpcContext.setAttachment即可。比如web的一次请求。

2.2 范围:设置整个consumer端

public class MyFilter implements Filter {     @Override     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {           RpcContext.getContext().setAttachment("bizId", "电商");         Result result = invoker.invoke(invocation);                 return result;     } }

这样我们consumer端就不需再调用RpcContext了。

2.3 如何使filter生效
我们自定义filter的话,需要在resource下创建 /META-INFO/dubbo/com.alibaba.dubbo.rpc.Filter
文件内容为

helloFilter=com.fcbox.mall.item.MyFilter

dubbo filter实现参数透传

helloFilter为自定义的名称
然后
application.properties中配置
springboot:spring.dubbo.consumer.filter=helloFilter

spring dubbo需要我们自己去实现java配置,这个filter就存放在DubboProperties中consumerConfig中filter中:

@Configuration @EnableConfigurationProperties(DubboProperties.class) public class DubboAutoConfiguration {      @Autowired     private DubboProperties dubboProperties;      @Autowired     private Environment environment;      @Bean     public ApplicationConfig requestApplicationConfig() {         ApplicationConfig applicationConfig = dubboProperties.getApplication();         if(applicationConfig == null){             applicationConfig = new ApplicationConfig();         }         return applicationConfig;     }      @Bean     @Primary     public RegistryConfig requestRegistryConfig() {         RegistryConfig registryConfig = dubboProperties.getRegistry();         if(registryConfig == null){             registryConfig = new RegistryConfig();         }         return registryConfig;     }      @Bean     public ProtocolConfig requestProtocolConfig() {         ProtocolConfig protocolConfig = dubboProperties.getProtocol();          if(protocolConfig == null){             protocolConfig = new ProtocolConfig();         }          //获取启动参数,优先级最高         String host=environment.getProperty("server.address");         if(StringUtils.isNotEmpty(host)){             protocolConfig.setHost(host);         }           return protocolConfig;     }      @Bean     public MonitorConfig requestMonitorConfig() {         MonitorConfig monitorConfig = dubboProperties.getMonitor();         if(monitorConfig == null){             monitorConfig = new MonitorConfig();         }         return monitorConfig;     }          @Bean     public ProviderConfig requestProviderConfig(){         ProviderConfig providerConfig = dubboProperties.getProvider();         if(providerConfig == null){             providerConfig = new ProviderConfig();         }         return providerConfig;     }          @Bean     public ModuleConfig requestModuleConfig(){         ModuleConfig moduleConfig = dubboProperties.getModule();         if(moduleConfig == null){             moduleConfig = new ModuleConfig();         }         return moduleConfig;     }          @Bean     public MethodConfig requestMethodConfig(){         MethodConfig  methodConfig = dubboProperties.getMethod();         if(methodConfig == null){             methodConfig = new MethodConfig();         }         return methodConfig;     }          @Bean     public ConsumerConfig requestConsumerConfig(){         ConsumerConfig consumerConfig = dubboProperties.getConsumer();         if(consumerConfig == null){             consumerConfig = new ConsumerConfig();         }         return consumerConfig;     }  }  public class DubboProperties {      private String scan;      private ApplicationConfig application;      private RegistryConfig registry;      private ProtocolConfig protocol;      private MonitorConfig monitor;          private ProviderConfig provider;          private ModuleConfig module;          private MethodConfig method;          private ConsumerConfig consumer;

consumer配置类:com.alibaba.dubbo.config.ConsumerConfig

您可能还会对下面的文章感兴趣: