【Cloud TIPS】雲端儲存服務的 Log by qrtt1 | CodeData
top

【Cloud TIPS】雲端儲存服務的 Log

分享:

隨著將服務部署於雲端主機接受度提昇,越來越多公司開始在設計階段就思考著在架構設計上直接將『雲端』上的服務納入解決方案。在這樣的設計前提,將檔案儲存於 local 端不再是件理所當然的事。因為要考慮到所有的『機器』都是動態地增減這件事,許多的資料存放在䨌端儲存服務就成為自然的選項。這裡的『機器』可以是實體機、虛擬機或是 Container(像是 Docker 或相近的技術),拿近期 AWS Lambda 為例,它就單純提供你具有『運算能力的單位』並在手冊時時提供你,不該對底層的機器有任何假設,也不該依賴底的檔案系統上存的檔案。雲端儲存服務除了一般的存放資料需求,多數也被用來作為網站的靜態檔案存取來源,也能接上 CDN 提昇跨區服務的品質。像是 AWS CTO Werner Vogels 的部落格 All Things Distributed 就使用 AWS S3 + CloudFront 將他部落格的內容放在上面。除了作為一般靜態網頁之後,在上面放置多媒體影音資料也相當普遍。

將檔案都放上去之後,除了每個月會收到帳單後,能做簡單的查驗之外,它提供的資料有許多訊息值得去挖掘。像是有些服務是建構在這些 Cloud Provider 之上的,需要另外向客戶拆帳,那麼帳單計算的依據就得由這些 Log 來。本質上,這些 Log 都是一般 Web Server 的 Access Log,唯一的麻煩就是格式或有不同,這是需要另外處理的。

Hadoop & Spark

在這回的 Cloud Tips 主要記錄一些使用 Hadoop MapReduce 或 Spark 處理 log 時的設定,或是『地雷』。

看到 Hadoop 或 Spark 直覺上會處理『海量資料』,接著會想到需要建立 Cluster 並維運這些沉重的負擔。其實不用想得那麼嚴重,作為 ETL 工具它是個不錯的選擇,無論何種量級的資料都跑得不錯,覺得跑得不夠快就建多台一點再跑。平時不趕時間的情況,使用少量的 Slave 或是 Standalone 甚至 Development 模式執行就足夠。

單純提到 log 就用這樣的『牛刀』是否太大少小用呢?你可能會想同一批次不到 TB 或更小至不到 GB 的工作而已,也許單純使用 linux 處理文字資料的指令,像是 grep 或 awk 就能在可接受的時間內勝任。

我們需要考慮的不只是資料的絕對大小,而是單位時間內處理的速度!並期望隨著資料增加,也能透過擴大 cluster 大小來將單位時間內處理的速度維持在一定的水準。這麼想,就會覺得使用 Hadoop 或 Spark 作為 ETL 工作相當合理(若讀者的可限定固定的 cloud provider,像是 Google Cloud 可以簡單地使用 Big Query 服務來做到相同的事。)

Log 與存取設定

不同的雲端儲存服務都有它自己的 Access Log 儲存位置:

  1. AWS S3 Server Access Logging
  2. AWS CloudFront Access Log
  3. Google Cloud Access Log
  4. Azure: Monitor a storage account in the Azure portal

需依手冊的說明,知道他是存儲在什麼地方,或是怎麼把它開啟並存到設定的位置。有這些 log 後,接下來就是做些 ETL (Extract, Transform, Load) 的工,將它重製後加以保存或是再運用,例如將它再匯入 ElasticSearch 配合 Kibana 做視覺化的診斷資訊。

Hadoop FileSystem

處理雲端儲存服務上的 log,無論是存取儲存服務本生產生的 log,或是使用 log 遞送服務(像是 Logstash 或 fluentd)上傳的服務,要先知道 Hadoop FileSystem。

這並不是在談論 HDFS (Hadoop Distributed File System),它是 Hadoop FileSystem 支援的一種 FileSystem,也是廣為人知 Hadoop 預設支援的 FileSystem。對於處理 log 這個工作,我們比較把重心放在『轉換』的工作而非分散式儲存,因為已經存了一份在雲端儲存服務上了。

Hadoop FileSystem 是一組標準 API,描述在 Hadoop 的世界觀裡,FileSystem 提供哪些功能,並將它抽象化讓 Hadoop 生態系能接上不同的 FileSystem 實作:

  1. 在 Hadoop 0.10.0 版就開始支援 Amazon S3 作為它的 FileSystem
  2. Azure Blob Storage 的 FileSystem 支援會在 Hadoop 2.7,若是使用 Hadoop 2.7 前的版本也只需要加入 JARs 並完成設定就能使用。
  3. Google Cloud Storage Connector 是 Google 實作的 Cloud Storage FileSystem

