• 项目总结1--技术


    1.数据。数据特点,各种各样的报文数据,包括农业气象观测报和实时自动站数据,这些数据有规则的存放在中心服务器,要做的是down下这些数据,通过本系统处理存入数据库,自动完成day数据统计。主要涉及数据的自动和手动处理,数据的自我统计;前台用到winform,后台用的Sql Server 2008.

    2.winform。手动和自动区别不大,我是在自动处理的基础上稍加修改就有了手动处理程序,事实上手动比自动搞起来简单点,后面将说明why……。

    ①农业气象观测报,这里称为AB报。该报文种类几十个,这里用到17个,AB报只是总称,该大类下又细分为土壤的Soil(0~i) 、物候的Pheno(0~1)、作物的Crop(0~i)……,子分类下报文格式字段又五花八门。这里大概是用到了工厂模式,处理如下图:

    通过对象制作工厂产生能够处理特定类型报文的Class 对象,这个对象类实现接口:ZABMessage0;ZABTypeHandler就是根据报文的标识符来产生对应的处理类,因此命名为CreateObj。由于这些处理类要做的操作基本一致,只是报文内容和格式稍异,因此考虑使用统一接口来实现,可以使前台winform代码简洁而方便维护,总共要处理17种文件,也就是说要写17个相关的类,如果不用接口统一来管理,一个人维护起来简直就是噩梦啊!!!如果不用对象制作工厂,那么前台的代码尽管引入了统一接口,仍旧会很臃肿,臃肿的原因在于:数据源数据分为17种,如果不用对象生产器,那么要做多少次逻辑判断,才可以确定我们需要一个什么样的类来处理该文件。下面是部分代码:

     public ZABMessage0 CreateObj()
            {
                switch (keyStr)
                { 
                    case "METE-01": 
                        return (new Mete01_ZAB());
                    case "METE-02":
                        return (new Mete02_ZAB());
                    case "PHENO-01":
                        return (new Pheno01_ZAB());
    ……
    

     

     //w-外层记录段循环
                                                for (int i = 1; i <= headerZAB._segments; i++)
                                                {
                                                    line = reader.ReadLine();//关键字段部分  reading
                                                    splitArr = line.Split(sep, StringSplitOptions.RemoveEmptyEntries);
                                                    ZABTypeHandler abTypeHandler = new ZABTypeHandler(splitArr[0]);
                                                    int rows = int.Parse(splitArr[1].Remove(splitArr[1].Length - 1));//记录的行数
                                                    for (int ii = 1; ii <= rows; ii++)
                                                    {//每一行记录 入库
                                                        ZABMessage0 obj = abTypeHandler.CreateObj();
                                                        obj._ConStr = dbConfig.conStr;
                                                        line = reader.ReadLine();// row   reading
                                                        obj._ContentZAB = line.Substring(0, line.Length - 1);
                                                        obj._Header = headerZAB;
                                                        obj.Analysis();
                                                        obj.InsertDB();//obj 提交到数据库
                                                    }
                                                    reader.ReadLine();//读入END终结符
                                                }//end w-外层记录段循环
    

      ②自动站报文处理。自动站小时报文处理要考虑的因素就比较多了:原始的数据比较多,可能漏报,需要做day统计分析,同时数据来源另一个FTP,该FTP定时同步一些数据到磁盘,会出现文件读写竞争的问题(该问题后期给 了我不少麻烦,开始没考虑到这个问题)。该FTP定时10分钟做一次同步下载更新,而我的自动处理程序一个小时内,每5分钟做一次处理,不会重复处理一个文件,就是这样,每小时仅仅上百个站点的数据文件仍出现了“抢”的现象,造成了数据库读写异常。其次,刚开始设计的界面由于运行提示信息不够,带来了bug分析信息缺乏,后来补充了数据库表及字段。

     ③数据库。不用说了数据库都基本使用存储过程完成,天统计大部分是由存储过程完成少部分是在前台代码完成的。值得总结的是,对于实时的数据录入,虽然代码不会出错,但是放入到实际环境中还是会出现一些未知的错误,这些错误或者是由于代码量太大了自己掌控不了而忽略的错误,或是受其它客观因素的影响,因此记录软件运行过程信息显得十分有必要了,通过辅助记录信息如log.table,或者error.table,可以清楚看到每个小时到底处理了哪些数据,哪些站点是漏报的,某个时间段处理了哪些数据,可以精确到某一分钟处理了哪些数据文件,这为我们错误定位有很好很好好的帮助作用。这里使用了作业流水号,通过该流水号,记录了每小时处理数量,处理的文件类型,开始时间,结束时间;数据表中记录每条记录生成时间,开始处理时间结束处理时间。因此设计数据库时,丰富的字段和表看起来多余实则相当有用的!!!

    最大的心得是,有时候通过案例测试,看着很正确处理,把这些代码嵌入到整体中时,或者在实际运行时,总会有主客观的原因出现异常,因此要十分小心,考虑要周全些,其次不要怕数据库字段繁多,越丰富的信息越是对后期有帮助!

  • 相关阅读:
    RabbitMQ 3.8.5版本 windows安装和web管理界面登陆
    RabbitMQ 3.8.5版本 4 种Exchange交换机类型选择,关系RabbitMQ架构选型核心
    maven的settings.xml里设置aliyun镜像以及jdk1.8版本编译
    centos8赋予当前用户rpm文件所有权,并安装rpm文件
    Java8里的HashMap对象lambda遍历方法
    springboot项目application.properties配置文件里自定义日志输出
    kafka2.5.0硬件集群架构图、Topic主题与Partitions分区架构图
    kafka2.5.0分区再均衡监听器java例子
    kafka2.5.0自定义分区器
    kafka2.5.0自定义数据序列化类
  • 原文地址:https://www.cnblogs.com/DebugMe/p/3223388.html
Copyright © 2020-2023  润新知