簡介: 日誌是任何計算系統中一個必不可少的部分,支持從審計到錯誤管理等功能。隨着日誌的發展和日誌來源數量的不斷增加(比如在雲環境中),有必要提供一個可擴展的系統來高效處理日誌。這篇實踐將探討如何在典型 Linux 系統上使用 Apache Hadoop 來處理日誌。
日誌形態千差萬別,但隨着應用程序和基礎架構的發展,結果產生了大量對用戶有用的分佈式數據。從 Web 和郵件服務器到內核和引導日誌,許多現代的服務器擁有豐富的信息集。大量的分佈式數據是 Apache Hadoop 的完美應用,就像日誌文件(按時間排序的結構化文本數據)一樣。
您可以使用日誌處理來提取各種信息。其中最常用的一種用法是提取錯誤,或是對某個系統中的一些事件(比如登錄失敗)的發生次數進行計數。您還可以提取某些類型的性能數據,比如每秒連接數或每秒處理的事務數。其他有用的信息包括 Web 日誌中的站點訪問量(減少)的提取(映射)和構造。這一分析除了支持檢測文件訪問統計之外,還支持對惟一用戶訪問的檢測。
這些練習將爲您提供以下幾方面的實踐:
- 建立一個簡單的 Hadoop 環境並運行它
- 與 Hadoop 文件系統 (HDFS) 進行交互
- 編寫一個簡單的 MapReduce 應用程序
- 編寫一個過濾的 Apache Pig 查詢
- 編寫一個累計的 Pig 查詢
要從這些練習中獲得最大的益處,您應當掌握 Linux® 的基本應用知識。對虛擬設備有一些瞭解也有助於建立一個簡單的環境。
1.建立一個簡單的 Hadoop 環境並運行它
要建立 Hadoop 環境並運行它,有兩種方法。第一種是安裝 Hadoop 軟件,然後針對您的環境(最簡單的情況是一個單節點實例,其中所有的守護程序都在單個節點上運行)對其進行配置。參見 用 Hadoop 進行分佈式數據處理,第 1 部分:入門 以瞭解有關的詳細信息。
第二種(也是較爲簡單的一種)方法是通過使用 Cloudera 的 Hadoop Demo VM(包含一個 Linux 映像和一個預配置的 Hadoop 實例)。Cloudera 虛擬機 (VM) 運行於 VMware、基於 Kernel 的虛擬機或 Virtualbox 之上。
選擇一種方法,並完成安裝。然後,完成以下任務:
- 通過發出一個 HDFS
ls
命令來驗證 Hadoop 是否正在運行。
HDFS 是一種專用的文件系統,用來管理一個 Hadoop 集羣內的數據和副本,並將它們分配給各個計算節點,以便高效處理它們。儘管 HDFS 是一種專用的文件系統,但它仍然可以實現許多典型的文件系統命令。要檢索 Hadoop 的幫助信息,可發出
hadoop dfs
命令。請執行以下任務:
- 在 HDFS 內創建一個測試子目錄。
- 使用
copyFromLocal
將一個文件從本地文件系統移動到 HDFS 子目錄中。 - 對於額外的練習,請使用
hadoop dfs
命令查看 HDFS 內的文件。
編寫一個單詞數映射和縮減應用程序非常簡單。使用本文中演示的 Ruby 示例,開發一個 Python 映射和縮減應用程序,並在樣例數據集上運行它們。回想一下,Hadoop 對映射的輸出進行了排序,所以詞語很可能是連續的,這爲縮減程序 (reducer) 提供了一種有用的優化。
Pig 允許您構建一個簡單的、可轉換成 MapReduce 應用程序的腳本。在本練習中,您提取了所有的日誌條目(來自 /var/log/messages),這些日誌條目中包含單詞 kernel: 和單詞 terminating。
- 創建一個根據預定義的標準提取所有日誌行的腳本。
- 編寫一個聚合 Pig 查詢
日誌消息由 Linux 內核(比如 kernel
或 dhclient
)中的各種來源生成。在本例中,您需要找出生成日誌消息的各種來源,以及每個來源生成的日誌消息數量。
- 創建一個對每個日誌來源生成的日誌消息數進行計數的腳本。習解決方案
具體的輸出取決於特定的 Hadoop 安裝和配置
清單 1. 在 HDFS 上執行一個 ls 操作
$ hadoop dfs -ls / drwxrwxrwx - hue supergroup 0 2011-12-10 06:56 /tmp drwxr-xr-x - hue supergroup 0 2011-12-08 05:20 /user drwxr-xr-x - mapred supergroup 0 2011-12-08 10:06 /var $ |
所顯示文件的多少取決於具體的使用。
在
練習 2 中,您在 HDFS 內創建了一個子目錄,並將一個文件複製到這個子目錄中。請注意,您是通過將內核消息緩衝器移動到某個文件中來創建測試數據的。對於額外的練習,請使用
cat
命令(參見
清單 2)查看 HDFS 內的文件。
清單 2. 操作 HDFS
$ dmesg > kerndata $ hadoop dfs -mkdir /test $ hadoop dfs -ls /test $ hadoop dfs -copyFromLocal kerndata /test/mydata $ hadoop dfs -cat /test/mydata Linux version 2.6.18-274-7.1.el5 ([email protected])... ... e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX $ |
練習 3 的解決方案:編寫一個簡單的 MapReduce 應用程序
清單 3. 用 Python 編寫的映射應用程序
#!/usr/bin/env python import sys for line in sys.stdin: line = line.strip() words = line.split() for word in words: print '%s\t1' % word |
提供了縮減應用程序。
清單 4. 用 Python 編寫的縮減應用程序
#!/usr/bin/env python from operator import itemgetter import sys last_word = None last_count = 0 cur_word = None for line in sys.stdin: line = line.strip() cur_word, count = line.split('\t', 1) count = int(count) if last_word == cur_word: last_count += count else: if last_word: print '%s\t%s' % (last_word, last_count) last_count = count last_word = cur_word if last_word == cur_word: print '%s\t%s' % (last_word, last_count) |
說明了在 Hadoop 中調用 Python MapReduce 示例的流程。
清單 5. 使用 Hadoop 測試 Python MapReduce
$ hadoop jar /usr/lib/hadoop-0.20/contrib/streaming/hadoop-streaming-0.20.2-cdh3u2.jar \ -file pymap.py -mapper pymap.py -file pyreduce.py -reducer pyreduce.py \ -input /test/mydata -output /test/output ... $ hadoop dfs -cat /test/output/part-00000 ... write 3 write-combining 2 wrong. 1 your 2 zone: 2 zonelists. 1 $ |
在 練習 4 中,您提取了 /var/log/messages 日誌條目,該條目同時包含了單詞 kernel: 和單詞 terminating。在這種情況下,您可以在本地模式下使用 Pig 查詢本地文件(參見 清單 6)。將文件加載到一個 Pig 關係(日誌)中,過濾其內容,直到只剩下內核消息,然後過濾結果關係,以便獲得終止消息。
清單 6. 提取所有的內核日誌消息 + 終止日誌消息
$ pig -x local grunt> log = LOAD '/var/log/messages'; grunt> logkern = FILTER log BY $0 MATCHES '.*kernel:.*'; grunt> logkernterm = FILTER logkern BY $0 MATCHES '.*terminating.*'; grunt> dump logkernterm ... (Dec 8 11:08:48 localhost kernel: Kernel log daemon terminating.) grunt> |
在
練習 5 中,提取日誌來源和根據 /var/log/messages 獲得的日誌消息計數。在這種情況下,需要爲查詢創建一個腳本,並在 Pig 的本地模式下執行它。在
清單 7 中,您加載了文件,並使用空格作爲分隔符對輸入進行解析。隨後將已劃分界限的字符串字段分配給指定的元素。使用 GROUP
運算符根據消息來源對消息進行分組,然後使用
FOREACH
運算符和 COUNT
來聚合您的數據。
清單 7. /var/log/messages 的日誌來源和計數腳本
log = LOAD '/var/log/messages' USING PigStorage(' ') AS (month:chararray, \ day:int, time:chararray, host:chararray, source:chararray); sources = GROUP log BY source; counts = FOREACH sources GENERATE group, COUNT(log); dump counts; |
執行結果如 清單 8 所示。
$ pig -x local logsources.pig ... (init:,1) (gconfd,12) (kernel:,505) (syslogd,2) (dhclient:,91) (localhost,1168) (gpm[2139]:,2) [gpm[2168]:,2) (NetworkManager:,292) (avahi-daemon[3345]:,37) (avahi-daemon[3362]:,44) (nm-system-settings:,8) $