市场项目详细架构
一、每小时任务
1.简述:这一切的一切都来自于每小时任务,将原始日志转换成新日志
2.脚本所在机器:首先通过堡垒机登录211.151.183.151,通过堡垒机登录该服务器
3.脚本的位置:/opt/wxw/project/new_market_report_hour.sh
4.脚本内容:
#!/bin/sh
# 115版数据转换
java -jar /opt/wxw/project/report_data_change/report_data_change.jar
sleep 1
# 每日趋势图
java -jar /opt/wxw/project/new_market_report_1_6/new_market_report_1_6.jar
sleep 1
java -jar /opt/wxw/project/new_market_report_1_6/new_market_report_1_6.jar
5.脚本分析:
可以看到,该脚本总共执行了两步操作,我们先来看看第一部分。
1).日志数据转换部分
第一步,svn地址:
svn://192.168.0.191/sta/Analytics/project/market/Src/Server/com.tydtech.mig.report_data_change_143
第二步,代码走查:
我们定位到main方法里面:
移除点击此处添加图片说明文字Main调用了ReportDataMultiThread的start方法,追查代码
移除点击此处添加图片说明文字进入start方法,查看详细细则。
因为代码量较多,我们只说个大概。
首先我们看到一上来就声明了很多全局变量和开关。
移除点击此处添加图片说明文字在这里我们看到很多常量类,注意,一般我们将常量类放到tools或者beanUtils公共类里面已提供公共调用。
这里连接了三个库,一个mongoDB库,一个redis库,一个mysql库。我们一个一个点开来确定:
首先我们看mongo的OpenDB方法
移除点击此处添加图片说明文字这两个参数一个是url,一个是dbname,那行,记下来我们看看连接redis
移除点击此处添加图片说明文字创建一个jedisPool类即可,在接下来我们再看看mysql的连接方式。mysql使用了CommonMysql的类的loadDriver方法,这个是在tool工程里面已经写好的,直接import过来即可,方法请看图,仅仅是使用了统一的driver驱动。
移除点击此处添加图片说明文字好的,我们接着回到主ReportDataMultithread类,接着看连接的具体connection。
原来是在这里打开了三个mysql的连接,我们可知有三个mysql库了。
移除点击此处添加图片说明文字OpenConn的三个方法类似,都是类似这段代码。
移除点击此处添加图片说明文字其实就是给入url、username、password三个参数提供连接。
我这么分析是干嘛呢?是想带你搞清楚数据从哪里开,将来回到那里去,中间会经过什么数据库:
移除点击此处添加图片说明文字好了,既然所有的连接库搞明白了,拨开云雾,我们要接着看代码了。在ReportDataMultiThread类中有做了这件事:pdc_status = CommonReportMongo.db_report.getCollection("pdc_status");
使用了事先写好的工具类 CommonReportMongo的db_report的getCollection方法,我们要进去看。
移除点击此处添加图片说明文字其实就是打开mongo的url和客户端
移除点击此处添加图片说明文字我们分析一下,接下来做了什么:
移除点击此处添加图片说明文字这段代码,第一句,query是事先声明好的全局变量:BasicDBObject
其实就是去查status_id 为public static final String STATUS_ID_REPORT_DATA_CHANGE_115 = "023";的结果集,用mongo去查该结果集,如果结果集为空,我们设置一个默认的时间给变量dt1,否则,我们从结果集中拿到status_dt,时间,设置格式,转成时间。
接下来,dt2,我们看一下:dt2 = Common.addOnePhase(dt1,CommonReport.intPhase);
移除点击此处添加图片说明文字原来吧,dt1给入后,被加了一天。
好的,接下来我们看这段,到上个时段为止的数据已经处理完毕,程序退出
compareTo(参数str)比较。2大于1,返回值为1。如果dt2大于现在的时间,返回肯定是1,如果不大于返回为0,所以,判断是否已经跑过了,用时间。
移除点击此处添加图片说明文字程序接着往下,打日志,从dt1时间到dt2时间。CommonReportMongo.OpenDB_log(CommonReport.connUri_log,"new_market_log_" + CommonReport.CUR_YYYY_MM);
这里事实上就是打开dt1的库,上次最新的库。
移除点击此处添加图片说明文字注意,这段代码,开始启动多线程,线程数为常量类,6,启动六个线程。好的,在for循环里面,我们看进去,向arrBodyTopicVisit里面插入了ReportDataMultiThreadBodyTopicVisit类。我们推测该类就是跑线程的。
移除点击此处添加图片说明文字果然,实现了Runnable接口,这里有run方法,看一下逻辑。生命了一大堆的成员变量。
移除点击此处添加图片说明文字这里方法,首先初始化线程,我们追进init()方法。
移除点击此处添加图片说明文字通过常量类看业务:/** 市场报表 report data_change 存放已经处理过的_id,避免重复插入*/
public static final int REDIS_DB_REPORT_DATA_CHANGE_6379_28 = 28;
原来是该库是存放已经处理过的id的,放在redis里面,用内存数据库确实增大了随机数据提取的速度。
好的,回到该线程类中,我们继续看,提取了mongoDB表里面的两个字段集合,封装对象为DBCollection,现在暂时还看不出来,他提取出来是干嘛,往后看。这里应该是调用了jdbc,拼接sql了,去oz_topic_visit_rec_ yyyymmdd库中提取数据
移除点击此处添加图片说明文字结果集便利出来,在此处做了很多清洗。因为很多if判断里面continue跳出了循环了。具体的业务就不展示了,不要影响后续。
移除点击此处添加图片说明文字小细节是这里有很多计数器,来记录总条数和imsi为空的条数。
然后我们看一下这个代码:
docTopic = CommonReport.getInfo(rs.getString("topic_id"), rs.getString("t_from"),rs.getString("version_code"), rs.getString("reserved"));
点进方法getInfo方法吓死人。洋洋洒洒几千行代码逻辑,各种数据处理判断。通过四个参数,依照参数不同去得到一个BasicDBObject对象
我们大致说一下,就是根据topic_id和from字段算出旧版接口栏目和渠道等信息(127版)
2).每日趋势图Java部分。
6.总结: