工程优化——服务程序自身调度


  之前是使用 crontab 去调度程序,让程序启动,但是在实际中很少只是使用 crontab 去调度。一般都是 crontab 和自身调度结合使用去调度程序,所以现在将 psurfdata.cpp (数据入库程序)调整为自身调度。

  程序自身调度其实就是利用 while(true) 让程序一直执行,执行一遍之后就 sleep() 一段指定的时间。这就有点类似于 crontab 任务中的指定时间去执行程序。

一 、优化程序,修改存在的问题

  (1)这个程序现在是打开了数据文件存放的目录,就马上连接数据库。其实这是有些不妥的。如果目录中没有数据文件,其实是不需要连接数据库的,因为没有文件要处理。这样就会浪费数据库连接资源

if ( Dir.OpenDir(argv[1],"SURF_ZH_*.txt",10,false,true) == false )
        {
                logfile.Write("Dir.OpenDir(%s) failed.\n",argv[1]);
                return -1;
        }

        logfile.Write("Dir.OpenDir(%s) Sucess.\n",argv[1]);

        //  导入数据库前,连接数据库
        if ( conn.connecttodb("scott/123456@snorcl11g_198","Simplified Chinese_China.ZHS16GBK") != 0 )
        {
                logfile.Write("connect database failed.\n%s\n",conn.m_cda.message); return -1;
        }
         while (true)
        {
                // (1) 先读取文件,其实这里读取文件是放在容器中的,
                // 只是封装了ReadDir() ,容器声明在 ReadDir() 里面
                if ( Dir.ReadDir() == false )
                {
                        logfile.Write("Dir.ReadDir() 读取文件完毕.\n");
                        break;
                }

                //(2) 开始处理文件
                logfile.Write("开始处理文件 filename=%s\n",Dir.m_FullFileName);

                if ( _psurfdata() == false )
                {
                        logfile.Write("失败。\n");
                        break;
                }
                logfile.Write("处理文件结束 filename=%s\n",Dir.m_FullFileName);
        }


        return 0;
}

  (2)那应该什么时候开始连接数据库比较合理?在扫描了目录( ReadDir() )确认有需要处理的数据文件之后开始连接数据库。所以需要将连接数据库的代码的位置调整到扫描目录之后。

 while (true)
        {
                // (1) 先读取文件,其实这里读取文件是放在容器中的,
                // 只是封装了ReadDir() ,容器声明在 ReadDir() 里面
                if ( Dir.ReadDir() == false )
                {
                        logfile.Write("Dir.ReadDir() 读取文件完毕.\n");
                        break;
                }

                // 连接数据库
                if ( conn.m_state == 0 )
                {
                        if ( conn.connecttodb("scott/123456@snorcl11g_198","Simplified Chinese_China.ZHS16GBK") != 0 )
{
                                logfile.Write("connect database failed.\n%s\n",conn.m_cda.message); break;
                        }
                }

二、修改程序,让程序调度自身

  到现在为止,已经做到将分钟气象观测数据导入数据库。在做这个项目的开始,就有一个要求就是能够尽可能地模拟出真实的气象数据中心。

  其中就有一个要求就是能够实时地处理数据,也就是说气象站点生成了气象观测数据了,能够及时地将数据取回来,然后将数据处理好导入数据库。这三个步骤应该是能自动完成的,一气呵成的。这样就能更接近一步真实的气象项目。

  为了能够达到这个要求,就需要将程序修改成程序能够自身调度,当然也可以使用 crontab 任务去调度,但是实际中并不只是使用 crontab 任务去调度。

1.修改模拟气象站点生成气象观测数据

  (1)气象站点的气象观测数据是隔一段时间就会生成的,所以我们也要实现这个。现在使用的是分钟气象观测数据,所以要求每隔 60 秒就生成一批气象观测数据。

  在前言已经说了,自身调度就是使用 while(true),让程序一直执行,分钟气象观测数据,就是执行一次循环就 sleep(60);

在这里插入图片描述
  (2)让程序一直调度自身还有一个问题,就是程序出错了还能够继续运行下去。但是要注意的是程序出的错误,不是所有的错误都能忽略掉,让程序继续运行的,在工程的优化的,错误处理有详细的说明。

  这个程序能出的错误,并不是能数据库断开连接类的,所以能将这些错误忽略掉,当出现错误时就不继续执行这一次的操作的剩下步骤,continue 执行下一次操作,但是不 return 让程序停止。

  下图是将气象站点参数加载到程序容器中时可能数据的格式不对,会出错。
在这里插入图片描述
在这里插入图片描述

  修改的模拟气象站点生成气象观测数据程序(crtsurfdata.cpp)如下:

 while( true )
        {
        // 二、将气象站点参数加载程序中的容器
        if ( LoadSTCode(argv[1]) == false )
        {
                logfile.Write("LoadSTCode(%s)failed.\n",argv[1]);
                sleep(60);
                continue;
        }
        logfile.Write("气象站点参数加载成功(%s)\n",argv[1]);


        // 三、模拟生成观测数据
        CrtSurfData();


        // 四、将观测数据写入指定的文件
        if ( CrtSurfFile(argv[2]) == false )
        {
        logfile.Write("CrtSurfFile(%s)failed.\n",argv[2]);
                sleep(60);
                continue;
        }

        sleep(60);

        }
        return 0;
}
        

