dubbo filter实现参数透传
2019-11-13 本文已影响0人
LJasperliet
- 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();
}
}
}
- 有的时候我们不想每次调用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了。
- 如何使filter生效
我们自定义filter话,需要在resource下创建 /META-INFO/dubbo/com.alibaba.dubbo.rpc.Filter
文件内容为
helloFilter=com.fcbox.mall.item.MyFilter
image.png
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