分類:我的除錯食譜

C# 工作平行程式庫的例外處理機制

C# 工作平行程式庫的例外處理機制

最近2個月又重回C#懷抱了,昨晚追查一個底層ThreadPool Exception,然後會造成w3wp的Exception, 會造成集區重啟的異常

後來發現有一個非同步呼叫射後不理的部分,並沒有合理的包裝例外,然後又會造成.net framework底層無法Handle的例外

Legacy Code的用法是改一半的非同步呼叫方法

function method1()
{
       method2();
}

async Task<ResultObj> function method2()
{
       //略
}

後來查詢多方說法後(StackOverFlow網友建議),建議這種射後不理的整合寫法,可以採用TPL(工作型非同步執行庫)

正規TPL的非同步方法在Handle的時候如下:

其例外處理範例,因為Task的例外會拋出來的是AggregateException方法。因此可以例用以下方法來走訪所有的Exception

   public static void Main()
   {
      var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );

      try
      {
          task1.Wait();
      }
      catch (AggregateException ae)
      {
          foreach (var e in ae.InnerExceptions) {
              // Handle the custom exception.
              if (e is CustomException) {
                  Console.WriteLine(e.Message);
              }
              // Rethrow any other exception.
              else {
                  throw;
              }
          }
      }
   }

 

後續改寫一版後,能明確抓到射後不理的Exception,也不會造成集區崩潰就變成以下的版本了

Task listenerTask = Task.Run(() => proxy.callService<ResultObject>(inputObj)).ContinueWith( 
	t => { logException(t, proxy.ServiceName); }, TaskContinuationOptions.OnlyOnFaulted);

private static void logException(Task<BaseAddOutput> t, string serviceName)
{
	var message = string.Empty;
    if (t.Exception != null)
       message = t.Exception.Message;
    if (t.Exception.InnerException != null)
       message = t.Exception.InnerException.Message;
    Debug.Log(ConfigUtil.GetBoolean("Debug"), "system call " + serviceName + " error, msg:" + message);
}

 

當然,若不是要射後不理的話,建議還是要讓function async / wait化,來確保執行流程順序中的工作都有被完成

 

MS Docs參考

https://docs.microsoft.com/zh-tw/dotnet/standard/parallel-programming/task-based-asynchronous-programming

Nosql之Cassandra 的Docker 除錯歷程,schema重置大法

Nosql之Cassandra 的Docker 除錯歷程,schema重置大法

早上因為自己的vm容量不太夠,所以開始關機調配了一下相關設定,重啟vm後,照慣例是要restart相關docker服務,結果就馬上遇到下面的狀況
Cassandra掛掉了…,restart數次都這樣,跑了二分鐘後,就exit
sudo docker ps -a
一開始我只知道看log的指令,先看看是遇到什麼鬼問題吧…
sudo docker logs {{containner id}}
如下圖log顯示,commitlog異常,讀取失敗,導致cassandra爆掉…,但log上寫的全部都是containner內部的相對位置,我怎麼追查呀?重開一個containner是很簡單…但資料因為沒有獨立出來,所以有一些設計的schema若重啟一個是不是會不見呀?想到這邊,還是覺得這是一種逃避,決定下海來找原因
以往ap跑不起來,我比較知道的查詢的方式,是必須shell進去 container,然後在runtime環境查問題。但containner根本跑不起來…怎麼辦?
然後當初是透過dokcerfile(吧?)跑指令,所以無從知道這個containner有沒有綁定volumn,若沒有的話,我該怎麼去追查cassandra的問題呢?
查了一小多小時,有一個command露出了一線曙光
我们可以使用docker inspect命令找到Volume在主机上的存储位置:
$ sudo docker inspect -f {{.Volumes}} container-test
以cassandra 異常,為例:我們可以透過docker得知預設volumn的位置,這些位置其實可以在起始指令的時候進行綁定
部分指令好位置的我覺得沒問題,dockerfile也應該查的到,但沒有dockerfile可以 參考的,我們就可以透過這個指定看到containner現況的所有相關資訊
 “Mounts”: [
            {
                “Name”: “31a88f59c57b5a75b98f9c4e6a539e4140cb226760fc540b15b930d96010a84c”,
                “Source”: “/var/lib/docker/volumes/31a88f59c57b5a75b98f9c4e6a539e4140cb226760fc540b15b930d96010a84c/_data“,
                “Destination”: “/var/lib/cassandra”,
                “Driver”: “local”,
                “Mode”: “”,
                “RW”: true,
                “Propagation”: “”
            }
檢查其下的volumns路徑,發現data/我的keyspace下怎麼這麼多這個file,原來是我先前透過工具去clone TABLE的時候,其實都會記錄下來…封存在這邊,這邊我先不管了,先把那些我rename過的目錄都刪掉…
docker restart 後以後,還是死掉…,到這邊,我想到…log中寫的是commitlog異常,我看到cassandra的volumn根目錄下有一個commitlog的目錄,我直接把裡面的檔案mv到/backup,再重啟一次…終於正常了,schema回來了
但…資料不見了?  shit!!所以這些commitlog才是跟資料有關,data則是只有schema??神奇啊…至目前為止,還好我是測試資料…schema比較重要,至於正式資料的環境我覺得根本不能這樣搞,但為何commitlog會讓cassandra掛掉,無法啟動,我還是不知道,至少這次經驗,成功重啟了,我猜測原因可能是我對cassandra建立了很多blob field,根本原因,等我有空再來研究看看,這些log裡面到是在賣什麼藥,幸好我有把commitlog備份出來…
先繼續其他nosql的測試了
WP Facebook Auto Publish Powered By : XYZScripts.com