给Dubbo添砖加瓦:自定义Filter扩展点实现!

Dubbo源码解析:Dubbo过滤器 自定义Filter 我们先手动定义一个Filter,用来统计服务端每个接口的执行时间。 实现Filter接口 在resources/META-INF/dubbo文件夹下新建org.apache.dubbo.rpc.Filter文件 在org.apache.dubbo.rpc.Filter文件中写上Filter的路径 @Slf4j @Activate(group = PROVIDER) public class CostFilter implements Filter { @Override . 阅读详情

最近一个小伙伴在开发一款小而美的应用程序性能监控框架(Pepper-Metrics)。

其中一个需求,需要收集Dubbo在Provider端和Consumer端的接口响应性能数据,以便存储到DataSource中或提供给Printer使用。

在此背景下,我们需要对Provider端和Consumer端的每一次请求和响应进行监控。在Dubbo中,可以通过扩展org.apache.dubbo.rpc.Filter接口实现。

01  org.apache.dubbo.rpc.Filter介绍

Filter可以理解为调用过程拦截,每次方法调用该拦截器都会生效,扩展时需要注意对性能的影响。

用户定义的Filter默认在已有的Filter之后被执行。

02  Pepper-Metrics-Dubbo的Filter实现

在我们的项目中,这个子模块被命名为Pepper-Metrics-Dubbo,此模块的结构如下:

Pepper-Metrics-Dubbo
    |-src/main/java
        |-com.pepper.metrics.integration.dubbo
            |-DubboProfilerFilterTemplate
            |-DubboProviderProfilerFilter
            |-DubboConsumerProfilerFilter
    |-src/main/resources
        |-META-INF
            |-dubbo
                |-org.apache.dubbo.rpc.Filter

在Pepper-Metrics-Dubbo中,DubboProfilerFilterTemplate类实现了org.apache.dubbo.rpc.Filter接口。

这是一个模板类,定义了Filter.invoke()方法的通用实现,由于具体收集profile时,针对Provider和Consumer需要不同的收集器,这里通过其子类DubboProviderProfilerFilter和DubboConsumerProfilerFilter分别实现。

上述的类关系可通过下图描述:

 

DubboProfilerFilterTemplate大致实现如下:

public abstract class DubboProfilerFilterTemplate implements Filter {

    // Provider的收集器
    static final Stats PROFILER_STAT_IN = Profiler.Builder
            .builder()
            .name("app.dubbo.request.in")
            .build();
    // Consumer的收集器
    static final Stats PROFILER_STAT_OUT = Profiler.Builder
            .builder()
            .name("app.dubbo.request.out")
            .build();

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        // 省略... 一些必要的准备工作

        // 模板方法,before trace...
        beforeInvoke(tags);
        try {
            Result result = invoker.invoke(invocation);
            // 记录是否调用报错
            if (result == null || result.hasException()) {
                isError = true;
            }

            specialException = false;

            return result;
        } finally {
            if (specialException) {
                isError = true;
            }
            // 模板方法,after trace...
            afterInvoke(tags, begin, isError);
        }
    }

    abstract void afterInvoke(String[] tags, long begin, boolean isError);

    abstract void beforeInvoke(String[] tags);
}

 

两个实现类如下:

// Provider
@Activate(group = {PROVIDER})
public class DubboProviderProfilerFilter extends DubboProfilerFilterTemplate {
    @Override
    void afterInvoke(String[] tags, long begin, boolean isError) {
        // 记录响应实现
        PROFILER_STAT_IN.observe(System.nanoTime() - begin, TimeUnit.NANOSECONDS, tags);
        // 并发数递减
        PROFILER_STAT_IN.decConc(tags);
        // 记录错误数
        if (isError) {
            PROFILER_STAT_IN.error(tags);
        }
    }

    @Override
    void beforeInvoke(String[] tags) {
        // 并发数递增
        PROFILER_STAT_IN.incConc(tags);
    }
}

 

