【問題經驗】dubbo回聲測試異常(NumberFormatException:null)

現象

     在用dubbo回聲測試機制做回聲測試時返回異常信息"NumberFormatException:null"

cause: org.apache.dubbo.remoting.RemotingException: java.util.concurrent.CompletionException: java.lang.NumberFormatException: null java.util.concurrent.CompletionException: java.lang.NumberFormatException: null at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292) 

分析

     異常是RemotingException說明不是消費者端拋的,大概率是提供者端拋的異常。因爲在測試環境必現,所以直接用debug調試跟蹤了一下代碼,發現拋異常的地方是在org.apache.dubbo.monitor.support.MonitorFilter.MonitorListener#onResponse位置

斷點位置invocation.getAttachment(MONITOR_FILTER_START_TIME)返回值是null。

     再跟一下源碼發現org.apache.dubbo.monitor.support.MonitorFilter#invoke裏對MONITOR_FILTER_START_TIME賦值

    停下來思考下,回聲測試這個地方爲啥沒有設置值?我們知道回聲測試是利用EchoFilter來實現,EchoFilter發現請求對方法名是"$echo"就直接返回接口並且終止Dubbo的Invoker鏈(即後面的Filter以及真正的服務方法都不會執行到)。很巧,EchoFilter優先級比MonitorFilter優先級高,也就是回聲測試MonitorFilter沒有執行到,也就沒用給invocation設置"MONITOR_FILTER_START_TIME"。 但是在invoke完成後會再次遍歷所有的Filter,如果是ListenableFilter則執行org.apache.dubbo.rpc.Filter.Listener#onResponse。MonitorFilter也繼承了ListenableFilter從而中招。

方案

    最好是dubbo源碼修改一下。再不修改源碼的情況下,可用以下兩種方式規避:

    1 去除monitor參數

     筆者查看源碼發現只有URL中帶了monitor參數纔會執行到拋異常的地方,所以只要我們關閉monitor特性即可。

    2 重寫MonitorFilter

  • 自定義CustomMonitorFilter繼承MonitorFilter,在拋異常的位置加一個判斷
  • 配置Dubbo SPI加載customMonitor=xx.xx.xx.CustomMonitorFilter
  • 在dubbo:provider的配置上加上"filter=-monitor,customMonitor"(提供者去除默認的MonitorFilter,加上自定義的CustomMonitorFilter)

引申思考

     再思考下Dubbo這樣實現的合理性,"只有被執行了Filter,它的listener才被執行" 這樣是不是更合理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章