工程中實際問題解決兩例——基於C#
1. try catch的妙用
1.1 遇到問題的現象
機房動環監控系統,新增了100多個站點,新加裝置無法同步,介面點同步,通訊服務會報錯退出
同步裝置操作如下:
通訊異常如下:
大概意思是字典快取中查無此值(根據鍵找)。
1.2 原因分析
其實每個比較大的bug都是系統設計不合理的地方,同時也是下次系統設計的寶貴經驗。
同時需要闡明的是bug只要能復現,就一定能解決,或者是從正面解決,或者是策略解決(受限於資源或者網路的時候)。
主要從日誌(檔案列印或者命令視窗列印),資料庫,程式碼三個層面。
1.2.1 先從資料庫入手
找到資料庫中歷史資料插入的表deviceData,會不會因為有些欄位為非空了,導致插入失敗。全欄位允許為空,結果依然報錯;
1.2.2 程式碼日誌逐級列印結合資料庫
根據窗體報錯的行數970,598,以及資料庫中的PesudoDevice表,結合系統設計的邏輯,大體流程如下:請求裝置上報資料,根據協議裝置將上報資料格式(配置規則),平臺將協議模板序列化儲存到PesudoDevice表的content欄位中。採集的資料會按照告警規則與訊號點規則,儲存到businessSignal與activeAlarm表中去。
其中主要的兩個型別如下:
某機房的所有業務裝置
/// <summary>
/// 業務裝置模板內容
/// </summary>
public class PseudoDeviceTemplateContext
{
/// <summary>
/// 物理裝置
/// </summary>
public List<string> ConcreteDeviceIDs { get; set; }
/// <summary>
/// 測點列表
/// </summary>
public List<PseudoDeviceTemplateSignal> Signals { get; set; }
}
單個訊號點的型別
/// <summary>
/// 業務裝置模板測點定義
/// </summary>
public class PseudoDeviceTemplateSignal
{
/// <summary>
/// 物理裝置ID
/// </summary>
public string ConcreteDeviceID{get;set;}
/// <summary>
/// 物理裝置名稱
/// </summary>
public string ConcreteDeviceName{get;set;}
/// <summary>
/// 物理裝置型別ID
/// </summary>
public string ConcreteDeviceTypeID {get;set;}
/// <summary>
/// 物理裝置型別ID
/// </summary>
public string ConcreteDeviceTypeName { get; set; }
/// <summary>
/// 測點ID
/// </summary>
public string SignalID { get; set; }
/// <summary>
/// 通道ID
/// </summary>
public string ChannelID { get; set; }
/// <summary>
/// 通道名稱
/// </summary>
public string ChannelName {get;set;}
/// <summary>
/// 通道型別
/// </summary>
public int? ChannelType {get;set;}
/// <summary>
/// 測點名稱
/// </summary>
public string SignalName{get;set;}
/// <summary>
/// 測點型別ID
/// </summary>
public string SignalTypeID{get;set;}
/// <summary>
/// 單位ID
/// </summary>
public string UnitMeasureID { get; set; }
/// <summary>
/// 告警條件列表
/// </summary>
public List<SignalAlarmCondition> AlarmConditions { get; set; }
/// <summary>
/// 儲存條件列表
/// </summary>
public List<DeviceDataStoreRule> DeviceDataStoreRules { get; set; }
/// <summary>
/// 精度
/// </summary>
public string MinPrecision { get; set; }
/// <summary>
/// 標稱值
/// </summary>
public double? Stander { get; set; }
/// <summary>
/// 標稱值
/// </summary>
public int? IsSaveHis { get; set; }
/// <summary>
/// 標稱值
/// </summary>
public double? MaxVal { get; set; }
/// <summary>
/// 標稱值
/// </summary>
public double? MinVal { get; set; }
/// <summary>
/// 標稱值
/// </summary>
public int? IsControl { get; set; }
/// <summary>
/// 標稱值
/// </summary>
public long? DataID { get; set; }
/// <summary>
/// 父資料ID
/// </summary>
public long? ParentDataID { get; set; }
}
1.2.3 原因分析
經過前端介面狀態查詢,資料庫sql查詢,日誌逐級列印,最終定位某同步失敗站點資料表PesudoDevice的content欄位為空,原來應該為裝置ID集合與協議模板解析規則。因為該裝置協議模板較大,而序列化json比較耗時,此時裝置的輪詢報文到來,導致解析異常,從而程式崩潰。
1.2.4 解決方案
原因找準確了,解決方法其實很簡單,只要把一開始解析異常的程式碼try catch異常。等解析規則儲存完畢了,自然就能把訊號點解析準確。
異常崩潰程式碼;
PseudoDeviceStatus data;
this.DPServiceObj.GetPseudoDeviceRealData(task.DstPseudoDeviceID, task.DstSignalID, out data );
解決異常程式碼:
PseudoDeviceStatus data=null;
try
{
this.DPServiceObj.GetPseudoDeviceRealData(task.DstPseudoDeviceID, task.DstSignalID, out data);
}
catch (Exception e)
{
log.ErrorFormat("獲取裝置實時資料失敗:{0}",e);
}
分析問題時間用了很久,對問題理解透徹了以後,解決問題並不需要幾行程式碼。
1.2.5 問題解決
資料同步成功結果
2. json長度限制帶來的困惑
2.1 現象描述
隨著站點(含待測點)新增越來越多,單次載入遇到瓶頸,無法將全部資料單次載入。
2.2 問題分析
2.2.1 第一步,檢視對應告警預案介面,報伺服器錯誤
2.2.2 第二步,檢視介面返回結果預覽
錯誤提示為返回字串長度超過了json的預設最大長度,這個問題已經遇到過,設定下json序列化的最大長度即可輕鬆解決。
2.2.3 問題解決
問題程式碼
/// <summary>
/// 獲取裝置樹
/// </summary>
/// <returns></returns>
public ActionResult GetAlarmPlanDevTree()
{
List<object> children = new List<object>();
List<Area> areas = DevicesTreeHelper.GetAreaStation();
foreach (Area a in areas)
{
children.Add(GetATreeData(a, true));
}
return Json(children);
}
問題解決程式碼
/// <summary>
/// 獲取裝置樹
/// </summary>
/// <returns></returns>
public ActionResult GetAlarmPlanDevTree()
{
List<object> children = new List<object>();
List<Area> areas = DevicesTreeHelper.GetAreaStation();
foreach (Area a in areas)
{
children.Add(GetATreeData(a, true));
}
return new JsonResult() { Data = children, MaxJsonLength = int.MaxValue, ContentType = "application/json" };
}
解決之後所有測點訊號載入成功
3. 小結
遇到問題並不可怕,只要能復現,根據具體提示,逐級列印日誌,分析資料庫,問題就能迎刃而解,在此做個記錄,下次類似問題遇到能有印象,快速定位解決。
版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。