// Consumer
@Activate(group = {CONSUMER})
public class DubboConsumerProfilerFilter extends DubboProfilerFilterTemplate {
    @Override
    void afterInvoke(String[] tags, long begin, boolean isError) {
        PROFILER_STAT_OUT.observe(System.nanoTime() - begin, TimeUnit.NANOSECONDS, tags);
        PROFILER_STAT_OUT.decConc(tags);
        if (isError) {
            PROFILER_STAT_OUT.error(tags);
        }
    }

    @Override
    void beforeInvoke(String[] tags) {
        PROFILER_STAT_OUT.incConc(tags);
    }
}

写完实现类后,需要在项目的resources目录下配置Dubbo的扩展文件。

在resources下创建META-INF/dubbo/org.apache.dubbo.rpc.Filter文件,内容如下:

dubboProviderProfiler=com.pepper.metrics.integration.dubbo.DubboProviderProfilerFilter
dubboConsumerProfiler=com.pepper.metrics.integration.dubbo.DubboConsumerProfilerFilter

 

这样Dubbo就可以扫描到自定义的扩展点。

03  自定义Filter的使用

接下来需要将自定义的扩展点配置到Dubbo中,告诉Dubbo我要使用这个Filter,分别在Provider和Consumer中配置:

首先看一下Provider:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <dubbo:application name="demo-provider"/>

    <dubbo:registry address="multicast://224.5.6.7:1234"/>

    <bean id="demoService" class="com.pepper.metrics.sample.dubbo.spring.provider.DemoServiceImpl"/>

    <!-- 在这里配置自定义的扩展点 -->
    <dubbo:service filter="default,dubboProviderProfiler" interface="com.pepper.metrics.sample.dubbo.spring.api.DemoService" ref="demoService" />

</beans>

 

说明:default代表已有的扩展点,dubboProviderProfiler是我们自定义的扩展点,这样配置表示我们自定义的扩展点在已有的扩展点之后执行。

同样,在Consumer端配置自定义扩展点:<

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>

    <dubbo:application name="demo-consumer"/>

    <dubbo:registry address="multicast://224.5.6.7:1234"/>

    <!-- 在这里配置自定义的扩展点 -->
    <dubbo:reference filter="default,dubboConsumerProfiler" id="demoService" check="true" interface="com.pepper.metrics.sample.dubbo.spring.api.DemoService" />

</beans>

 

04  自定义扩展点的自动激活

从上文得知,我们自定义的扩展点必须要修改配置才能生效,这样一来,是有代码侵入的。那么,能不能引入pepper-metrics-dubbo的jar包后,不用修改配置,就直接生效呢?

答案是:当然可以!

pepper-metrics-dubbo使用了Dubbo提供的@Activate机制。这个注解可用于类或方法上。其作用是可以让Dubbo自动激活此扩展,从而简化配置。

以Provider为案例,看一下这个东西在pepper-metrics-dubbo里是咋用的。

@Activate(group = {PROVIDER}) // is here
public class DubboProviderProfilerFilter extends DubboProfilerFilterTemplate {
    @Override
    void afterInvoke(String[] tags, long begin, boolean isError) {
        // ...
    }

    @Override
    void beforeInvoke(String[] tags) {
        // ...
    }
}

 

首先,如果只配置@Activate注解,不自定义其属性的话,会无条件自动激活所有扩展点。在我们的项目中,就是会同时激活DubboConsumerProfilerFilter和DubboProviderProfilerFilter。

但在我们的需求中是不能同时激活两个扩展点的。如果同时激活,服务提供方和调用方都会同时调用两个扩展点。而我们需要的是提供方调用Provider,调用方调用Consumer。

这可以通过group来实现。定义了group之后,就只对特定的group激活了。

在Filter中,有两个group:

String PROVIDER = "provider";
String CONSUMER = "consumer";

 

定义为PROVIDER就只对提供方生效,定义为CONSUMER就只对调用方生效,也可以同时定义,那就同时生效。

这样一来,只需要依赖pepper-metrics-dubbo包即可激活扩展点了。

从DIY桌面CNC到工业机器人:手把手教你用LinuxCNC搭建自己的第一台数控系统(基于Xenomai实时补丁) 本文详细介绍了如何使用LinuxCNC和Xenomai实时补丁搭建高性价比的数控系统,从硬件选型到实时系统构建,再到HAL硬件抽象层实战和G代码加工,手把手教你打造从DIY桌面CNC到工业机器人的完整解决方案。 阅读详情

相关推荐

Docker环境下onlyOffice 7.5.1破解版部署全攻略(含ARM架构适配)

本文提供了在Docker环境中部署OnlyOffice 7.5.1破解版的完整实战指南。内容涵盖x86与ARM架构服务器的详细部署步骤、环境配置、持久化存储设置以及生产环境下的安全与性能优化。重点解决了ARM架构适配的常见问题,并分享了使用Docker Compose进行服务编排和日常维护的技巧,帮助用户快速搭建私有化文档协作平台。

redis7keeper的博客 353

Dubbo服务调用扩展点Filter的介绍与使用

Dubbo服务调用扩展点Filter的介绍与使用,如拦截、负载均衡、路由等

一名Java语言狂热分子。 6164

Android perfetto 简介

android linux 性能优化 原理及操作

求变,从思想开始 3480

Dubbo接口中的Filter

如果是http请求的话,filter很容易就能写出来,现在项目全部换成dubbo接口,也想使用拦截器进行统一操作预处理,就需要用到dubbo里的filter。 自定义的filter需要去实现org.apache.dubbo.rpc.Filter接口,同时实现接口里边的invoke方法。 具体步骤如下 1.编写filter类,该类实现org.apache.dubbo.rpc.Filter接口以及接口的invoke方法。 @Slf4j public class DubboFilter implements Fi

weixin_45614626的博客 1795

VS2019 从零构建 OSG+OSGEarth+OSGQt 开发环境实战指南

本文提供了一份详细的实战指南,指导开发者如何在Windows系统下使用VS2019从零开始编译和配置OSG、OSGEarth与OSGQt开发环境。文章涵盖了从环境准备、源码获取、CMake配置、Visual Studio编译到最终测试的完整流程,并分享了关键的避坑技巧,旨在帮助三维GIS与可视化开发者高效搭建稳定、可控的专业开发平台。

weixin_28826961的博客 367

CloudCompare 和 PCL:点云网格化分析与处理

点云网格化是将点云数据转化为规则网格的过程,其主要思想是将离散的点云投影到一个平面上,然后对该平面进行划分,形成一系列小区域。在点云网格化方面,PCL 提供了各种算法和工具,可以实现高效的点云网格化操作。以上示例代码中,首先加载了输入的点云数据,然后通过设置合适的网格化算法参数,如搜索半径和最大三角形边长等,执行了网格化操作,最后将网格化结果保存到输出文件中。以上示例代码中,首先加载了输入的点云数据,然后通过设置合适的网格化参数,如分辨率等,执行了网格化操作,最后将网格化结果保存到输出文件中。

TechPulseZ的博客 1291

dubbo复习:(18)服务端Filter

用来在服务响应返回到客户端之前进行额外处理。三、配置文件中指定Filter。二、SPI注入Filter。一、定义Filter。

amadeus_liu2的博客 535

C#串口通信从入门到精通(21)——一个串口多线程发送数据

本文详细介绍了串口通信中采用多线程发送串口数据的解决方案,由多年实战经验总结,绝对干货!

qq_34059233的博客 3690

dubbo org.apache.dubbo.rpc.Filter 不生效的原因

dubbo Filter 不生效

weixin_42554209的博客 1335

Dify之八添加各种在线大模型

Dify之八添加各种在线大模型

yilvyangguang520的博客 939

把 ABAP SQL 窗口函数讲透:从 OVER 到 LEAD、RANK 与累计分析

