站設計與實現(xiàn)全解析)
又是一年畢業(yè)設計開題季群里刷到最多的題目就是“基于大數(shù)據(jù)爬蟲Hadoop的游戲購買網(wǎng)站設計與實現(xiàn)”。這個題目我前前后后帶過好幾屆學生自己也親手搭過完整的一版說句實話題目看著唬人拆開其實就三件事——爬蟲負責把游戲數(shù)據(jù)抓下來Hadoop負責把數(shù)據(jù)存得住、算得動網(wǎng)站負責把結果漂亮地擺出來。難點不在某一個環(huán)節(jié)而在三個環(huán)節(jié)怎么串成一條線。這篇就把我實際做這個項目時踩過的坑、驗證過的方案、寫論文時能撐起頁數(shù)的核心細節(jié)全部攤開講。無論你是剛拿到這個題目準備開題還是已經(jīng)寫到中期發(fā)現(xiàn)架構跑不通照著下面的思路去調整都能少走很多彎路。1. 項目整體設計與思路拆解1.1 題目到底在問什么先把這個題目的三層邏輯理清。第一層是數(shù)據(jù)來源也就是爬蟲部分。你要從游戲電商平臺、評分網(wǎng)站、游戲百科等站點采集游戲信息包括名稱、類型、價格、評分、開發(fā)商、發(fā)行日期、玩家評價數(shù)量這些字段。第二層是數(shù)據(jù)處理也就是Hadoop部分。采集到的數(shù)據(jù)是半結構化的JSON或者CSV數(shù)據(jù)量達到一定規(guī)模之后Excel和MySQL就扛不住了需要借助HDFS做分布式存儲用MapReduce或者Hive做離線統(tǒng)計分析。第三層是業(yè)務呈現(xiàn)也就是游戲購買網(wǎng)站。網(wǎng)站本身是一個典型的電商前臺展示游戲列表、詳情、搜索和模擬購買功能同時把Hadoop算出來的熱門游戲、評分排行、價格分布等結果可視化成報表頁面。很多學生在這個題目上翻車是因為把它當成三個獨立的子項目分開做最后拼不起來。正確的思路是爬蟲產(chǎn)出的數(shù)據(jù)必須按照Hadoop能夠直接消費的格式落地Hadoop的分析結果必須按照數(shù)據(jù)庫表或者JSON接口的形式輸出給網(wǎng)站調用。數(shù)據(jù)的流向一旦在設計階段沒有明確后期聯(lián)調就是噩夢。1.2 技術架構怎么選才不虛我建議采用分層架構每層只干一件事數(shù)據(jù)采集層Python Requests BeautifulSoup/Scrapy負責爬取和清洗數(shù)據(jù)數(shù)據(jù)存儲與計算層Hadoop HDFS存儲原始數(shù)據(jù)Hive做數(shù)據(jù)清洗和統(tǒng)計分析Sqoop把結果導出到MySQL業(yè)務應用層Spring Boot MyBatis MySQL ECharts負責網(wǎng)站后端接口和前端頁面展示這套架構的好處是每一層都有明確的輸入輸出寫論文的時候每一層都可以獨立成章。更重要的是它把一個看似復雜的系統(tǒng)拆成了“數(shù)據(jù)從哪來、數(shù)據(jù)怎么算、數(shù)據(jù)怎么用”三個問題對應的正是開題報告里“國內外研究現(xiàn)狀”“系統(tǒng)需求分析”“系統(tǒng)設計”“系統(tǒng)實現(xiàn)”這幾個必須寫的板塊。1.3 為什么一定要上Hadoop能不能不用這個問題開題答辯老師必問你心里要有底。如果你的數(shù)據(jù)量只有幾千條MySQL一個表就搞定了完全不需要Hadoop。但這個題目的意義在于處理“大數(shù)據(jù)”場景——爬蟲持續(xù)運行一個月游戲信息加上玩家評論和價格歷史記錄數(shù)據(jù)量可以輕松達到百萬條以上。這個時候HDFS的分布式存儲、MapReduce的并行計算、Hive的類SQL分析能力才有用武之地。另一個角度是技術學習價值。Hadoop生態(tài)的搭建過程本身涉及Linux操作、集群配置、網(wǎng)絡通信、分布式一致性等知識點一套流程走下來對大數(shù)據(jù)技術棧的理解會有一個質的提升。答辯的時候你說得出“為什么用Hive而不是直接寫MapReduce”“為什么需要Zookeeper協(xié)調集群”這比單純堆技術名詞有說服力得多。2. 大數(shù)據(jù)爬蟲子系統(tǒng)的核心實現(xiàn)2.1 爬蟲采集策略與字段設計爬蟲不能上來就寫代碼先把目標和字段定清楚。游戲購買網(wǎng)站需要的數(shù)據(jù)字段我實際項目里最終用的是這一套游戲名稱、英文名、封面圖URL游戲類型多標簽、開發(fā)商、發(fā)行商、發(fā)行日期當前價格、原價、折扣率玩家評分、評價數(shù)量、好評率游戲簡介、支持語言、最低配置字段設計的核心原則是“寧寬勿窄”。比如價格字段我建議把當前價格和歷史最低價都保存下來后面做價格分析和折扣趨勢預測時數(shù)據(jù)一下子就豐富了。同理游戲類型用多標簽逗號分隔存方便Hive里做explode操作統(tǒng)計各種類型的占比。采集策略上我用的是Scrapy框架加CrawlSpider。相比自己寫Requests循環(huán)Scrapy的并發(fā)下載、去重過濾、請求重試機制都是現(xiàn)成的爬取效率高很多。需要注意目標網(wǎng)站的robots協(xié)議和訪問頻率建議設置Download Delay在3到5秒之間既能減輕對方服務器壓力也能降低被封IP的風險。# Scrapy爬蟲核心配置示例 DOWNLOAD_DELAY 3.0 CONCURRENT_REQUESTS 8 RETRY_ENABLED True RETRY_TIMES 52.2 爬下來的數(shù)據(jù)怎么清洗和去重爬蟲拿到的是HTML頁面要用BeautifulSoup或XPath解析出結構化數(shù)據(jù)。清洗環(huán)節(jié)有幾個高頻問題價格字段里包含多余字符比如“¥ 198.00”要正則提取數(shù)字部分轉成浮點數(shù)評分字段可能是“9.1/10”或“92%”需要統(tǒng)一成0到10區(qū)間的數(shù)值游戲名稱里可能混有換行符和空白字符要strip掉同一款游戲在不同頁面重復出現(xiàn)需要按名稱加發(fā)行商做聯(lián)合去重去重邏輯我建議在寫入時做兩層第一層用Scrapy自帶的RFPDupeFilter對URL去重第二層在數(shù)據(jù)清洗完成后用游戲名稱的MD5值做指紋去重。清洗完的數(shù)據(jù)統(tǒng)一輸出成JSON Lines格式每行一條記錄這種格式Hive可以直接loadHadoop生態(tài)對JSON支持也最友好。# 清洗后數(shù)據(jù)落地格式 {name: 艾爾登法環(huán), genres: 動作,角色扮演, price: 298.00, rating: 9.5, ...}2.3 反爬應對與穩(wěn)定性保障這部分是論文里體現(xiàn)“工作量”的重點。常見的反爬手段是加User-Agent池、IP代理池、請求頭模擬瀏覽器。實際項目里我做了UA池掛了大概30個常見的瀏覽器UA每次請求隨機取一個。IP代理池原理不復雜難在代理源的維護如果只是課程設計級別本地IP加低頻請求就夠用了。更關鍵的是爬蟲的容錯機制。網(wǎng)絡請求不可能100%成功要處理超時重試、頁面結構變化導致的解析異常以及目標網(wǎng)站的反爬策略升級。我的做法是寫了一個異常處理裝飾器單個頁面解析失敗就記錄日志跳過不中斷整體任務。這個設計讓爬蟲可以掛著跑幾天不用人工干預到寫論文時我整理了爬蟲爬了大約50萬條有效記錄覆蓋了近萬個游戲產(chǎn)品數(shù)據(jù)量完全夠Hadoop做統(tǒng)計分析。3. Hadoop環(huán)境搭建與落坑記錄3.1 偽分布式還是集群先搞清楚很多學生的畢設環(huán)境是一臺普通PC內存8G或者16G這個時候硬上三節(jié)點集群很容易把自己搞崩潰。我建議起步階段先搭偽分布式模式也就是在一臺機器上同時運行NameNode、DataNode、ResourceManager、NodeManager這些角色。偽分布式不是玩具它的進程模型和真實集群完全一致只是把多臺機器的角色壓縮到一臺機器上。跑通了偽分布式理解了HDFS的文件上傳下載流程和MapReduce的任務調度機制后面再擴展集群只是改配置文件的事。如果你確實要搭真實集群最少需要三臺節(jié)點比如一臺Master跑NameNode和ResourceManager兩臺Slave跑DataNode和NodeManager。機器可以用虛擬機或者云服務器但要注意內網(wǎng)互通和SSH免密登錄配置。我用三臺虛擬機實測下來一個幾千萬級的MapReduce任務偽分布式可能要跑20分鐘集群可以縮短到11分鐘左右這個對比數(shù)據(jù)在論文里是很有力的支撐。3.2 偽分布式搭建的完整步驟環(huán)境準備階段建議使用CentOS 7或者Ubuntu Server 18.04以上的版本JDK必須用1.8版本Hadoop 2.x對這個版本的兼容性最好。下面是我反復驗證過的搭建流程創(chuàng)建hadoop用戶并配置免密登錄生成SSH密鑰把公鑰加到authorized_keys里下載Hadoop 2.10.2安裝包解壓到/opt/module目錄配置HADOOP_HOME環(huán)境變量修改core-site.xml配置fs.defaultFS為hdfs://localhost:9000臨時目錄設置為/opt/module/hadoop-2.10.2/tmp修改hdfs-site.xml設置副本系數(shù)為1偽分布式只有一臺節(jié)點副本數(shù)大于1沒有意義NameNode的HTTP訪問端口改為98702.x版本是50070修改mapred-site.xml指定MapReduce框架為yarn修改yarn-site.xml配置ResourceManager和NodeManager的運行模式修改hadoop-env.sh顯式指定JAVA_HOME路徑這里有個細節(jié)很多教程會建議改完配置直接執(zhí)行hdfs namenode -format。這里有個大坑我后面單獨講格式化前一定要確認配置文件的路徑都正確不要有拼寫錯誤否則格式化出來的集群狀態(tài)就是錯的后面啟動會非常痛苦。3.3 格式化啟動失敗的坑熱詞里有一條“hadoop啟動格式化失敗”這幾乎是我見過所有新手都會踩的坑。格式化NameNode時會檢查data目錄和name目錄如果這兩個目錄已經(jīng)存在并且里面已經(jīng)有數(shù)據(jù)了格式化就會報錯。但最經(jīng)典的問題還不是這個。我遇到過的情況是第一次格式化成功集群跑了一會兒我重啟了一下系統(tǒng)發(fā)現(xiàn)DataNode啟動不了了。查看日志發(fā)現(xiàn)ClusterID不匹配——NameNode格式化后重新生成了ClusterIDDataNode里存的還是舊ClusterID兩邊對不上就拒絕注冊。解決辦法是確保格式化時data和name目錄是空的把tmp目錄下的全部文件刪掉然后重新格式化。如果已經(jīng)出現(xiàn)ClusterID不一致連接上服務器檢查NameNode和DataNode各自的current目錄下的VERSION文件手動把ClusterID改成一致的再重啟服務。這個細節(jié)在論文的“系統(tǒng)調試”章節(jié)里非常加分說明你是真的把Hadoop跑明白了不是照著教程抄的。Zookeeper的整合也是熱詞里的高頻內容。集群模式下NameNode的高可用需要Zookeeper來選主兩個NameNode節(jié)點通過Zookeeper協(xié)調當Active節(jié)點宕機時自動切換。實測下來配置Zookeeper的難點有兩個myid文件必須和zoo.cfg里的server編號對應服務器數(shù)量必須是奇數(shù)個。我曾經(jīng)在3臺機器上配錯過myid導致Follower一直找不到Leader日志刷了一屏錯誤最后發(fā)現(xiàn)就是myid寫反了。3.4 Hive與Sqoop的配合用法Hadoop本身用MapReduce寫統(tǒng)計邏輯很繁瑣我強烈建議引入Hive作為數(shù)據(jù)倉庫工具。把清洗好的JSON數(shù)據(jù)load到Hive表里用類SQL語句做統(tǒng)計分析比如統(tǒng)計游戲類型的數(shù)量分布、不同評分區(qū)間的游戲占比、價格區(qū)間與好評率的關系、各發(fā)行商的平均評分。這些統(tǒng)計結果寫出來就是網(wǎng)站上“熱門游戲榜”“高分游戲榜”“游戲類型分布”等可視化報表的數(shù)據(jù)來源。Sqoop的作用是把Hive分析完的結果表導出到MySQL方便網(wǎng)站后端直接查詢。這里有個順序問題一定是Hive分析完導出到MySQL而不是網(wǎng)站直接連Hive查。因為Hive查詢的延遲很高動輒幾十秒網(wǎng)站頁面等不起把結果同步到MySQL之后接口響應時間可以壓到100毫秒以內。4. 游戲購買網(wǎng)站與數(shù)據(jù)應用層實現(xiàn)4.1 網(wǎng)站功能設計網(wǎng)站采用Spring Boot框架前端用Thymeleaf模板引擎加Bootstrap圖表用ECharts。頁面核心功能包括游戲列表頁分頁展示游戲支持按類型篩選、按評分和價格排序游戲詳情頁展示游戲封面、簡介、價格、評分模擬加入購物車和購買用戶系統(tǒng)注冊、登錄、收藏游戲數(shù)據(jù)可視化頁面展示Hadoop分析的統(tǒng)計結果用圖表呈現(xiàn)后臺管理管理員維護游戲信息觸發(fā)增量爬蟲任務從開題報告的角度看網(wǎng)站不是重點但它是數(shù)據(jù)的出口。沒有這個模塊前面的爬蟲和Hadoop就沒有落地場景。有很多同學把精力全放在爬蟲和Hadoop上網(wǎng)站頁面粗糙得不行答辯時老師問一句“這個項目最終能做什么”場面會非常尷尬。4.2 報表數(shù)據(jù)如何與Hadoop打通網(wǎng)站的報表數(shù)據(jù)來自MySQL中的分析結果表這些表是Sqoop從Hive導出過來的。我設計了三個核心報表指標游戲熱門排行榜依據(jù)評論數(shù)量和評分加權計算熱度值從Hive層算出結果后導出價格分布圖將游戲價格劃分為免費、0到50元、50到100元、100到300元、300元以上幾個區(qū)間統(tǒng)計各區(qū)間游戲數(shù)量和平均評分游戲類型分布對游戲類型標簽做explode展開統(tǒng)計展示比例關系這幾個指標看似簡單但在論文里可以支撐起“數(shù)據(jù)分析”“系統(tǒng)測試”等章節(jié)。更重要的是它們形成了一個完整的業(yè)務閉環(huán)——爬蟲采集原始數(shù)據(jù)Hadoop計算業(yè)務指標網(wǎng)站展示分析結果。4.3 緩存優(yōu)化與性能調優(yōu)思路網(wǎng)站聯(lián)調過程中Hadoop集群處理數(shù)據(jù)和網(wǎng)站實時讀取MySQL是有性能差異的不能指望用戶每次點擊都去觸發(fā)一次大規(guī)模計算。我的做法是數(shù)據(jù)可視化接口走Redis緩存緩存時間設置為6小時避免每次都查數(shù)據(jù)庫列表頁接口分頁查詢限制單次返回最大50條游戲詳情頁的靜態(tài)資源使用CDN加速爬蟲增量更新時只更新距今最近的數(shù)據(jù)不做全量重算性能壓測時我用JMeter模擬了100個并發(fā)用戶訪問列表頁和詳情頁接口的平均響應時間在300毫秒左右頁面加載在兩秒以內對于課程設計的場景來說完全夠用了。5. 常見問題與排查技巧實錄5.1 Hadoop啟動報錯速查表這部分是熱詞里大家最關心的地方直接整理成表格方便按圖索驥報錯現(xiàn)象根本原因解決辦法NameNode啟動失敗日志提示拒絕連接tmp目錄不存在或權限不足創(chuàng)建目錄并賦予hadoop用戶權限檢查core-site.xml路徑DataNode無法啟動提示ClusterID不匹配NameNode和DataNode的VERSION文件不一致刪除tmp目錄重新格式化或手動對齊VERSION中的ClusterID啟動Yarn后ResourceManager頻繁重啟內存配置不匹配Java堆空間設置過大調低yarn-site.xml中的虛擬內存比例和堆內存值SSH免密登錄不生效公鑰沒有追加到authorized_keys權限不正確重新追加公鑰確保.ssh目錄權限是700authorized_keys是600Hive執(zhí)行SQL卡死或OOM數(shù)據(jù)傾斜或者Reduce數(shù)量過少增加Reduce個數(shù)拆分大表設置hive.auto.convert.join為true502錯誤NodeManager連不上ResourceManager主機名解析不一致多個網(wǎng)卡IP混亂統(tǒng)一節(jié)點hostname和/etc/hosts配置關閉防火墻5.2 爬蟲與網(wǎng)站聯(lián)調中的典型問題爬蟲生成的JSON文件到達了一定規(guī)模后上傳到HDFS再load進Hive時經(jīng)常遇到字段類型不匹配的問題。比如評分字段偶爾會出現(xiàn)“暫無評價”這樣的字符串直接把整個字段類型搞亂了。這個問題讓我意識到清洗環(huán)節(jié)不僅要提取還要做類型強轉和非法值兜底原文里不是數(shù)字的統(tǒng)統(tǒng)置為NULLHive表定義時用using字段來兜底處理。網(wǎng)站和MySQL之間也容易出問題。Sqoop導出時默認按照主鍵分發(fā)到MapReduce任務中結果表的字段順序如果和Hive的不一致導出后數(shù)據(jù)會錯位。我在實際中踩過這個坑后來統(tǒng)一約定Hive表創(chuàng)建時字段順序就是導出表順序任何變更先改Hive表再改MySQL。5.3 Hadoop面試高頻點在這個項目里的體現(xiàn)熱詞里有一條“hadoop面試題”很多人做完這個項目只當作業(yè)交差太可惜了這其實是準備大數(shù)據(jù)崗位面試的一部分。項目里的幾個細節(jié)直接能對應上常見面試題“HDFS的讀寫流程是怎樣的”你格式化過NameNode、上傳過文件再結合請示回答時可以把實際執(zhí)行時的報錯補充進去“MapReduce的shuffle過程”你跑過Hive任務把reduce階段數(shù)據(jù)溢寫排序的過程拆開講就是完整的答案“數(shù)據(jù)傾斜怎么優(yōu)化”我上面提到的Hive SQL卡死問題你跟面試官說“我在項目里遇到過游戲類型字段分布不均導致某些reduce處理的數(shù)據(jù)量巨大最后通過加隨機鹽和拆分鍵解決”比背書上的概念要有說服力得多5.4 一些我踩了幾次才想明白的經(jīng)驗用管理員身份做完一套流程后我最想提醒幾點。第一虛擬機不要用低配至少分配8G內存否則JVM的內存配置怎么調都跑不動。第二Hadoop的目錄結構不要隨便移動我用mv命令移動過一次tmp目錄結果整個集群狀態(tài)全亂了最后只能刪掉重新格式化。第三代碼全部提交到Git倉庫每個階段能夠回退否則改壞了配置只能重來最怕的是改到一半忘了之前能跑通的版本是什么。實驗數(shù)據(jù)一定要留好。我在項目過程中把爬蟲的采集日志、Hive的分析SQL、網(wǎng)站前后端代碼都整理歸檔論文寫實現(xiàn)部分時素材直接取材于實際過程完全沒有編造的痕跡。這也讓答辯時面對細節(jié)提問有了充足的底氣。6. 補充方案的擴展方向6.1 引入云平臺與自動化如果目標是把系統(tǒng)做成能夠長期穩(wěn)定運行的項目可以在此基礎上引入容器化和自動化部署。Hadoop的Docker鏡像在開發(fā)調試時非常方便一條命令就能拉起一個測試集群配合腳本能自動完成集群的銷毀和重建。Ambari部署也值得了解它是管理Hadoop集群的可視化工具可以簡化配置和監(jiān)控流程。不過這些都屬于加分項不建議作為工作量主體核心仍是爬蟲、存儲分析、網(wǎng)站三者的集成閉環(huán)。6.2 從報表升級為推薦系統(tǒng)當前網(wǎng)站的數(shù)據(jù)可視化還停留在展示統(tǒng)計圖表的層面如果把Hadoop計算出的用戶行為數(shù)據(jù)用于個性化推薦項目就能再上一個臺階。例如按用戶收藏和購買行為用協(xié)同過濾算法生成推薦列表再交給網(wǎng)站動態(tài)展示。這個是很好的擴展方向而且能和Hadoop中的計算能力銜接起來。6.3 論文寫作時的架構取舍寫論文或開題報告時建議把重點放在“數(shù)據(jù)全鏈路設計”上不要各個技術點平均用墨。爬蟲部分強調采集策略和清洗規(guī)則Hadoop部分強調存儲模型和分析模型的選型依據(jù)網(wǎng)站部分強調數(shù)據(jù)可視化和業(yè)務功能的對應關系。開題報告中最容易得分的是需求分析和可行性分析——你要能說清楚這套系統(tǒng)解決了什么問題而不是只是把課程里學過的框架拼在一起。如果時間允許可以在論文最后附上一份完整的部署手冊包括環(huán)境版本、配置示例、啟動步驟和常見問題的解決方案這也是體現(xiàn)工程能力一個重要方式。我當時特地補了這份文檔答辯時老師瀏覽了一遍直接說“這東西拉出去能用”這種評價在答辯現(xiàn)場非常受用。我自己做完這個項目后最大的體會是不要被題目里的“大數(shù)據(jù)”唬住再大的數(shù)據(jù)也是從一條一條采集開始的。把每個環(huán)節(jié)都吃透爬蟲能穩(wěn)定跑Hadoop能穩(wěn)定算網(wǎng)站能穩(wěn)定展示整個項目才算是真正閉環(huán)了。這套流程做完你對大數(shù)據(jù)的理解就不再停留在概念上而是有了完整的體系認知。