要使用不同實作的 Hadoop FileSystem,其實只要確認相依的 JARs 有放在安裝目錄,並有設定好認證資訊即可,你可以放在設定檔,隨著部署程式一起安裝到 Server 上,或寫在程式內。以 AmazonS3 為例,在程式內先設好 fs.s3n.awsAccessKeyId fs.s3n.awsSecretAccessKey 就能在 Hadoop 與 Spark 直接存儲 S3 上的檔案或目錄:

Configuration conf = new Configuration();
setConf(conf);

conf.set("fs.s3n.awsAccessKeyId", ...);
conf.set("fs.s3n.awsSecretAccessKey", ...);

不同的 FileSystem 設定方式(或說難易度)不同,拿 Google Cloud Storage 的 gcs-core-default.xml 設定來看,它的認證方式有 2 種。

  1. 使用 OAuth 2.0 授權的 user 驗證
  2. 使用 Service Account(透過 PKC12 憑證檔案驗證)

這時就要注意有確實把需要的檔案複製到 Server 端,才能讓 gcs:// FileSystem 正確運作。

需特別注意,當使用 Service Account 證認的方式,在 p12 憑證檔不慎外流時,那就重新產生一組並把舊的刪除。因為它的密碼是無法變更的 notasecret。在 Google Cloud Console 產生時沒有讓使用者設定的地方,程式碼實作也是 hardcode 在裡面的,短期內應該不會讓使用者自訂密碼。

PS. 沒有特別提 Spark 是因為它就是直接使用 Hadoop FileSystem API。

Hadoop InputFormat

執行 Map Reduce 工作時,需要指定資料來源(檔案)。這項工作就落在 InputFormat 類別的身上,一般文字資料最常用的 InputFormat 為 TextInputFormat

  • Hadoop 1.x org.apache.hadoop.mapreduce.lib.input.TextInputFormat
  • Hadoop 2.x org.apache.hadoop.mapred.TextInputFormat

Hadoop 1.x 或 2.x 的實作方式差異不大,除了 package 不同,皆是繼承至 FileInputFormat,以 2.x 為例,它的繼承樹為:

java.lang.Object
  extended by org.apache.hadoop.mapred.FileInputFormat<LongWritable,Text>
      extended by org.apache.hadoop.mapred.TextInputFormat

由於實作上的變異不大,所以無論哪一個版本,它們的行為都換一致的。而有個重要的特性會影響到 log 處理,在 FileInputFormat,針對『隱藏檔』的篩選實作為:

private static final PathFilter hiddenFileFilter = new PathFilter() {
    public boolean accept(Path p) {
        String name = p.getName();
        return !name.startsWith("_") && !name.startsWith(".");
    }
};

簡而言之,所有底線 _ 與點 . 開頭的檔名都視為隱藏檔,在 FileInputFormat 製作處理檔案列表時,會略含有這些特徵的檔名。當需要處理的 log 含有這樣的特徵時,你需要有能處理它們的 TextInputFormat。可以簡單繼承 FileInputFormat 並覆寫下列的 method 提供新的 file filter:

protected FileStatus[] listStatus(JobConf job) throws IOException { 
    ...
}

注意檔名

知道 FileInputFormat 的特性後,來看個實際的例子!以 Google Cloud Storage 來說,它可以設定 log prefix,格式如下:

gs://<bucket_name>/<object_prefix>_usage_<timestamp>_<id>_v0
gs://<bucket_name>/<object_prefix>_storage_<timestamp>_<id>_v0

設定的指令範例為:

gsutil logging set on -b gs://example-logs-bucket \
    [-o log_object_prefix ] gs://example-bucket

雲端存儲空間沒有一般檔案系統的『目錄』概念,但在 UI 上會透過 / 字元來模擬,製造出巢狀結構的感覺,而由 bucket 起算到 / 前的字串,就是 prefix。若我們即 example-bucket 設定 logging 指令如下:

gsutil logging set on< -b gs://example-logs-bucket gs://example-bucket

那麼 log 就可以是下列的型式(由於沒有設 log_object_prefix 變成空字串),你會看到檔名就是 _ 開頭的:

gs://example-logs-bucket/_storage_1234_5678_v0

若你想要模擬出目錄的效果:

gsutil logging set on -b gs://example-logs-bucket -o 'my_prefix/' gs://example-bucket

檔案在 my_prefix 目錄下仍是 _ 開頭的:

gs://example-logs-bucket/my_prefix/_storage_1234_5678_v0

對於這種『設定失誤』的情況,那就會需提供特殊的 InputFormat 來處理。有過痛苦的經驗後,就會學到應該設為:

gsutil logging set on -b gs://example-logs-bucket \
    -o 'my_prefix/log' gs://example-bucket
gs://example-logs-bucket/my_prefix/log_storage_1234_5678_v0
分享:
按讚!加入 CodeData Facebook 粉絲群

相關文章

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

關於作者

目前在一家網路應用軟體公司擔任開發工作,對多媒體處理與雲端應用充滿興趣,工作之餘亦常整理開發經驗分享於網路或於社群活動時進行分享。

熱門論壇文章

熱門技術文章