閱讀62 返回首頁    go 小米 go 小米6


SaaS服務商如何通過數加平台統計業務流量

一、概述

因為自家公司是做B2B類Saas服務的,難免會產生精準計費的問題,所以在通過多套方案的選型及對比以後,我們最終確定了以下的方式進行自有業務平台的流量計算方案。因為涉及到具體的操作,所以閱讀本文的前提是我默認您已經具備了阿裏雲相關產品的使用經驗。

目前的流量構成主要為:

1.用戶訪問業務平台產品的頁麵響應流量,即http返回頁麵的大小。
2.用戶訪問業務平台中圖片所產品的流量,所有的圖片存放在OSS中,通過CDN暴露在公網訪問。
3.用戶的API請求產生的響應流量,即Json返回值頁麵的大小。

我們的目標:

1.我們的計費顆粒為按天計算,所以我們隻需要確保第二天能得到前一天的流量數據即可。對實時性的要求不是那麼的高。
2.需要所有的數據都參與運算,並且能支持多渠道的日誌來源。
3.需要支持重新計算,有些時候因為一些特定原因,需要重新獲取某個時間段的流量數據,需要得到和之前一致的數據結果(前提是原始日誌相同的情況下)。
4.不能產生大量成本,最好是不要購買服務器,不要進行太大的支出。
5.所有流量計算出的結果,按年、月、日、時存入Mysql數據庫,便於實時查表顯示給客戶。


二、流量統計流程

d1e55028a26f0732c4f34b052787df13.png


三、獲取訪問日誌

目前所有的訪問都基於HTTP展開,那麼無論是apache還是nginx都是自帶訪問日誌功能的,隻需要把這些文本日誌清洗一下存到數據庫就行了,或者有更簡單的方式,將這些日誌通過阿裏雲的日誌服務收集起來,然後定時投遞到數加的ODPS表裏即可。

這裏給一個日誌服務的傳送門:https://www.aliyun.com/product/sls

相對於自己收集日誌並清洗,我還是更加建議使用阿裏雲的日誌服務,查詢快且穩定、收費也低、客戶支持力度很棒、迭代速度很快。

值得一提的是,數加平台支持一鍵導入CDN日誌,如果你的業務恰恰好是全CDN加速的,那麼你隻需要收集CDN日誌就可以進行較為精準的流量統計了。

我們收集到的訪問日誌格式大概是這樣的:

[12/Nov/2017:00:09:15 +0800] 112.28.172.8 - 0 "https://www.xxx.com/Article/86892.html" "GET https://www.xxx.com/Public/css/style.css" 200 393 21427 HIT "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36" "text/css"

分割後按順序分別是:時間,訪問IP,代理IP,responsetime,referer,method,訪問URL,httpcode,requestsize,responsesize,cache命中狀態,UA頭,文件類型。

其中最重要的就是2個字段:URL、responsesize。
URL字段是整個訪問的URL路徑,可以用於分析文件類型和客戶平台。
Responsesize是指整個請求響應的數據大小。
你也可以結合httpcode和緩存命中來進行更精準的計算,我下麵的介紹不涉及這一塊內容,一通百通,明白後自己調整一下ODPS的SQL語句就行了。

日誌導入ODPS

如果我們需要將日誌數據導入到ODPS中,那麼需要完成ODPS表的創建,這一塊進入到數加平台即可完成,與我們平時開發中創建MYSQL、MSSQL表的方式差不多,隻是有些數據類型上的差異。同時ODPS表也支持了一個很重要也很有用的概念——分區。

你可以在創建ODPS表的時候,指定一個或多個字段來對某一些數據進行分區,常見的就是按時間分區,比如日誌時間格式化到小時級別用作分區,這樣就能把某個小時的數據置入特定分區。設置分區的目的主要是在後期運算、覆寫、重跑時更便利。

那麼日誌導入到ODPS的方式有幾種:
1.如果你的日誌在阿裏雲日誌服務中,直接配置一下ODPS投遞即可,具體查詢文檔還是比較簡單的,就不囉嗦了。
2.如果你的日誌數據在自建係統中,那麼可以考慮使用“數加平台的-數據集成”功能來完成數據的導入和同步,支持的數據庫種類超級多,具體請看文檔:https://help.aliyun.com/document_detail/53008.html ,市麵上90%的數據庫都支持的。

此處我們得到一個ODPS數據表名為:cdn_logs,裏麵存放的是所有的cdn訪問日誌,名字隻是演示,你可以自定義。我的建表語句是這樣的:

