• 工程中实际问题解决两例——基于C#


    工程中实际问题解决两例——基于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 版权协议,转载请附上原文出处链接和本声明。

    本文链接:https://www.cnblogs.com/JerryMouseLi/p/15545356.html

    The Sky is the limit.
  • 相关阅读:
    fiddler查看IP地址和请求响应时间
    web安全测试排查
    搞站思路 <陆续完善中>
    sys模块进度条玩法笔记
    Webbench、ab命令:做压力测试的工具和性能的监控工具
    xlwings excel(三)
    xlwings excel(二)
    xlwings excel(一)
    xlwings API Documentation
    Python+Excel 操作对比
  • 原文地址:https://www.cnblogs.com/JerryMouseLi/p/15545356.html
Copyright © 2020-2023  润新知