ABAP SQL窗口函数在不丢失明细记录的前提下,为每行数据提供组内统计和排名功能。它通过OVER子句定义计算窗口,支持三类函数:聚合型(AVG/SUM等)、排名型(ROW_NUMBER/RANK等)和取值型(LEAD/LAG)。相比GROUP BY会合并多行数据,窗口函数保留原始记录同时附加计算结果,特别适合需要保留明细又要展示统计信息的业务场景,如销售排名、客户分层分析等。语法核心是OVER子句,通过PARTITION BY分组,ORDER BY排序,可灵活定义计算范围。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1274

Dubbo源码

今天,我们从消费方发起调用开始介入,逐步分析Dubbo的每层模块的由来以及承担的职责,形成对Dubbo的整体了解,最后在 Dubbo 3.0.7 源码层面上标识出每个模块与工程的 Module 对号入座。一个简简单单的调用,居然有这么多需要关注的层次模块,即便是你自己写的RPC调用框架壮大成型后,代码层次结构设计以及每层可能遇到的问题,和 Dubbo 框架其实会有着相似的解决套路。

qq_33240556的博客 1239

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Dubbo Filter用法详解

Filter是Dubbo中使用较为频繁的组件,其作用在于对所指定的请求进行过滤,功能非常类似于AOP,可以实现诸如请求过滤器和全局异常捕获器等组件。本文首先会讲解Filter的用法,然后会从源码的角度讲解其实现原理。 1. 用法示例 对于Filter的划分,根据其面向的对象不同,可以分为service端和consumer端;根据其所作用的范围的不同,则可以分为单个服务过滤器(单个service或reference)和全局过滤器(整个provider或consumer)。Filter的指定方式主要有三种:

m0_67393295的博客 2024

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

十一:Apache Dubbo 之 Filter(二)filter加载机制以及系统中的默认的filter

//org.apache.dubbo.config.ServiceConfig#doExportUrlsFor1Protocol方法中 Exporter<?> exporter = PROTOCOL.export(wrapperInvoker); //org.apache.dubbo.qos.protocol.QosProtocolWrapper#export @Override public <T> Exporter<T> export(Inv

qq_36364521的博客 1359

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Dubbo—Filter剖析

你是湖光潋滟中一掠而过的飞鸟, 面对朝圣者的赞美, 沉醉在无止境的自诩中。 当暮色降临, 你化身迷途的羔羊, 被黑夜释意玩弄的惆怅, 无处安放的彷徨, 透过光和影的交织摸索前行。 遥望远方, 不一定灯火辉煌, 却一定诗意盎然。 ...

qq_30051265的博客 3566

十一、面向对象底层逻辑-Dubbo过滤器Filter接口

本文深入探讨了Dubbo框架中Filter接口的设计原理、核心实现及其在生产环境中的应用。Filter接口作为Dubbo服务治理的核心扩展点,通过责任链模式实现服务调用的拦截,支持日志记录、权限校验、性能监控等非业务功能的解耦与动态加载。文章详细解析了Filter接口的核心方法、内置Filter的功能及激活条件,并提供了自定义Filter的开发步骤和配置方法。此外,还介绍了Filter在生产级应用中的最佳实践,如全链路追踪、敏感参数脱敏和性能监控埋点。最后,文章分析了Filter接口的源码级实现,并提供了典

u013883798的博客 1553

dubbo-6:dubbo的拦截(过滤)机制

目录一、filter项目配置1、pom2、添加一个自定义类,并继承Filter3、进行配置二、在需要的项目引用pom引用consumerprovider三、注意1、需要在filter类上方添加@Activate注解并使用group指定生产端 消费端2、单独开发依赖 与很多框架一样,Dubbo也存在拦截(过滤)机制,可以通过该机制在执行目标程序前后执行我们指定 的代码。 Dubbo的Filter机制,是专门为服务提供方和服务消费方调用过程进行拦截设计的,每次远程方法执行,该拦截都会被执行。这样就为开发者提供

