聊聊dubbo的Filter

本文聚焦于dubbo的Filter和ProtocolFilterWrapper。Filter定义了invoke、onResponse等方法及Listener接口,其invoke返回的Result有抽象类及子类。ProtocolFilterWrapper实现Protocol接口,定义的CallbackRegistrationInvoker类实现Invoker接口,invoke方法会遍历filters回调onResponse。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要研究一下dubbo的Filter

Filter

dubbo-2.7.2/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java

@SPI
public interface Filter {
    /**
     * Does not need to override/implement this method.
     */
    Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;

    /**
     * Filter itself should only be response for passing invocation, all callbacks has been placed into {@link Listener}
     *
     * @param appResponse
     * @param invoker
     * @param invocation
     * @return
     */
    @Deprecated
    default Result onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
        return appResponse;
    }

    interface Listener {

        void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation);

        void onError(Throwable t, Invoker<?> invoker, Invocation invocation);
    }

}
复制代码
  • Filter定义了invoke、onResponse方法,另外还定义了Listener接口,该接口定义了onResponse、onError方法

ProtocolFilterWrapper

dubbo-2.7.2/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java

public class ProtocolFilterWrapper implements Protocol {

    private final Protocol protocol;

    public ProtocolFilterWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }



    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        Invoker<T> last = invoker;
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);

        if (!filters.isEmpty()) {
            for (int i = filters.size() - 1; i >= 0; i--) {
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                last = new Invoker<T>() {

                    @Override
                    public Class<T> getInterface() {
                        return invoker.getInterface();
                    }

                    @Override
                    public URL getUrl() {
                        return invoker.getUrl();
                    }

                    @Override
                    public boolean isAvailable() {
                        return invoker.isAvailable();
                    }

                    @Override
                    public Result invoke(Invocation invocation) throws RpcException {
                        Result asyncResult;
                        try {
                            asyncResult = filter.invoke(next, invocation);
                        } catch (Exception e) {
                            // onError callback
                            if (filter instanceof ListenableFilter) {
                                Filter.Listener listener = ((ListenableFilter) filter).listener();
                                if (listener != null) {
                                    listener.onError(e, invoker, invocation);
                                }
                            }
                            throw e;
                        }
                        return asyncResult;
                    }

                    @Override
                    public void destroy() {
                        invoker.destroy();
                    }

                    @Override
                    public String toString() {
                        return invoker.toString();
                    }
                };
            }
        }

        return new CallbackRegistrationInvoker<>(last, filters);
    }

    @Override
    public int getDefaultPort() {
        return protocol.getDefaultPort();
    }

    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
        return protocol.export(buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER));
    }

    @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
            return protocol.refer(type, url);
        }
        return buildInvokerChain(protocol.refer(type, url), REFERENCE_FILTER_KEY, CommonConstants.CONSUMER);
    }

    @Override
    public void destroy() {
        protocol.destroy();
    }

    static class CallbackRegistrationInvoker<T> implements Invoker<T> {

        private final Invoker<T> filterInvoker;
        private final List<Filter> filters;

        public CallbackRegistrationInvoker(Invoker<T> filterInvoker, List<Filter> filters) {
            this.filterInvoker = filterInvoker;
            this.filters = filters;
        }

        @Override
        public Result invoke(Invocation invocation) throws RpcException {
            Result asyncResult = filterInvoker.invoke(invocation);

            asyncResult.thenApplyWithContext(r -> {
                for (int i = filters.size() - 1; i >= 0; i--) {
                    Filter filter = filters.get(i);
                    // onResponse callback
                    if (filter instanceof ListenableFilter) {
                        Filter.Listener listener = ((ListenableFilter) filter).listener();
                        if (listener != null) {
                            listener.onResponse(r, filterInvoker, invocation);
                        }
                    } else {
                        filter.onResponse(r, filterInvoker, invocation);
                    }
                }
                return r;
            });

            return asyncResult;
        }

        @Override
        public Class<T> getInterface() {
            return filterInvoker.getInterface();
        }

        @Override
        public URL getUrl() {
            return filterInvoker.getUrl();
        }

        @Override
        public boolean isAvailable() {
            return filterInvoker.isAvailable();
        }

        @Override
        public void destroy() {
            filterInvoker.destroy();
        }
    }
}
复制代码
  • ProtocolFilterWrapper实现了Protocol接口,它定义了一个静态类CallbackRegistrationInvoker,该类实现了Invoker接口,其invoke方法首先会调用filterInvoker的invoke方法获取asyncResult,之后通过thenApplyWithContext注册rpc调用完成时的回调,这里会挨个遍历filters,回调每个filter的onResponse方法

