热爱技术,追求卓越
不断求索,精益求精

扩展dubbo功能,springboot项目轻松实现自定义拦截器(dubbo Filter)

dubbo是一个特别棒的soa框架,但是有时候我们会考虑对其进行扩展,实现一些自定义的功能。今天我们就来简单说说通过dubbo提供的com.alibaba.dubbo.rpc.Filter接口实现自定义的拦截器,扩展dubbo的功能。

dubbo Filter是责任链模式的一种实现方式,类似于servlet中的filter、mybatis中的plugin等都使用了责任链模式,只是各自实现的方式有些差异,但都能达到异曲同工之妙。

我们通常会用dubbo的Filter来实现一些比较有意思的功能,比如在服务消费方(consumer)实现一个本地缓存、在服务提供方(Provider)实现日志记录、耗时最终、异步上报等。

此处以服务提供方实现日志记录为例:

package cn.lovecto.promotion.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.fastjson.JSON;

/**
 * 日志过滤器
 *
 */
public class DubboLogFilter implements Filter {

    protected static final Logger LOG = LoggerFactory.getLogger("dubbo");

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation)
            throws RpcException {
        Object args[] = invocation.getArguments();
        String argsJson = JSON.toJSONString(args);
        long start = System.currentTimeMillis();
        try {
            return invoker.invoke(invocation);
        } catch (RpcException re) {
            LOG.error(String.format("Duubo rpc error, args:[ {} ].", argsJson), re);
            throw re;
        } catch (Throwable e) {
            LOG.error(String.format("Duubo rpc error, args:[ {} ].", argsJson), e);
            throw new RpcException("Dubbo server uncaught exception!", e);
        } finally {
            long spend = (System.currentTimeMillis() - start);
            int clientPort = RpcContext.getContext().getRemotePort();
            //获取调用方IP地址
            String clientIP = RpcContext.getContext().getRemoteHost();
            //记录日志
            LOG.info(
                    "DubboRPC info: API[ {} ], method[ {} ], args[ {} ], spendTime[ {} ms ], clientIp[ {} ], clientPort[ {} ].",
                    invoker.getInterface().getSimpleName(),
                    invocation.getMethodName(), argsJson, spend, clientIP,
                    clientPort);
        }
    }
}

代码写好了,由于我们的项目是基于springboot的,我们在src/main/resources创建META-INF/dubbo目录,在src/main/resources/META-INF/dubbo新建一个文件名“com.alibaba.dubbo.rpc.Filter”的文件,里面的内容如下:

dubboLogFilter=cn.lovecto.promotion.filter.DubboLogFilter

我的dubbo相关的配置是放到res目录中的,有两个文件,dubbo-interfaces.xml和dubbo.properties。springboot的相关配置类如下:

@Configuration
@PropertySource("file:res/dubbo.properties")
@ImportResource({ "file:res/dubbo-interfaces.xml" })
public class DubboConfig {
}

dubbo.properties文件如下:

dubbo.consumer.name=service_promotion
dubbo.zookeeper.address=zookeeper://172.17.0.2:2181
dubbo.timeout=20000

dubbo.group=test
dubbo.version=0.0.1

dubbo-interfaces.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://code.alibabatech.com/schema/dubbo 
         http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="${dubbo.consumer.name}"></dubbo:application>
    <!-- 使用zookeeper注册中心暴露服务地址 -->  
    <dubbo:registry address="${dubbo.zookeeper.address}" check="false" protocol="zookeeper"></dubbo:registry>
    <dubbo:provider port="-1" filter="dubboLogFilter" retries="0" />

    <!-- 要暴露的服务接口  -->  
    <dubbo:service group="service_promotion" version="${dubbo.version}" interface="cn.lovecto.api.IPageQueryService" ref="pageQueryServiceImpl" />

</beans>

dubbo-interfaces.xml中filter=”dubboLogFilter”就是我们刚刚上文提到的拦截器。

赞(1)
未经允许不得转载:LoveCTO » 扩展dubbo功能,springboot项目轻松实现自定义拦截器(dubbo Filter)

热爱技术 追求卓越 精益求精