起因
客戶說:“今天的預報又沒有發出去,幫忙看下怎麼回事?”
“...”
經過
登陸伺服器,發現程式一直在列印
running
running
running
...
這是程式碼中寫的
public static void Main(string[] args)
{
Console.Title = string.Format("Grib2壓碼程式 請勿關閉");
ActiveMq();
while (hasMessage)
{
Console.WriteLine("running");
Thread.Sleep(1000);
}
}
程式通過啟動ActiveMQ,然後判斷是否仍有訊息在處理,如果在處理就Sleep當前執行緒,等待處理完畢
當接收到訊息時的處理主邏輯:
public static void OnMessage(IMessage message)
{
var msg = message as ITextMessage;
if(msg != null)
{
hasMessage = true;
String date = msg.Text;
Compress(date);
mq.send(date);
hasMessage = false;
}
}
那麼問題應該是Compress
或者 mq.send
一直在處理,卡住了??
因為是.net程式,所以不能用jstack來分析執行緒了
通過windows自帶的工作管理員,把程式dump出來
然後使用windbg分析一下執行緒,直接通過檔案, "open dump file",開啟匯出的dmp檔案。
windbg第一次使用,不是很懂得使用,但是注意到右下角threads的執行緒資訊,發現只有一個主執行緒在執行!!
也就是說:我們的監聽執行緒退出了!!!
那麼,什麼情況下會退出呢?
一般是執行緒執行過程中丟擲異常沒有處理
檢查原始碼,發現程式沒有對出現異常做任何處理
所以,修改方案如下:
public static void OnMessage(IMessage message)
{
var msg = message as ITextMessage;
if(msg != null)
{
hasMessage = true;
String date = msg.Text;
if(Compress(date, 3))
{
mq.send(date);
}
else
{
mq.fail(date);
}
hasMessage = false;
}
}
public static bool Compress(string date, int retry)
{
if (retry == 0)
{
return false;
}
try
{
Compress(date);
return true;
}
catch (Exception ex)
{
Log.writeException(ex);
return Compress(date, retry - 1);
}
}
將監聽訊息部分的程式碼進行修改,增加重試,並進行try catch異常處理,出現異常時,在檔案中記錄日誌
當然mq.send
也有可能出現異常,將send方法也進行try catch異常處理
替換程式,上線執行(這種問題看能否重現了,重現了就可以在error.log中找到了)
總結分析
windbg第一應用,表示很多資訊都看不懂
主執行緒中需要考慮子執行緒的異常,有些執行緒,你以為在執行,實際上它退出了
其它
面試的時候,面試官問我
“你遇到過最難解決的問題,你是怎麼解決的?”
“我特麼都是問題解決了就忘記了,所以沒啥印象”
不過,我是在心裡說的
所以,對於別人問我的問題,我決定記錄下來,免得將來忘記了