CREATE TABLE cdn_logs (
	station_node STRING COMMENT '節點',
	unix_time BIGINT COMMENT '訪問時間',
	method STRING COMMENT '請求方法',
	procotol STRING COMMENT '請求協議',
	domain STRING COMMENT '域名',
	uri STRING COMMENT '請求的uri',
	uri_parameter STRING COMMENT '請求參數',
	imgsrc_type BIGINT COMMENT '圖片壓縮類型ID',
	return_code BIGINT COMMENT '返回碼',
	rt BIGINT COMMENT '延時',
	request_size BIGINT COMMENT '請求大小',
	response_size BIGINT COMMENT '響應大小',
	hit_info STRING COMMENT '命中信息',
	client_ip BIGINT COMMENT '真實用戶IP',
	proxy_ip STRING COMMENT '中間代理ip',
	remote_address BIGINT COMMENT '客戶端IP',
	bacend_server STRING COMMENT '回源IP',
	refer_procotol STRING COMMENT '引用協議',
	refer_domain STRING COMMENT '引用域名',
	refer_uri STRING COMMENT '引用uri',
	refer_parameter STRING COMMENT '引用參數',
	content_type STRING COMMENT '請求返回類型',
	user_agent STRING COMMENT 'UA',
	port BIGINT COMMENT '客戶端口',
	transfer_success BIGINT COMMENT '傳輸是否成功',
	last_modify STRING COMMENT '服務器上文件的最後修改時間',
	user_info STRING COMMENT '用戶信息',
	traceid STRING COMMENT '訪問錯誤排查跟蹤id',
	sent_http_via STRING COMMENT 'http  via頭',
	reserve_1 STRING COMMENT '保留字段1',
	reserve_2 STRING COMMENT '保留字段2',
	reserve_3 STRING COMMENT '保留字段3'
)
PARTITIONED BY (
	log_date STRING COMMENT '日期分區',
	domain_id BIGINT COMMENT 'ID分區'
)
LIFECYCLE 100000;

四、進行離線計算任務配置

我們已經擁有了一個基礎數據表:cdn_logs,在此之外我們還需要創建2個表,分別為:
cdn_logs_format表——對cdn_logs表進行格式化後得到的進一步清洗數據,此處需要貼近業務進行各種DIY操作,這個表的生命周期建議是參考自己的日誌量來規劃,如果日誌少,就設為永久,否則設置成周期。建表語句如下:

CREATE TABLE cdn_logs_format (
	unix_time BIGINT COMMENT '訪問時間',
	uri_parent STRING COMMENT '首層目錄名',
	method STRING COMMENT '請求方法',
	procotol STRING COMMENT '請求協議',
	domain STRING COMMENT '域名',
	uri STRING COMMENT '請求的uri',
	return_code BIGINT COMMENT '返回碼',
	rt BIGINT COMMENT '延時',
	response_size BIGINT COMMENT '響應大小',
	client_ip BIGINT COMMENT '真實用戶ip',
	remote_address BIGINT COMMENT '客戶端ip',
	bacend_server STRING COMMENT '回源ip',
	refer_domain STRING COMMENT '引用域名',
	refer_uri STRING COMMENT '引用uri',
	content_type STRING COMMENT '請求返回類型',
	user_agent STRING COMMENT 'ua'
)
PARTITIONED BY (
	log_date STRING COMMENT '日期分區'
)
LIFECYCLE 100000;

aggr_product_traffic表——最終的流量統計結果表,這個表結果少,建議生命周期永久,建表語句:

CREATE TABLE aggr_product_traffic (
	clientcode STRING COMMENT '客戶端代碼',
	year BIGINT COMMENT '年',
	month BIGINT COMMENT '月',
	day BIGINT COMMENT '日',
	hour BIGINT COMMENT '小時',
	mi BIGINT COMMENT '分鍾',
	traffic BIGINT COMMENT '流量',
	create_at BIGINT COMMENT '創建匯總時的時間戳',
	targetdate STRING COMMENT '匯總結果時間'
)
COMMENT '產品流量匯總表'
PARTITIONED BY (
	aggr_date STRING COMMENT '分區時間',
	product STRING COMMENT '產品代碼'
)
LIFECYCLE 100000;

把準備工作準備完成後,我們需要在數加裏配置對應的離線任務,在配置離線任務之前可以使用數加的“數據開發IDE”進行試驗,這裏需要注意,試驗是有成本的,但是很便宜,一瓶可樂錢大概可以玩一天。

開始之前,我們需要明白幾個關鍵詞:

虛節點:沒意義的節點,沒實際功能,虛擬出來便於理解整體邏輯關係的,可建可不建。

任務節點:說白了就是一個具體的操作,比如跑SQL語句或同步數據。

調度周期:這個很重要,關係到了你的任務顆粒細度,可以設置為分鍾、小時、天、周、月,大部分是夠用的。