JoyceYoung的博客 1980

dubbo集成zipkin遇到的问题一【No such extension tracing for filterorg.apache.dubbo.rpc.Filter】

官方demo地址 dubbo集成zipkin官网的博客地址 问题概述 问题的异常大概是下面这样的,主要异常信息是Property 'filter' threw exception; nested exception is java.lang.IllegalStateException: No such extension tracing for filter/org.apache.dubbo.rpc.Filter,这个错误很明显,就是自定义的dubbo过滤器没有被加载到,然后就是找原因了。 Caused b

geinvse_seg的博客 2949

apache dubbo 2.7.3 源代码片段 - Protocol扩展的Filter机制

org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper public class ProtocolFilterWrapper implements Protocol { private final Protocol protocol; public ProtocolFilterWrapper(Protocol protocol) { if (protocol == null) { throw ne

~~简~~ 268

dubbo-filter

1、编写模块 dubbo-filter,引入 dubbo jar 包。文件名:org.apache.dubbo.rpc.Filter。4、在 demo-base 中引入该过滤器模块,进行测试。2、编写 filter 类,按照规范。在指定文件夹下创建指定文件名称的文件。包名:META-INF/dubbo。3、在配置文件中注册过滤器。

xingcsdnboke的博客 264

dubbo 自定义过滤器,打印接口调用信息

dubbo提供了web filter类似的com.alibaba.dubbo.rpc.Filter,这样,我们可以在dubbo提供的服务提供方和消费方都可以自定义过滤 器,从而可以获得方法调用的时间或参数、返回结果及异常信息。我们可以利用log打印出来。而且,这个过滤器机制,也是分布式跟踪系统的一部分。       下面代码实例是一个自定义过滤器例子,获得方法调用的参数、返回结果、执行时间及异...

weixin_34162695的博客 209

简易版Dubbo方法级性能监控(实现TP90、TP99)

一、具体要求 在真实业务场景中,经常需要对各个业务接口的响应性能进行监控(常用指标为:TP90、TP99) 通过扩展Dubbo的Filter(TPMonitorFilter),完成简易版本 Dubbo 接口方法级性能监控,记录下TP90、TP99请求的耗时情况 要求 说明 1 提供一个Dubbo服务,提供3个方法(eat、sleep、beatBeanBean),每方法都实现了随机休眠0-100ms 2 编写一个消费端程序,不断调用Dubbo服务的3个方法(建议利用线程池进行并行调用,

chuanchengdabing的博客 1581

基于dubbo的filter过滤器实现微服务日志追踪,以及实现原理

dubbo-filter的使用与注册原理,实现简单的日志流水号追踪与打印,基于此也可以拓展其他微服务管理功能

一只皮卡狗的博客 2438

Dubbo捕获提供者自定义异常(设置filter,声明自定义异常,自定义DubboExceptionFilter并设置filter)

<dubbo:provider delay="${dubbo.provider.delay}" retries="0" filter="-exception" />

1734

SpringCloud+Dubbo实现自定义Filter,关键配置避免启动过滤器无效

直接上代码,服务提供方 package com.weifor.xx.api.dubbo; import com.weifor.util.WeiFor; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.*; im

PangSir的专栏 1837

手打RPC- 拦截器与负载均衡

继续上篇内容,本篇讲解三部分内容,分别是拦截器,负载均衡,以及服务降级。 一. 拦截器 定义RpcFilter 接口,提供对请求对象和响应对象的处理 public interface RpcFilter { Object filterRequest(Object params); Object filterResponse(Object result); /** * 是否支持服务端过滤 * @return */ default boolea

起风 566
上一篇: 我说精通字符串,面试官竟然问我Java中的String有没有长度限制?
下一篇: 补码、反码、原码、位运算傻傻分不清?
加班不秃顶
博客等级 码龄7年 1822粉丝 599原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值