天天看點

工程中實際問題解決兩例——基于C#

工程中實際問題解決兩例——基于C#

目錄

    • 1. try catch的妙用
      • 1.1 遇到問題的現象
      • 1.2 原因分析
        • 1.2.1 先從資料庫入手
        • 1.2.2 代碼日志逐級列印結合資料庫
        • 1.2.3 原因分析
        • 1.2.4 解決方案
        • 1.2.5 問題解決
    • 2. json長度限制帶來的困惑
      • 2.1 現象描述
      • 2.2 問題分析
        • 2.2.1 第一步,檢視對應告警預案接口,報伺服器錯誤
        • 2.2.2 第二步,檢視接口傳回結果預覽
        • 2.2.3 問題解決
    • 3. 小結

機房動環監控系統,添加了100多個站點,新加裝置無法同步,界面點同步,通信服務會報錯退出

同步裝置操作如下:

通信異常如下:

大概意思是字典緩存中查無此值(根據鍵找)。

其實每個比較大的bug都是系統設計不合理的地方,同時也是下次系統設計的寶貴經驗。

同時需要闡明的是bug隻要能複現,就一定能解決,或者是從正面解決,或者是政策解決(受限于資源或者網絡的時候)。

主要從日志(檔案列印或者指令視窗列印),資料庫,代碼三個層面。

找到資料庫中曆史資料插入的表deviceData,會不會因為有些字段為非空了,導緻插入失敗。全字段允許為空,結果依然報錯;

根據窗體報錯的行數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; }
    }
           

經過前端接口狀态查詢,資料庫sql查詢,日志逐級列印,最終定位某同步失敗站點資料表PesudoDevice的content字段為空,原來應該為裝置ID集合與協定模闆解析規則。因為該裝置協定模闆較大,而序列化json比較耗時,此時裝置的輪詢封包到來,導緻解析異常,進而程式崩潰。

原因找準确了,解決方法其實很簡單,隻要把一開始解析異常的代碼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);
            }
           

分析問題時間用了很久,對問題了解透徹了以後,解決問題并不需要幾行代碼。

資料同步成功結果

工程中實際問題解決兩例——基于C#

随着站點(含待測點)添加越來越多,單次加載遇到瓶頸,無法将全部資料單次加載。

工程中實際問題解決兩例——基于C#

工程中實際問題解決兩例——基于C#

工程中實際問題解決兩例——基于C#

錯誤提示為傳回字元串長度超過了json的預設最大長度,這個問題已經遇到過,設定下json序列化的最大長度即可輕松解決。

問題代碼

/// <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" };
        }
           

解決之後所有測點信号加載成功

工程中實際問題解決兩例——基于C#

遇到問題并不可怕,隻要能複現,根據具體提示,逐級列印日志,分析資料庫,問題就能迎刃而解,在此做個記錄,下次類似問題遇到能有印象,快速定位解決。

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協定,轉載請附上原文出處連結和本聲明。

本文連結:https://www.cnblogs.com/JerryMouseLi/p/15545356.html

The Sky is the limit.

繼續閱讀