離線任務:我們一定要明白一個概念,所有在數加平台運行的離線任務都是非實時的,所有的ODPS表查詢也都是非實時的,雖然SQL語句查詢的方式很像實時數據庫,但是你不能直接連接到ODPS進行業務數據實時展示,所以在流程的最後,我們一般需要放一個數據同步的節點,用來將運算完成的ODPS數據同步到自己的數據庫中,進了自己數據庫還不是任你揉捏~

進入到數加平台的“數據開發”模塊,在左側創建任務,此處我們選擇工作流任務,便於理解整體的邏輯,以下是我的實現邏輯,不一定適合所有人,請自行調整(圖片看不清請放大看):

3e6f9a0b854558d3714579992a6243a6.png

格式化cdn日誌,我是通過SQL語句結合一些小技巧來完成的,因為我們是一家to B的Saas服務商,所以在文件的存儲上有自己的規律,比如:

https://www.xxx.com/client123/logo.png
https://www.xxx.com/client999/logo.png

分別代表了兩個客戶的文件URL,我們需要通過字符串切割,把客戶標識找出來,也就是連接中 client123和client999 這一部分。
以下是我的SQL語句:

ALTER TABLE cdn_logs_format DROP if exists PARTITION (log_date='${bdp.system.bizdate}');
INSERT into TABLE cdn_logs_format PARTITION (log_date='${bdp.system.bizdate}')
SELECT unix_time
	, TOLOWER(split_part(uri, '/', 2)) AS uri_parent
	, method, procotol, domain, uri, return_code
	, rt, response_size, client_ip, remote_address, bacend_server
	, refer_domain, refer_uri, content_type, user_agent
FROM cdn_logs
WHERE log_date = '${bdp.system.bizdate}'

上麵的語句中,最核心的其實就3個部分。

第一部分是維護cdn_logs_format表的特定分區,判斷是否存在髒數據,如果存在,刪除掉這個分區的內容。${bdp.system.bizdate}這個是內置變量,最終運行時會被替換為日期。

第二部分是通過split_part方法切割出url中的第一級目錄,也就是我們業務中的客戶標識部分。

第三部分是把查詢到的內容INSERT into到cdn_logs_format表中。

在完成了基礎日誌的格式化之後,我們需要對同一個客戶的訪問請求進行合並匯總,需要用到下麵的SQL語句:

ALTER TABLE aggr_product_traffic DROP IF EXISTS PARTITION (product = 'emp', aggr_date = '${bdp.system.bizdate}');

INSERT INTO TABLE aggr_product_traffic PARTITION (product = 'emp', aggr_date = '${bdp.system.bizdate}')
SELECT uri_parent AS clientcode
	, datepart(TO_DATE(log_date, 'yyyymmdd'), 'yyyy') AS year
	, datepart(TO_DATE(log_date, 'yyyymmdd'), 'mm') AS month
	, datepart(TO_DATE(log_date, 'yyyymmdd'), 'dd') AS day
	, datepart(TO_DATE(log_date, 'yyyymmdd'), 'hh') AS hour
	, datepart(TO_DATE(log_date, 'yyyymmdd'), 'mi') AS mi
	, SUM(response_size) AS traffic
	, UNIX_TIMESTAMP(TO_DATE('${bdp.system.bizdate}', 'yyyymmdd')) AS create_at
	, to_char(TO_DATE('${bdp.system.bizdate}', 'yyyymmdd'), 'yyyy-mm-dd') AS targetdate
FROM cdn_logs_format
WHERE log_date = '${bdp.system.bizdate}'
GROUP BY uri_parent,log_date

上麵的語句中,核心其實就是group by + sum方法,做過關係型數據庫開發的同學一定很熟悉,我也就不贅述了。
至此我們就通過2個任務分別完成了基礎日誌的處理及流量數據的合並匯總。

五、運算結果同步到自有數據庫

這一步就不截圖展示了,很簡單,配置好數據源,一一對應數據庫字段即可,傻瓜操作,so easy!然後找你的開發同學做個好看的圖表,出來後,你的客戶看到的就是這個效果:

d166a5c0b4b08039695e97379bb0c22e.png

六、後記

因為隻是偏場景方向的某一個側重點展示,所以對經常使用數加平台的同學來說這個可能太淺了,幫助不大。但是對未接觸過數加產品的同學來說,其實數加有好多產品都挺有意思的,隻不過因為大數據這一塊因為大家領域、場景重疊的少導致分享的東西很難產生共鳴。

不得不說,阿裏雲的大數據產品真的做的還不錯,開箱即用,如果大家感興趣的,後麵也會寫幾篇阿裏雲機器學習方麵的分享。


博客原文鏈接:https://qipangzi.com

最後更新:2017-11-13 23:04:23

  上一篇:go  阿裏雲推薦碼2017活動替代方案同樣優惠
  下一篇:go  阿裏重啟維護Dubbo了