日誌作為一種特殊的數據,對處理歷史數據、診斷問題以及了解系統活動等有著非常重要的作用。對數據分析人員、開發人員或者運維人員而言,日誌都是其工作過程中必不可缺的數據來源。
通常情況下,為節約成本,我們會將日誌設定一定的保存時間,只分析該時間段內的日誌,此類日誌稱之為「熱」日誌。這種做法,短期內可以滿足使用需求,但從長期來看,大量的歷史日誌被擱置,無法發揮其價值。
對於許多企業而言,對日誌分析的需求特徵通常為低時效和低頻率。並且在一個企業中,為偶發性的日誌分析去構建一套完整的日誌分析系統,無論在經濟成本還是運維成本上都是不划算的。如何在降低存儲成本的同時滿足大批量日誌的分析需求,是擺在企業面前的一道難題。
實施方案阿里雲從用戶角度出發,研發了一整套小而精的歷史日誌數據分析方案。利用阿里雲日誌服務 LOG(Log Service,簡稱LOG/原SLS)來投遞日誌,阿里雲對象存儲服務(Object Storage Service,簡稱OSS)來存儲日誌,Data Lake Analytics(DLA)來分析日誌。該方案有以下三個優勢:
LOG是針對實時數據一站式服務,在阿里集團經歷大量大數據場景錘鍊而成。提供日誌類數據採集、智能查詢分析、消費與投遞等功能,全面提升海量日誌處理/分析能力。LOG強大的日誌投遞能力,能夠從源頭對接各種類型的日誌格式,並且穩定地將日誌投遞到指定的位置。
OSS低廉的存儲成本,能夠讓您的日誌文件存儲任意長的時間。
DLA強大的分析能力,Serverless的架構,按掃描量收費。DLA可以對投遞到OSS上的日誌按年、按月、按日進行多維度的分區,提高日誌的命中率,降低掃描量,從而以極低的成本、極高的性能來完成大數據量歷史日誌分析。
例如,服務部署在雲伺服器ECS(Elastic Compute Service,簡稱ECS)集群上,該集群的每臺機器上都有一個記錄訪問情況的日誌access.log。我們需要提取access.log中的信息,並將過濾後的信息存儲至OSS上。本文檔將以此為例,詳細為您介紹實施步驟。
前提條件在開始實施步驟之前,需要先完成以下準備工作。
實施步驟步驟一:通過Logtail採集ECS日誌詳細操作請參見通過Logtail採集ECS日誌。
根據本示例中的日誌文件特點,Logtail配置如下所示。
模式選擇完整正則模式,需要提供完整正則表達式。
步驟二:投遞日誌到OSS詳細操作請參見投遞日誌到OSS,並且日誌服務投遞OSS使用Parquet存儲的相關配置。
在OSS投遞功能頁面,配置各項參數:
參數說明:
OSS Bucket和OSS Prefix設置日誌投遞到OSS的哪個目錄。
修改分區格式,將分區列的名字填入到目錄中,格式為分區列名=分區列值。
如圖所示,修改分區格式默認值,即一級分區列的列名為year,列值為%Y;二級分區列的列名為month,列值為%m;三級分區列的列名為day,列值為%d。
存儲格式設置為parquet。
壓縮方式設置為snappy,使用snappy算法對數據做壓縮,可以減少OSS Bucket存儲空間使用量。
日誌數據投遞到OSS中以後,就可以通過DLA讀取並分析OSS中的日誌。
步驟三:在DLA中創建OSS連接登錄DLA控制臺,登錄DMS,在DLA中創建一個到OSS的連接。語法如下:
CREATE SCHEMA oss_log_schema with DBPROPERTIES( catalog='oss', location = 'oss://myappbucket/sls_parquet/' );
location:日誌文件所在的OSS Bucket的目錄,需以/結尾表示目錄。myappbucket是OSS Bucket名字。
步驟四:在DLA中創建指向OSS日誌文件的外表(分區表)CREATE EXTERNAL TABLE sls_parquet ( content STRING, client STRING, process_id STRING, start_time STRING, total_time STRING, status STRING, original_sql STRING, rewritten_sql STRING ) PARTITIONED BY (year STRING, month STRING, day STRING) STORED AS PARQUET LOCATION 'oss://myappbucket/sls_parquet/';
「注意:
步驟五:使用MSCK命令更新分區信息外表創建成功後,執行MSCK REPAIR TABLE將分區信息同步到DLA中。MSCK命令只能識別符合DLA分區列命名規則的目錄,即分區列的目錄名為分區列名=分區列值。
<div class="code-tools"> <i class="theme-switch-btn"></i><i class="copy-btn"></i></div><pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="lang-sql hljs"><span class="pln">MSCK <span class="hljs-keyword">REPAIR</span> <span class="hljs-keyword">TABLE</span> sls_parquet</span><span class="pun">;</span></code></li></ol></pre><div class="pre-scrollbar-track" style="display: none;width: 100%;height: 4px;margin-bottom: 16px;"> <div class="pre-scrollbar-thumb" style="height: 100%;background-color: #d7d8d9;position: relative;"></div></div>
步驟六:查詢分區表數據分區信息同步完成後,使用SELECT語句對日誌進行查詢分析。例如,得到某一天查詢最慢的5條語句。
<div class="code-tools"> <i class="theme-switch-btn"></i><i class="copy-btn"></i></div><pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="lang-sql hljs"><span class="pln"><span class="hljs-keyword">SELECT</span> original_sql</span><span class="pun">,</span><span class="pln"> total_time </span></code></li><li class="L1"><code class="lang-sql hljs"><span class="pln">FROM sls_parquet </span></code></li><li class="L2"><code class="lang-sql hljs"><span class="pln">WHERE client</span><span class="pun">!=</span><span class="str">''</span><span class="pln"> </span></code></li><li class="L3"><code class="lang-sql hljs"><span class="pln">ORDER BY total_time DESC </span></code></li><li class="L4"><code class="lang-sql hljs"><span class="pln">LIMIT </span><span class="lit">5</span><span class="pun">;</span></code></li></ol></pre><div class="pre-scrollbar-track" style="display: none;width: 100%;height: 4px;margin-bottom: 16px;"> <div class="pre-scrollbar-thumb" style="height: 100%;background-color: #d7d8d9;position: relative;"></div></div>
後續操作上述示例中,日誌數據投遞OSS的存儲格式為Parquet格式,除了Parquet格式,LOG還可以將投遞文件的格式設置為JSON和CSV。詳細的配置,請參見JSON格式和CSV格式。
JSON格式當投遞文件的格式設置為JSON且無壓縮時,建表語句為:
CREATE EXTERNAL TABLE sls_json ( content STRING, client STRING, process_id STRING, start_time STRING, total_time STRING, status STRING, original_sql STRING, rewritten_sql STRING ) PARTITIONED BY (year STRING, month STRING, day STRING) STORED AS JSON LOCATION 'oss://myappbucket/sls_json/';當投遞文件的格式設置為JSON且使用標準Snappy壓縮時,建表語句為:
CREATE EXTERNAL TABLE sls_json_snappy ( content STRING, client STRING, process_id STRING, start_time STRING, total_time STRING, status STRING, original_sql STRING, rewritten_sql STRING ) PARTITIONED BY (year STRING, month STRING, day STRING) STORED AS JSON LOCATION 'oss://myappbucket/sls_json_snappy/' TBLPROPERTIES( 'text.compression'='snappy', 'io.compression.snappy.native'='true' );CSV格式當投遞文件的格式設置為CSV,不包含header,使用標準Snappy壓縮時,建表語句為:
CREATE EXTERNAL TABLE sls_csv_snappy ( content STRING, client STRING, process_id STRING, start_time STRING, total_time STRING, status STRING, original_sql STRING, rewritten_sql STRING ) PARTITIONED BY (year STRING, month STRING, day STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES( 'separatorChar'=',', 'quoteChar'='"', 'escapeChar'='\\' ) STORED AS TEXTFILE LOCATION 'oss://myappbucket/sls_csv_snappy/' TBLPROPERTIES( 'text.compression'='snappy', 'io.compression.snappy.native'='true', 'skip.header.line.count'='0' );當投遞文件的格式設置為CSV無壓縮,且包含header時,建表語句為:
CREATE EXTERNAL TABLE sls_csv ( content STRING, client STRING, process_id STRING, start_time STRING, total_time STRING, status STRING, original_sql STRING, rewritten_sql STRING ) PARTITIONED BY (year STRING, month STRING, day STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES( 'separatorChar'=',', 'quoteChar'='"', 'escapeChar'='\\' ) STORED AS TEXTFILE LOCATION 'oss://myappbucket/sls_csv/' TBLPROPERTIES( 'skip.header.line.count'='1' );