小结

  • Filter定义了invoke、onResponse方法,另外还定义了Listener接口,该接口定义了onResponse、onError方法
  • Filter定义的invoke方法返回的Result有个抽象类为AbstractResult,而AbstractResult有几个子类,分别为AppResponse、AsyncRpcResult(替代原来的RpcResult)
  • ProtocolFilterWrapper定义了一个静态类CallbackRegistrationInvoker,该类实现了Invoker接口,其invoke方法首先会调用filterInvoker的invoke方法获取asyncResult,之后通过thenApplyWithContext注册rpc调用完成时的回调,这里会挨个遍历filters,回调每个filter的onResponse方法

doc

转载于:https://juejin.im/post/5d07acc0f265da1b6d40261a

<think>嗯,用户想了解如何在Dubbo中实现自定义Filter。首先,我需要回忆一下DubboFilter机制。DubboFilter可以拦截RPC调用,进行各种处理,比如日志、鉴权、限流等。用户可能希望自己添加一些逻辑,比如记录访问日志或者权限验证。 根据系统指令,我需要确保回答结构清晰,分步骤说明。首先应该介绍实现自定义Filter的步骤,然后给出示例代码,再说明配置方式。还要注意引用中的资料,比如引用3提到扩展自定义过滤器,引用4提到Filter的应用场景,比如参数校验、认证授权等。 用户可能需要具体的代码示例,所以应该提供一个实现Filter接口的类,比如实现org.apache.dubbo.rpc.Filter接口,并重写invoke方法。然后配置这个Filter,可以通过XML或者注解方式。引用2中的XML配置例子<dubbo:filter ref="rbacAuthFilter"/>可以作为参考。 还要注意DubboFilter生效范围,是服务提供者还是消费者端,或者同时配置。可能需要提醒用户如果要在全局生效,需要在consumer和provider都配置,如引用1中的配置consumer的filter列表。 另外,用户可能关心如何确保自定义Filter被正确加载,需要提到META-INF/dubbo/org.apache.dubbo.rpc.Filter文件中的配置,这点在引用3中有类似的自定义扩展说明。 可能还需要提到@Activate注解的使用,指定group为provider或consumer,这样Dubbo会自动激活对应的Filter。同时,需要确保依赖的版本兼容性,如引用5提到的版本问题,避免因版本不匹配导致类找不到的问题。 最后,生成相关问题时要围绕自定义Filter的实现、配置、应用场景、调试和生效范围等方面,帮助用户进一步了解相关知识。</think>### 如何在Dubbo中实现自定义Filter #### 一、实现步骤 1. **定义Filter类** 继承`org.apache.dubbo.rpc.Filter`接口并实现`invoke`方法,通过`@Activate`注解指定生效场景(服务提供方/消费方): ```java import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.*; @Activate(group = {"provider", "consumer"}) // 同时作用于服务提供方和消费方 public class CustomFilter implements Filter { @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { System.out.println("请求参数: " + Arrays.toString(invocation.getArguments())); Result result = invoker.invoke(invocation); // 执行后续调用链 System.out.println("响应结果: " + result.getValue()); return result; } } ``` 2. **SPI配置** 在`META-INF/dubbo/org.apache.dubbo.rpc.Filter`文件中注册Filter(需UTF-8编码): ```text customFilter=com.example.CustomFilter ``` 3. **XML配置方式** 在服务提供方或消费方的Spring配置中显式声明(可选): ```xml <!-- 单服务生效 --> <dubbo:service interface="com.example.DemoService" filter="customFilter" /> <!-- 全局生效 --> <dubbo:provider filter="customFilter"/> <dubbo:consumer filter="customFilter"/> ``` #### 二、核心机制 - **Filter链式调用**:Dubbo通过责任链模式组织多个Filter,执行顺序由`@Activate`的`order`参数控制(值越小优先级越高) - **上下文透传**:通过`RpcContext.getContext()`可获取或修改请求上下文参数,实现跨Filter数据传递 - **异常处理**:在Filter中捕获`RpcException`可实现统一错误码转换或熔断逻辑 #### 三、典型应用场景 1. **安全控制** ```java public Result invoke(Invoker<?> invoker, Invocation invocation) { String token = invocation.getAttachment("authToken"); if (!validateToken(token)) { throw new RpcException("鉴权失败"); } return invoker.invoke(invocation); } ``` 2. **性能监控** 统计接口耗时并上报监控系统: ```java long start = System.currentTimeMillis(); Result result = invoker.invoke(invocation); long cost = System.currentTimeMillis() - start; Metrics.report(invocation.getMethodName(), cost); ``` #### 四、注意事项 1. **版本兼容性**:不同Dubbo版本对Filter的加载机制有差异,需参考官方文档[^5] 2. **资源释放**:在Filter中创建的资源(如数据库连接)需在`result.whenCompleteWithContext()`中确保释放 3. **配置覆盖**:服务级配置会覆盖全局配置,可通过`<dubbo:reference filter="-default" />`禁用默认Filter链 [^1]: Dubbo官方文档建议通过`filter`参数显式指定生效范围 [^3]: Filter扩展需遵循SPI机制规范 [^4]: 自定义Filter应避免阻塞操作以保证调用链路性能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值