2.修改 ftpgetfile.cpp

  当模拟的数据源生成了气象观测数据,要及时地将数据取回来,修改 ftpgetfile.cpp 的方法思路与修改前面的程序是大同小异的。

  (1)将主要的步骤,必要的步骤放到 while(true) 中,指定 sleep() 的时间

  (2)忽略掉出现的错误,将 return 改为 continue。
在这里插入图片描述

3.修改处理入库程序(psurfdata.cpp)

  处理思路大同小异

 while ( true )
        {

                logfile.Write("开始扫描目录。\n");

        if ( Dir.OpenDir(argv[1],"SURF_ZH_*.txt",10,false,true) == false )
        {
                logfile.Write("Dir.OpenDir(%s) failed.\n",argv[1]);
                sleep( atoi( argv[3] ) );
                continue;
        }

        logfile.Write("Dir.OpenDir(%s) Sucess.\n",argv[1]);
        // 4.2 逐个处理目录中的数据文件,并将处理好的数据导入数据库
        while (true)
        {
                // (1) 先读取文件,其实这里读取文件是放在容器中的,
                // 只是封装了ReadDir() ,容器声明在 ReadDir() 里面
                if ( Dir.ReadDir() == false )
                {
                        logfile.Write("Dir.ReadDir() 读取文件完毕.\n");
                        break;
                }

                // 连接数据库
                if ( conn.m_state == 0 )
                {
                        if ( conn.connecttodb("scott/123456@snorcl11g_198","Simplified Chinese_China.ZHS16GBK") != 0 )

                        {
                         {
                                logfile.Write("connect database failed.\n%s\n",conn.m_cda.message); break;
                        }
                }

                logfile.Write("连接数据库成功.\n");

                //(2) 开始处理文件
                logfile.Write("开始处理文件 filename=%s\n",Dir.m_FullFileName);

                if ( _psurfdata() == false )
                {
                        logfile.Write("失败。\n");
                        break;
                }

                logfile.Write("处理文件结束 filename=%s\n",Dir.m_FullFileName);
        }
        // 处理完一批数据就断开与数据库的连接
        if ( conn.m_state == 1 )
        {
                conn.disconnect();
                logfile.Write("断开数据库连接。\n");
        }

        sleep( atoi( argv[3] ) );
     }


        return 0;
}

三、利用脚本启动关闭程序

  修改好了程序之后,就可以启动这三个程序了,但是每次都要手动去敲每个程序的执行程序,并把执行参数写上,这样就很麻烦。关闭程序大同小异

  可以写两个脚本来解决上述的问题,一个脚本用来启动这些程序,一个用来停止运行。

1.启动脚本

  启动程序,让程序在后台运行,加上 “&” 符合

# 该脚本用于启动气象数据中心的服务程序
  
# 生成全国气象站点分钟气象观测数据文件
/htidc/qxidc/bin/crtsurfdata /htidc/qxidc/ini/stcode.ini /data/qxidc/ftp/surfdata /log/qxidc/crtsurfdata.log &

# 采集分钟气象观测数据文件
/htidc/public/bin/ftpgetfile /log/qxidc/ftpgetfile_surfdata.log "<host>8.131.80.81:21</host><mode>1</mode><username>root</username><password>ue68malinux</password><localpath>/data/qxidc/surfdata</localpath><remotepath>/data/qxidc/ftp/surfdata</remotepath><matchname>SURF_*.TXT</matchname><ptype>2</ptype><remotepathbak>/data/qxidc/ftp/surfdatabak</remotepathbak><listfilename>/htidc/qxidc/list/ftpgetfile_surfdata.list</listfilename><okfilename>/htidc/qxidc/list/ftpgetfile_surfdata.xml</okfilename><timetvl>30</timetvl>" &

# 处理分钟气象观测数据文件并入库
/htidc/qxidc/bin/Testpsurfdata /data/qxidc/surfdata /log/qxidc/psurfdata.log 10 &

2.关闭程序脚本

killall ftpgetfile crtsurfdata Testpsurfdata

3.给予脚本可执行权限

四、总结

  1.如何让程序自身调度?
  (1)while(true) + sleep()
  (2)忽略错误,continue

  2.善于利用脚本去解决一些事情

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值