使用Dubbo、JSF等RPC框架時,對於異常的處理


無論是Dubbo還是JSF等RPC框架,一般都會把接口分為2部分:

1,服務端(provider)

2,客戶端(consumer)

 

由於,客戶端與服務端可能不在同一個應用中,所以客戶端一般在調用服務端的接口時,通常會返回一個結果實體,來標明這一次請求操作是否成功。

例如:

  

public class BaseResultDto<T> {

    /**
     * 是否操作成功
     */
    private boolean success;

    /**
     * 提示信息
     */
    private String msg;
    /**
     * 操作結果
     */
    private T result;
}

 

客戶端在拿到這個實體后,可以明確得知,這一次操作是否成功。

但是防御式編程中,我們應該對一切未知的接口都持有懷疑態度,況且不怕一萬就怕萬一:“如果服務端出現異常怎么辦?”

網上有2中答案:

  1,直接將異常拋出去,經過RPC序列化后,客戶端進行展示。

  2,不拋異常出去,服務端進行全方位攔截,攔截到后,通過BaseResultDto,告訴客戶端現在服務端出現異常了。

 

但是各自的缺點很明顯:

  1,服務端與客戶端,很可能不在同一個應用中,所以各自會依賴不同的jar包,比方說:服務端拋出了個spring的duplicateKeyException,但是客戶端並沒用引用spring的相關jar包,這樣就會導致:拋出異常后,由於客戶端沒有依賴這個類,最終拋出個ClassNotDefError,注意是Error不是Exception。如果客戶端只對Exception進行捕獲的話,會導致直接拋到最頂層。可能日志、重試等都沒了。

  2,全方位攔截后,可能返回的結果中只會告訴客戶端:“系統出現異常”,無法准確通過日志去定位問題。

 

最終解決方案:

  將2者折中處理,服務端全方位進行攔截,如果出現異常后,把異常信息轉換成字符串,然后把異常信息返回到客戶端中:

  

public class BaseResultDto<T> {

	/**
	 * 是否操作成功
	 */
	private boolean success;

	/**
	 * 提示信息
	 */
	private String msg;
	/**
	 * 操作結果
	 */
	private T result;

	/**
	 * 異常堆棧信息
	 */
	private String errorTrace;
}

  errorTrace就是存儲異常對戰信息的屬性,這樣如果客戶端檢測到success為false,這樣就可以直接把errorTrace打到log中,方便定位問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM