推薦閱讀:1. 字節跳動的面試難嗎?我該如何應對?
最近一個小夥伴在開發一款小而美的應用程序性能監控框架(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中,DubboProfilerFilterTemplate類實現了org.apache.dubbo.rpc.Filter接口。
這是一個模板類,定義了Filter.invoke()方法的通用實現,由於具體收集profile時,針對Provider和Consumer需要不同的收集器,這裏通過其子類DubboProviderProfilerFilter和DubboConsumerProfilerFilter分別實現。
上述的類關係可通過下圖描述:
DubboProfilerFilterTemplate大致實現如下:
兩個實現類如下:
寫完實現類後,需要在項目的resources目錄下配置Dubbo的擴展文件。
在resources下創建META-INF/dubbo/org.apache.dubbo.rpc.Filter文件,內容如下:
這樣Dubbo就可以掃描到自定義的擴展點。
03 自定義Filter的使用
接下來需要將自定義的擴展點配置到Dubbo中,告訴Dubbo我要使用這個Filter,分別在Provider和Consumer中配置:
首先看一下Provider:
說明:default代表已有的擴展點,dubboProviderProfiler是我們自定義的擴展點,這樣配置表示我們自定義的擴展點在已有的擴展點之後執行。
同樣,在Consumer端配置自定義擴展點:
04 自定義擴展點的自動激活
從上文得知,我們自定義的擴展點必須要修改配置才能生效,這樣一來,是有代碼侵入的。那麼,能不能引入pepper-metrics-dubbo的jar包後,不用修改配置,就直接生效呢?
答案是:當然可以!
pepper-metrics-dubbo使用了Dubbo提供的@Activate機制。這個註解可用於類或方法上。其作用是可以讓Dubbo自動激活此擴展,從而簡化配置。
以Provider爲案例,看一下這個東西在pepper-metrics-dubbo裏是咋用的。
首先,如果只配置@Activate註解,不自定義其屬性的話,會無條件自動激活所有擴展點。在我們的項目中,就是會同時激活DubboConsumerProfilerFilter和DubboProviderProfilerFilter。
但在我們的需求中是不能同時激活兩個擴展點的。如果同時激活,服務提供方和調用方都會同時調用兩個擴展點。而我們需要的是提供方調用Provider,調用方調用Consumer。
這可以通過group來實現。定義了group之後,就只對特定的group激活了。
在Filter中,有兩個group:
定義爲PROVIDER就只對提供方生效,定義爲CONSUMER就只對調用方生效,也可以同時定義,那就同時生效。
這樣一來,只需要依賴pepper-metrics-dubbo包即可激活擴展點了。