001-dubbo基礎-001-服務化最佳實踐、異常處理邏輯
1、參看地址
http://dubbo.apache.org/zh-cn/
2、服務化最佳實踐
分包
建議將服務介面、服務模型、服務異常等均放在 API 包中,因為服務模型和異常也是 API 的一部分,這樣做也符合分包原則:重用釋出等價原則(REP),共同重用原則(CRP)。
如果需要,也可以考慮在 API 包中放置一份 Spring 的引用配置,這樣使用方只需在 Spring 載入過程中引用此配置即可。配置建議放在模組的包目錄下,以免衝突,如:com/alibaba/china/xxx/dubbo-reference.xml
。
粒度
服務介面儘可能大粒度,每個服務方法應代表一個功能,而不是某功能的一個步驟,否則將面臨分散式事務問題,Dubbo 暫未提供分散式事務支援。
服務介面建議以業務場景為單位劃分,並對相近業務做抽象,防止介面數量爆炸。
不建議使用過於抽象的通用介面,如:Map query(Map)
,這樣的介面沒有明確語義,會給後期維護帶來不便。
版本
每個介面都應定義版本號,為後續不相容升級提供可能,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />
。
建議使用兩位版本號,因為第三位版本號通常表示相容升級,只有不相容時才需要變更服務版本。
當不相容時,先升級一半提供者為新版本,再將消費者全部升為新版本,然後將剩下的一半提供者升為新版本。
相容性
服務介面增加方法,或服務模型增加欄位,可向後相容,刪除方法或刪除欄位,將不相容,列舉型別新增欄位也不相容,需通過變更版本號升級。
各協議的相容性不同,參見:服務協議
列舉值
如果是完備集,可以用 Enum
,比如:ENABLE
, DISABLE
。
如果是業務種類,以後明顯會有型別增加,不建議用 Enum
,可以用 String
代替。
如果是在返回值中用了 Enum
,並新增了 Enum
值,建議先升級服務消費方,這樣服務提供方不會返回新值。
如果是在傳入引數中用了 Enum
,並新增了 Enum
序列化
服務引數及返回值建議使用 POJO 物件,即通過 setter
, getter
方法表示屬性的物件。
服務引數及返回值不建議使用介面,因為資料模型抽象的意義不大,並且序列化需要介面實現類的元資訊,並不能起到隱藏實現的意圖。
服務引數及返回值都必需是傳值呼叫,而不能是傳引用呼叫,消費方和提供方的引數或返回值引用並不是同一個,只是值相同,Dubbo 不支援引用遠端物件。
異常
建議使用異常彙報錯誤,而不是返回錯誤碼,異常資訊能攜帶更多資訊,並且語義更友好。
如果擔心效能問題,在必要時,可以通過 override 掉異常類的 fillInStackTrace()
方法為空方法,使其不拷貝棧資訊。
查詢方法不建議丟擲 checked 異常,否則呼叫方在查詢時將過多的 try...catch
,並且不能進行有效處理。
服務提供方不應將 DAO 或 SQL 等異常拋給消費方,應在服務實現中對消費方不關心的異常進行包裝,否則可能出現消費方無法反序列化相應異常。
呼叫
不要只是因為是 Dubbo 呼叫,而把呼叫 try...catch
起來。try...catch
應該加上合適的回滾邊界上。
Provider 端需要對輸入引數進行校驗。如有效能上的考慮,服務實現者可以考慮在 API 包上加上服務 Stub 類來完成檢驗。
3、異常處理邏輯
dubbo的異常處理類是com.alibaba.dubbo.rpc.filter.ExceptionFilter 類,歸納下對異常的處理分為下面幾類:
1)如果provider實現了GenericService介面,直接丟擲
2)如果是checked異常,直接丟擲
3)在方法簽名上有宣告,直接丟擲
4)異常類和介面類在同一jar包裡,直接丟擲
5)是JDK自帶的異常,直接丟擲
6)是Dubbo本身的異常,直接丟擲
7)否則,包裝成RuntimeException拋給客戶端【為了防止客戶端反序列化失敗】