2014-12-05 36 views
2

TLDR:是否有更好的方式通知客戶端服務器上發生了意外事件,而沒有拋出IDL中定義的異常。我現在在服務器端(THttpServer,TThreadPooledServer)和客戶端上使用JavaScript AngularJS App(我有一些在C#上運行客戶端foo的測試)使用Thrift和C#。Apache Thrift中的常見錯誤處理

所以......我知道在Apache Thrift中有異常處理。我可以在IDL中定義一個,並告訴服務方法發生異常的可能性。當發生這種情況時,客戶會收到通知,發現此異常並可以採取相應措施。

但是,如果由於某種原因,在處理程序中執行的代碼會繼續執行並死亡並引發異常,則客戶端會收到「無法讀取,遠程端已關閉」錯誤,那就是這樣。我無法真正看到發生了什麼事,我不得不開始調試服務器,而無需理會要看的內容。當然,我可以在服務器端記錄這個異常(我打算這麼做),但是這可能會變得混亂,需要花點時間看一下。

我真正想要的是讓客戶至少知道在服務器端發生的事情,而不僅僅是讓它得到一個「是的,連接關閉了,不知道爲什麼發生了,快樂的晚上!」。

獲得此方法的一種方法是創建一個GeneralExceptions.thrift文件並在其中定義一個常規異常。然後將此文件包含在其他.thrift文件中,並讓每個服務方法都將該異常視爲可能發生的異常。然後在我的節儉處理程序方法周圍製作巨大的try catch塊,以捕捉所有內容和他們的母親,並將其包裝在一個整潔的普通節儉異常包中,然後傳遞給客戶端。

問題是......必須讓那些嘗試catch塊到處都會很煩人。並且必須在所有其他文件中包含一個節儉文件並讓每種服務方法聲明它可以拋出這個普遍的異常......好吧,讓我們說...這是一大堆工作,並且人們通常是他們的方式可能會忘記包含該文件,或者不會在這些服務方法中添加該例外,以及如果您有多於一個人或加利福尼亞州工作的任何特定事情,那麼往往會發生所有其他好事。

那麼有沒有人知道另一種方式來通知客戶端,「服務器」發生在服務器上,而沒有跳過大量的箍?

回答

0

服務器既不應該死也不能關閉連接。我最近修復了Trunk中的exactly that problem for Delphi(將成爲0.9.3的一部分)。如果C#遇到同樣的問題,請提交一張票(包括測試用例)和/或提供補丁。

如何捕捉服務器方法中的任何意外異常?這圖案的,與普通的COM太有用,沒有太多的差別:

// this is a service method 
void FooBar() { 
    try 
    { 
    // lets see whether we can divide by zero ... 
    var a = 0; 
    var b = 1/a; 
    Console.Writeln("It works!!"); 
    } 
    catch(e:TException) 
    { 
    throw; // Thrift exception, don't interfere 
    } 
    catch(e:Exception) 
    { 
    throw new TApplicationException("WTF?"); // or some other exception 
    } 
} 

問題是...不必有那些嘗試到處catch塊會被討厭。並且必須在所有其他文件中包含一個節儉文件並讓每種服務方法聲明它可以拋出這個普遍的異常......好吧,讓我們說...這是一大堆工作,並且人們通常是他們的方式可能會忘記包含該文件,或者不會在這些服務方法中添加該例外,以及如果您有多於一個人或加利福尼亞州工作的任何特定事情,那麼往往會發生所有其他好事。

產生通過其他方式直接服務器實現和實際工作轉發到其他一些方法和/或類:

// this is a service method 
MyResult FooBar(MyArg arg1, MyOtherArg arg2) { 
    try 
    { 
    return pimpl.FooBar(arg1,arg2); // delegate work via pimpl pattern 
    } 
    catch(e:TException) 
    { 
    throw; // Thrift exception, don't interfere 
    } 
    catch(e:Exception) 
    { 
    throw new TApplicationException("WTF?"); // or some other exception 
    } 
} 

這是非常簡單,可以很容易地實現自動化。

+0

那麼如果服務器不應該死亡或關閉連接(將爲此打開一個JIRA問題),那麼異常處理應該在c#thrift庫的服務器部分完成。難道這不應該讓「將大型try-catch塊中的服務方法的整個代碼包裝起來」變成多餘的嗎?只有你的例子會做的是用其他東西掩蓋實際的異常。或者我完全錯了嗎? – 2014-12-05 10:37:07

+0

取決於您在異常處理程序中要執行的操作以及要使用的版本。這個修復程序很可能不會回到0.9.2。所以,如果你必須堅持0.9.2或更早...... :-) – JensG 2014-12-05 15:35:18