上一篇文章介紹了'網站點擊流數據分析項目業務背景';本篇博客博主將繼續分享網站分析的相關知識。node
1、總體技術流程及架構 jquery
1.1.數據處理流程nginx
該項目是一個純粹的數據分析項目,其總體流程基本上就是依據數據的處理流程進行,依此有如下幾個大的步驟:
1) 數據採集
首先,經過頁面嵌入JS代碼的方式獲取用戶訪問行爲,併發送到web服務的後臺記錄日誌
而後,將各服務器上生成的點擊流日誌經過實時或批量的方式匯聚到HDFS文件系統中web
固然,一個綜合分析系統,數據源可能不只包含點擊流數據,還有數據庫中的業務數據(如用戶信息、商品信 息、訂單信息等)及對分析有益的外部數據。spring
2) 數據預處理
經過mapreduce程序對採集到的點擊流數據進行預處理,好比清洗,格式整理,濾除髒數據等數據庫
3) 數據入庫
將預處理以後的數據導入到HIVE倉庫中相應的庫和表中apache
4) 數據分析
項目的核心內容,即根據需求開發ETL分析語句,得出各類統計結果瀏覽器
5) 數據展示
將分析所得數據進行可視化服務器
1.2.項目結構session
因爲本項目是一個純粹數據分析項目,其總體結構亦跟分析流程匹配,並無特別複雜的結構,以下圖:
其中,須要強調的是:系統的數據分析不是一次性的,而是按照必定的時間頻率反覆計算,於是整個處理鏈條中的各個環節須要按照必定的前後依賴關係緊密銜接,即涉及到大量任務單元的管理調度,因此,項目中須要添加一個任務調度模塊(此處可由以前講的azkaban替代OOZIE)。
1.3.數據展示
數據展示的目的是將分析所得的數據進行可視化,以便運營決策人員能更方便地獲取數據,更快更簡單地理解數據。可以使用springmvc+echarts的簡單架構實現。
2、模塊開發——數據採集
2.1.需求
數據採集的需求廣義上來講分爲兩大部分。
1)是在頁面採集用戶的訪問行爲,具體開發工做:
一、開發頁面埋點js,採集用戶訪問行爲
二、後臺接受頁面js請求記錄日誌
此部分工做也能夠歸屬爲「數據源」,其開發工做一般由web開發團隊負責
2)是從web服務器上匯聚日誌到HDFS,是數據分析系統的數據採集,此部分工做由數據分析平臺建設團隊負責,具體的技術實現有不少方式:
Shell腳本
優勢:輕量級,開發簡單
缺點:對日誌採集過程當中的容錯處理不便控制
Java採集程序
優勢:可對採集過程實現精細控制
缺點:開發工做量大
Flume日誌採集框架
成熟的開源日誌採集系統,且自己就是hadoop生態體系中的一員,與hadoop體系中的各類框架組件具備天生的親和力,可擴展性強
2.2.技術選型
在點擊流日誌分析這種場景中,對數據採集部分的可靠性、容錯能力要求一般不會很是嚴苛,所以使用通用的flume日誌採集框架徹底能夠知足需求。
本項目即用flume來實現日誌採集。
Flume日誌採集系統搭建
一、數據源信息
本項目分析的數據用nginx服務器所生成的流量日誌,存放在各臺nginx服務器上,如:
/var/log/httpd/access_log.2015-11-10-13-00.log
/var/log/httpd/access_log.2015-11-10-14-00.log
/var/log/httpd/access_log.2015-11-10-15-00.log
/var/log/httpd/access_log.2015-11-10-16-00.log
二、數據內容樣例
數據的具體內容在採集階段其實不用太關心。
58.215.204.118 - - [18/Sep/2013:06:51:35 +0000] "GET /wp-includes/js/jquery/jquery.js?ver=1.10.2 HTTP/1.1" 304 0 "http://blog.fens.me/nodejs-socketio-chat/" "Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0"
字段解析:
一、訪客ip地址: 58.215.204.118
二、訪客用戶信息: - -
三、請求時間:[18/Sep/2013:06:51:35 +0000]
四、請求方式:GET
五、請求的url:/wp-includes/js/jquery/jquery.js?ver=1.10.2
六、請求所用協議:HTTP/1.1
七、響應碼:304
八、返回的數據流量:0
九、訪客的來源url:http://blog.fens.me/nodejs-socketio-chat/
十、訪客所用瀏覽器:Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0
三、日誌文件生成規律
基本規律爲:
當前正在寫的文件爲access_log;
文件體積達到256M,或時間間隔達到60分鐘,即滾動重命名切換成歷史日誌文件;
形如: access_log.2015-11-10-13-00.log
固然,每一個公司的web服務器日誌策略不一樣,可在web程序的log4j.properties中定義,以下:
log4j.appender.logDailyFile = org.apache.log4j.DailyRollingFileAppender log4j.appender.logDailyFile.layout = org.apache.log4j.PatternLayout log4j.appender.logDailyFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n log4j.appender.logDailyFile.Threshold = DEBUG log4j.appender.logDailyFile.ImmediateFlush = TRUE log4j.appender.logDailyFile.Append = TRUE log4j.appender.logDailyFile.File = /var/logs/access_log log4j.appender.logDailyFile.DatePattern = '.'yyyy-MM-dd-HH-mm'.log' log4j.appender.logDailyFile.Encoding = UTF-8
四、Flume採集實現
Flume採集系統的搭建相對簡單:
一、在個web服務器上部署agent節點,修改配置文件
二、啓動agent節點,將採集到的數據匯聚到指定的HDFS目錄中
以下圖:
版本選擇:apache-flume-1.7.0
採集規則設計:
一、採集源:nginx服務器日誌目錄
二、存放地:hdfs目錄/home/hadoop/weblogs/
採集規則配置詳情
agent1.sources = source1 agent1.sinks = sink1 agent1.channels = channel1 # Describe/configure spooldir source1 #agent1.sources.source1.type = spooldir #agent1.sources.source1.spoolDir = /var/logs/nginx/ #agent1.sources.source1.fileHeader = false # Describe/configure tail -F source1 #使用exec做爲數據源source組件 agent1.sources.source1.type = exec #使用tail -F命令實時收集新產生的日誌數據 agent1.sources.source1.command = tail -F /var/logs/nginx/access_log agent1.sources.source1.channels = channel1 #configure host for source #配置一個攔截器插件 agent1.sources.source1.interceptors = i1 agent1.sources.source1.interceptors.i1.type = host #使用攔截器插件獲取agent所在服務器的主機名 agent1.sources.source1.interceptors.i1.hostHeader = hostname #配置sink組件爲hdfs agent1.sinks.sink1.type = hdfs #a1.sinks.k1.channel = c1 #agent1.sinks.sink1.hdfs.path=hdfs://hdp-node-01:9000/weblog/flume-collection/%y-%m-%d/%H%M%S #指定文件sink到hdfs上的路徑 agent1.sinks.sink1.hdfs.path= hdfs://hdp-node-01:9000/weblog/flume-collection/%y-%m-%d/%H-%M_%hostname #指定文件名前綴 agent1.sinks.sink1.hdfs.filePrefix = access_log agent1.sinks.sink1.hdfs.maxOpenFiles = 5000 #指定每批下沉數據的記錄條數 agent1.sinks.sink1.hdfs.batchSize= 100 agent1.sinks.sink1.hdfs.fileType = DataStream agent1.sinks.sink1.hdfs.writeFormat =Text #指定下沉文件按1G大小滾動 agent1.sinks.sink1.hdfs.rollSize = 1024*1024*1024 #指定下沉文件按1000000條數滾動 agent1.sinks.sink1.hdfs.rollCount = 1000000 #指定下沉文件按30分鐘滾動 agent1.sinks.sink1.hdfs.rollInterval = 30 #agent1.sinks.sink1.hdfs.round = true #agent1.sinks.sink1.hdfs.roundValue = 10 #agent1.sinks.sink1.hdfs.roundUnit = minute agent1.sinks.sink1.hdfs.useLocalTimeStamp = true # Use a channel which buffers events in memory #使用memory類型channel agent1.channels.channel1.type = memory agent1.channels.channel1.keep-alive = 120 agent1.channels.channel1.capacity = 500000 agent1.channels.channel1.transactionCapacity = 600 # Bind the source and sink to the channel agent1.sources.source1.channels = channel1 agent1.sinks.sink1.channel = channel1
啓動採集
在部署了flume的nginx服務器上,啓動flume的agent,命令以下:
bin/flume-ng agent --conf ./conf -f ./conf/weblog.properties.2 -n agent
注意:啓動命令中的 -n 參數要給配置文件中配置的agent名稱
3、模塊開發——數據預處理
3.1主要目的:a.過濾「不合規」數據;b.格式轉換和規整;c.根據後續的統計需求,過濾分離出各類不一樣主題(不一樣欄目path)的基礎數據
3.2實現方式:開發一個mr程序WeblogPreProcess(內容太長,見大數據hadoop之大型互聯網電商公司網站日誌分析、web日誌數據清洗)
public class WeblogPreProcess { static class WeblogPreProcessMapper extends Mapper<LongWritable, Text, Text, NullWritable> { Text k = new Text(); NullWritable v = NullWritable.get(); @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); WebLogBean webLogBean = WebLogParser.parser(line); // WebLogBean productWebLog = WebLogParser.parser2(line); // WebLogBean bbsWebLog = WebLogParser.parser3(line); // WebLogBean cuxiaoBean = WebLogParser.parser4(line); if (!webLogBean.isValid()) return; k.set(webLogBean.toString()); context.write(k, v); // k.set(productWebLog); // context.write(k, v); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf); job.setJarByClass(WeblogPreProcess.class); job.setMapperClass(WeblogPreProcessMapper.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(NullWritable.class); FileInputFormat.setInputPaths(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); job.waitForCompletion(true); } }
運行mr對數據進行預處理
hadoop jar weblog.jar cn.itcast.bigdata.hive.mr.WeblogPreProcess /weblog/input /weblog/preout
3.3點擊流模型數據梳理
因爲大量的指標統計從點擊流模型中更容易得出,因此在預處理階段,可使用mr程序來生成點擊流模型的數據
3.3.1點擊流模型pageviews表
Pageviews表模型數據生成
代碼見工程 hadoop jar weblogpreprocess.jar \ cn.itcast.bigdata.hive.mr.ClickStreamThree \ /user/hive/warehouse/dw_click.db/test_ods_weblog_origin/datestr=2013-09-20/ /test-click/pageviews/
表結構:
(表定義及數據導入見6.2節)
3.3.2 點擊流模型visit信息表
注:「一次訪問」=「N次連續請求」
直接從原始數據中用hql語法得出每一個人的「次」訪問信息比較困難,可先用mapreduce程序分析原始數據得出「次」信息數據,而後再用hql進行更多維度統計
用MR程序從pageviews數據中,梳理出每一次visit的起止時間、頁面信息
代碼見工程 hadoop jar weblogpreprocess.jar cn.itcast.bigdata.hive.mr.ClickStreamVisit /weblog/sessionout /weblog/visitout
而後,在hive倉庫中建點擊流visit模型表
load data inpath '/weblog/visitout' into table click_stream_visit partition(datestr='2013-09-18');