到新公司三個月了,上個月作的是Beacon項目,詳細的設計思想尚未寫文檔。這兩週開始搞Hadoop,開始閱讀相關論文。開始編寫MR程序。開始寫java,大學時用java較多,工做後就一直在用c/c++/php/shell/js 等。並不排斥語言,各有各的優劣。只是須要從底層的角度去理解各程序的運行態。php
Hadoop的原理架構方面的文章等再深刻了解以後再寫。先寫下上週作的RTB日誌分析MR程序的設計,懶得畫圖,僅用文字表述。java
需求:
1. 讀入RTB log日誌,對log日誌進行分析 按照特定格式輸出,並對某些字段作 異常 檢測。日誌爲json格式,順序無關。默認輸入格式不可靠(必填字段 可能會沒有 等)
2. 對錯誤的字段進行出錯次數統計,並記錄錯誤日誌。c++
現有代碼:
1. RTB字段對應的一個類,字段 爲類的屬性,序列化及反序列化時使用。相似於C/C++的結構體
2. 一次讀入字段,對每一個值進行parse,在Parse的輔助類內添加異常報警代碼。大量的if else 語句
3. 依賴於公共的RTB對象,RTB對象屬性變化時,線上對他依賴的程序會宕機。(強制檢測,是好處,亦是風險)。shell
現有代碼的不足:
1. 代碼量多,代碼邏輯很多重複。過量的if語句
2. 報警相關的數據存儲結構跨越三個類,三個文件。輔助類型判斷解析類承載了業務邏輯。
3. 字段變動或者增刪時 改動較多,庫的依賴將致使牽一髮而動全身。維護成本較高。
4. 配置相關的代碼文件跨越度太大,用的地方過於隨意。機器間遷移運行時沒法經過代碼直觀知道配置,易人維護成本高。環境遷移調試成本高。
json
現有代碼的優勢:
1. 主要業務邏輯代碼直觀,RTB字段封裝爲jar類庫,後期增長輸入配置時,便於接入。字段類型變動時會致使依賴於其的程序宕機(也是一種好處,強制檢測)
2. RTB字段設計爲類屬性,代碼效率較高。運行時直接棧上讀取。數組
新業務環境下的改進: 數據結構
目標:
1. 業務邏輯清晰,輸入輸出字段對應關係明確。
2. 字段的異常檢測統一處理,統一報告錯誤。不能遍處理字段遍檢測,由於輸入字段可能沒有,這種狀況下若是對應的目標字段不容許爲空就悲催了
3. 簡化配置:去除沒必要要的配置。如報警時的字段名稱配置。配置統一處理,統一管理。
4. warning異常時,記錄原始輸入字段
架構
設計一:
設計的數據結構:
LinkedHashMap保存輸入字段與目標字段的映射關係。 RecordField 爲自定義對象類。保存了目標Key, 目標Value,異常檢測標準。
private Map<String, RecordField> mapfields = new LinkedHashMap<String, RecordField>();
初始化時以下:
mapfields.put("vendor_id", new RecordField("vendorID", RecordField.E_NOT_EMPTY|RecordField.E_DIGITAL|RecordField.E_WARN));
mapfields.put("request_time", new RecordField("requestTime", RecordField.E_NOT_EMPTY|RecordField.E_FATAL));
mapfields.put("user_id", new RecordField("userID", RecordField.E_NOT_EMPTY));
mapfields.put("campaign_id", new RecordField("campaignID", RecordField.E_NOT_EMPTY));函數
異常處理:
RecordField 保存異常檢測策略,檢測時遍歷每一個字段,調用其Check方法得到異常結果便可。
交付代碼時老員工強制要求使用現有的RTB類,出於尊重,只能用了。但又不想大量的if else語句及字符串的相等判斷;因而有了設計二,主要用到了java的反射。oop
設計二:
linkedhaspmap 保存原始輸入與目標輸出之間的映射關係; 對現有類(包含近百個public屬性字段)的每一個屬性編寫Set方法,方法名爲void SetFieldName(String), 基本是體力勞動了,基本是對字段的類型轉換複製(上一個設計中爲制定 了一些配置規則自動轉換) 對每一個原始輸入字段,找到匹配的目標字段,經過目標字段反射得到其Set方法, 調用Set賦值;靜態變量保存反射的函數地址,因反射查找函數的過程較慢 異常檢測:對須要作異常檢測的字段專門編寫其對應的Check方法,並保存須要作檢測的字段數組,字段映射完成後遍歷須要檢測的字段,根據字段名獲取對應的Check方法並 執行