假如我来架构12306网站(一) - 概论
序言:? 此文的撰寫始于國慶期間,當中由于工作過于繁忙而不斷終止撰寫,最近在設計另一個電商平臺時再次萌發了完善此文并且發布此文的想法,期望自己的綿薄之力能夠給予各位同行一些火花,共同推進國內的大型在線交易系統的研發工作,本文更多地站在軟件工程角度來看待整個問題,有關后續的技術問題研究,將在另外的博文中予以探討。
?? 一年一度的國慶大假剛落下帷幕,由于這次長假是歷史上最長的一次,因此出行問題備受關注,而鐵路出行作為最主要的出行方式更是大家討論的熱點,老生常談的購票難問題又被提起。這幾天我在網站上也看到很多關于12306.cn的討論,很多網友都發表了自己對于鐵道部購票網站的不滿,更有很多同行討論了關于12306網站的設計問題,期待能夠貢獻自己的綿薄之力,我仔細拜讀了其中至少10篇文章,很多同行多是站在技術的角度來考慮,其中不乏很多有創意的想法,純粹的技術設計能解決一些問題,不過似乎不能夠全面地解決這個龐大的、堪稱瞬間流量“世界第一”的實時交易網站,目前12306的問題與其說是一個技術問題,還不如說它是個軟件工程問題,道理非常簡單,請看如下的新聞報導:
??????? [[[回望12306網站在2011年12月底以來的表現,鐵道部高層也直呼想不到。 ??? ?鐵道部副部長胡亞東介紹,今年第一次在全國鐵路實行網絡電話訂票,截至1月8日已經達到每天200萬張,12306網站的注冊用戶已超過1000萬人。1月1日至7日,“12306”網站日均點擊次數已經超過了10億次,專家認為瞬間點擊可能達到了“世界第一”。 ?
? ?? ?高度的關注、巨大的訪問量,導致12306網站頻繁出現系統崩潰、無法登陸、無法支付等情況。 ?
? ?? ?“像春運這樣龐大的需求量,難道鐵道部沒有預想到并有所準備?”隆梅資本管理有限公司副總經理馬宏興對此困惑不解。 ?
?? ?在探究12306網站問題的深層原因以及解決之道時,各家看法不同,“12306網站的問題最終還是系統架構的問題。因為用戶有大量的動態、交互式訪問,所有的請求都會發送到12306網站的服務器端,同時在線并發用戶數量太多,導致網站無力承載,造成擁堵。”華南師范大學計算機學院副院長單志龍認為。 ?
??????? 又有說法認為,如果給12306網站增加服務器和帶寬,也能夠緩解擁堵的癥狀。這一觀點鐵道部內部頗為認同。 ?
?? ?“得承認,我們對訪問量估計得不足。”鐵道部信息技術中心一位中層向記者透露,12306網站曾在2011年春運期間試運行,高峰時段訪問量約在1億點擊量,因此,信息中心估計2012年春運期間的訪問量約在3億至4億。 ?
?? ?但是,結果卻大大出乎人們的預料。“12306”網站在1月9日的日點擊量達到14億次,是原來料想峰值的5倍之多。“崩潰”在所難免!]]]
筆者連日來也萌發了一個想法,假如讓我來設計12306網站,我作為總架構師,該當如何考慮呢?自己雖然經歷過眾多的大項目的全生命周期跟蹤管理,對于軟件工程應該是有一定的研究,但像如此巨型項目,應該如何來設計、管控與實施? 確實也頗傷腦筋,下面就筆者根據自己多年根植于IT研發的經驗,特別是近年來對于巨型網站譬如國內的淘寶、京東等,國外的Facebook、Google等的跟蹤研究經驗談談自己的看法。
1. 需求分析階段
需求分析是至關重要的,對于12306而言,需求分析的重點應該需要得出如下方面的關鍵數據才算需求分析基本結束:
終端用戶方面的:
訪問用戶數量、總體注冊用戶數量、平時訪問用戶的峰值、平時訪問用戶的谷值、大假期訪問用戶的峰值、大假期訪問用戶的谷值、小假期訪問用戶的峰值、小假期訪問用戶的谷值;
用戶的地域分布性、用戶可能介入的設備、用戶接入的網絡狀況統計分析;
后臺服務方面的:
關鍵購票流程業務分析:
購票的基本流程分析、一次購票的TPS數量分析、一次購票的用戶流量分析、一次購票的用戶靜態流量分析、一次購票的用戶動態流量分析;
這其中又分為初次購票與再次購票兩種情況,流程稍微有些不同;
系統提供的其他服務統計分析;
前面所說的的大假在國內目前只有2個即春節與國慶,小假較多譬如清明、端午、中秋等。
對于用戶訪問用戶數、流量、網絡、后臺的TPS數量能夠建立一個數學預測模型那就非常的清晰了,對于后續的設計指導意義至關重要;
對于如此大的網站在安全性方面的需求需要做重點調研,另外由于是實時交易網站,還需要考慮金融安全問題,安全方面還得從如下兩個方面來全面考慮:
?? 內部安全,主要關注資金以及交易的安全,特別是防止內部人員尤其是系統管理員;
?? 外部安全,主要關注如何確保拒絕外部惡意入侵與攻擊成為一個核心,特別是類似DDOS之類的攻擊;
對照筆者的論述以及前面的新聞內容,不難發現,12306的設計組非常明顯沒有充分深入地進行需求調研與數據模型分析,特別是預案設計,因此筆者才敢說這更是個工程問題,而不完全是個純粹的技術問題。
2. 系統原型設計階段
國內很多的軟件公司不太重視原型設計,這點對于小軟件開發無關緊要,可是一旦到了大型軟件的開發之時,不重視原型設計會失敗得很慘,筆者曾經在后期救過一個ITSM管理系統的開發,究其原因,其中很重要的一條是對于原型設計不太重視,特別是在應用了大量的新技術而未進行原型設計是一件風險極大的事情,在筆者親身帶的幾十個項目中有一部分就是這種情況,其中幾個項目的痛苦經歷(通宵達晝的加班長達1-2個月)更是令我終生難忘;
根據前面的需求方面的分析討論,不難發現12306的原型設計中需要解決的問題如下:
前端Web服務器基于巨量訪問的(秒均訪問千萬級別)可伸縮性模式驗證:
?? 這塊可供選擇的技術包括如下一些:基于CDN的Internet緩存加速技術、基于Apache Server+JBoss(Weblogic)的組合服務不同的、基于不同接口的調用原型研究、請求排隊技術等的原型研究;
后端數據庫讀寫基于火車票應用的可擴展模式;
?? 大家都知道,借鑒Facebook的巨量數據處理經驗,必須基于現代數據庫的分區技術、分布式處理技術并且通過后續的查詢結果集成技術來實現巨量交易數據的可擴展性,基于巨量數據應用的可擴展模式通常有如下模式:
? 水平擴展技術,通常是基于分區技術來實施,維度是分區技術進行選擇時的關鍵,針對于火車票的交易數據而言,時間維度是最好的選擇,具體執行而言,可以將每天的車票交易信息放到某一分區上來執行,這樣對于后續的數據維護(存儲備份等)都將帶來極大的方便;
????? 垂直擴展技術,通常是基于地域等實現的分布式擴展,針對于火車票的交易數據而言,如何將不同地域的車票、車次信息劃歸為不同的數據庫服務器來執行,確保在數據交易上的廣域可并行性;
對于12306系統,筆者建議最好能夠按照列車始發與到達站的地域性進行垂直切割,而交易數據按照時間來進行橫向水平擴展形成不同的子數據庫,同時通過中間的緩存服務器、索引服務器、集成服務器將不同的數據進行地整合過來,提供給前端的應用服務器,因此從系統架構上來看這個結構圖形如下:
3. 原型驗證階段
針對系統的原型設計,需要針對相應的子系統來驗證原型的技術穩定性與成熟度,具體而言分別分為如下幾段:
針對前端訪問的巨量級別的HTTP負載均衡子系統驗證,特別是驗證針對單個數據農場的服務響應能力,需要驗證單個服務器的HTTP極限響應數量、動態擴展機制、網絡帶寬占用情況等;
針對中間訪問的緩存子系統、索引子系統、集成子系統,需要驗證依照前端的用戶請求如何將連接到后端不同的數據庫上進行相應的數據分布化集成服務;
針對后端訪問的數據庫垂直、水平切割技術,基于地域的垂直切割與基于時間的水平切割技術并且結合存儲方面的分布式來擴充數據庫系統的事務能力;
4. 系統正式設計階段
正式設計整個系統時要考慮的設計方面還是挺多的,分別列出如下。
功能性設計:
前端Web服務器設計,可以按照Apache來負責靜態頁面響應處理、JBOSS/WEBLOGIC負責動態頁面響應處理來進行設計,同時可以考慮將整個資源放到內存里面而使得Apache服務器對于靜態資源的調用徹底離開磁盤I/O的制限,從而最大程度上提升前端Web服務器響應能力,這點筆者在一個游戲網站的后端服務器上曾經使用過,整體的web server響應能力提升了好幾倍;
具體的業務設計需要依照個業務的流程來拆解實施,此設計的關鍵是在于將前段的業務如何能夠跟后端的高度擴展的分布數據庫能夠集成對應起來;
后端數據庫處理系統可以考慮按照如下的模式來予以完善設計:?? 將前段系統的運算分解與將各服務器進行(結果集成子系統)、使用成熟的反向搜索引擎系統作為前端的車站查詢系統(搜索引擎子系統)、中間基于車次的具體查詢可以使用緩存系統來實現(緩存子系統)、交易數據將寫入到RDBMS之中(可水平、垂直擴展的事務處理子系統); 這樣設計的好處主要是將各種交易以及訪問能夠最大程度上的并行化,實現分布式集成化處理,從而最大程度上提升系統的整體處理能力;
存儲子系統的設計:
主要是如何在RDMMS之間能夠最大化各數據庫的I/O處理能力同時提供不同地域(數據農場)的數據同步服務支持,同時對于從網絡條件來看,建議將不同數據中心互聯的光纖與用戶請求的光纖分開了確保后端的數據同步響應不受前端的密集巨量請求服務之影響。
安全性設計:
前端的安全性設計主要包括防止諸如拒絕訪問攻擊(DDOS)、腳本注入攻擊、用戶信息安全、系統入侵等,后端的安全性設計主要是要考慮賬戶信息、交易的安全等;
通常來說,前端可以考慮基于防火墻以及各種訪問監測技術來做統計分析監控各種異常情況,而后端主要是基于數據加密、交易通道安全、數據庫防篡改設計等來實施。
冗余設計:
包括依照地域、用戶群建立不同的數據中心的設計、基于DNS區域解析規劃設計、基于各服務器角色進行的冗余設計(WEB服務器、搜索服務器、緩存服務器、集成服務器、數據庫服務器、存儲服務器等)所進行的數據的冗余設計,譬如常見的集群技術、熱備以及熱切技術等均可考慮在此應用;
其實筆者使用了中國國內的服務器以及美國的服務器分別解析了12306.cn域名地址,顯示了兩個不同的地址,這已說明12306設計組已經考慮了這些內容:
從美國PING將會發現:
ping www.12306.cn
PING 08911.xdwscache.glb0.lxdns.com (183.60.136.64) 56(84) bytes of data.
64 bytes from 183.60.136.64: icmp_seq=1 ttl=49 time=171 ms
64 bytes from 183.60.136.64: icmp_seq=2 ttl=49 time=171 ms
從上海PING將會發現:
ping www.12306.cn
Pinging 08911.xdwscache.glb0.lxdns.com [211.144.81.22] with 32 bytes of data:
Reply from 211.144.81.22: bytes=32 time=11ms TTL=59
Reply from 211.144.81.22: bytes=32 time=10ms TTL=59
部署與維護設計:
部署設計的關鍵是確保各種角色的服務器如何能夠實現快速復制擴展,在緊急需要時能夠快速部署實施,同時對于服務器集群在進行升級時如何快速批量地更新整個執行包;
維護設計的關鍵考慮因素是系統運行的監控與報警系統設計,監控的指標就前端包括整個系統的訪問數量、單個客戶端的訪問頻率、訪問的URL分布等,后端需要監控的是各服務器的使用量、負載量同時以此進行上報到監控服務器來決定相應的服務器是否需要進行動態擴展;
5. 開發實施階段
針對于此巨型交易系統的開發,在開發階段的關鍵因素是代碼品質控制,建議采用軟件工程成熟的Coding->Review->UT控制技術(基于TDD的開發模式)來完成個模塊以及集成子系統的品質管控,在此特別提醒的是對于Review、UT段的密度需要做硬性的規定,流程裁剪時建議采用高密開發模式確保此階段的品質管控目標,在此不得不多說一句的是很多時候很多的公司、開發人員總是錯誤地認為這些流程過于復雜,浪費時間,其實從各種實際的項目實施經歷來看,此處多花了2-3倍的開發時間可以避免后續5-10甚至數十倍調試時間(Bug fix)的投入,整體上來算還是非常值得的,對于大型項目尤其如此,筆者在很多大型項目的集成階段碰到集成不暢、無法按時完成集成任務時,開發、測試人員都是通宵達晝地加班,這其中很多的工作都是無用功,何不在開發實施階段將系統的測試密度進行加大呢?構建質量上更好的組件(部件、模塊),這樣到集成的時候就不手忙腳亂了。
由于此系統的規模非常大,因此在詳細設計、開發時,應該考慮到各子系統必須設計得非常易于測試,特別是易于進行單體測試與自動化測試,這點可以大幅降低項目的執行成本;
6. 測試階段
對此巨型系統的構建完畢后需要經歷子系統集成測試、系統總集成測試兩個階段,并且需要按照如下不同的測試種類來進行逐個測試確認:
?功能測試、性能測試、安全測試、破壞性測試、持久運行能力測試等
功能測試需要針對多服務器角色集成后按照設計所提供的功能清單依據測試密度以及測試的分布性來確定不同方面的測試case,依據此來分步執行此功能測試,并且依照測試執行的結果來分析各個模塊的缺陷密度以及缺陷的消化曲線,以此指導后期的開發設計工作,并藉此可盡快完成功能方面的驗收確認;
性能測試針對這個案列相對比較復雜,由于服務器角色很多,其基本的思路還是分析確定前端各業務的使用比例,編寫開發自動化測試腳本來模擬用戶的操作行為,并且在測試環境下針對特定的服務器數量的集群發起服務請求,同時完整地檢測每個角色服務器的CPU/Memory/Disk I|O/Network方面的性能參數值,通過不斷增減客戶端請求數(伴隨客戶端機器的增加、譬如初期使用100臺,逐步增加到200臺測試機)來觀察服務器的性能反應,分析出拐點,同時需要測試出系統的極限吞吐量(RPS,TPS等值),并且測試出增加不同的服務器角色對于這些吞吐量的影響,同時在此階段需要開發人員的協助來針對不同的角色根據測試結果進行性能調優工作;
安全測試,需要針對以下不同的場景進行模擬攻擊測試:
外部安全而言: 包括腳本注入攻擊、端口掃描、拒絕服務攻擊、主機入侵等安全測試都需要逐個進行驗證,確保系統的外部安全;
內部安全而言: 包括各服務器的數據的安全、密碼安全等進行測試;
破壞性測試,需要就各個角色服務器所對應的物理服務器進行不同部位失效、移除等試驗,看看整個服務器集群的監控、維護服務以及服務輸出吞吐的影響,并且完善后續的各種系統對應的維護流程;
持久運行能力測試需要,待系統達到Beta測試版本要求之后,需要針對待部署的系統進行一定負載量持續運行至少2周以上,并且觀測系統的穩定性方面的反應,同時就數據庫的增長、日志的增長等各種情況進行綜合評估并且需要結合后續的部署維護做適當完善性調整;
7. 部署階段
對于如此巨型系統的部署調試工作,也是個不大不小的工程,那么如何確保部署調試工作進展的順利,根據筆者多年維護廣域網系統的經驗,有如下幾點需要注意:
?-> 如何管理好不同的服務器之間的發行版本問題,確保發布不會亂,特別是小版本的升級上部署不會亂是個關鍵,否則對于數以千計的服務器那絕對是個災難;
?->如何能夠快速解決單次發布的升級與回退問題同樣是很重要,這當中筆者的經驗是使用一個經過驗證的發布部署流程以及校驗流程,整個過程最后放在一個發布腳本中,對于具體的升級與回退,維護人員只需要執行一次命令即可完成,并且對于每個版本發布完畢后的校驗工作尤其重要,必須在腳本中予以體現;
?->最后一點對于部署而言,任何部署都必須要有回滾方案配套,確保任何時間點上系統皆可用;
在運行維護階段有很多細節需要配套考慮:
? ->系統整體的實時狀態監控,包括各種角色的應用主機的監控、網絡設備的監控、用戶訪問流量的監控、服務可用性監控、安全監控等;
? ->系統巨量的交易數據轉儲、交易日志的轉儲問題, 這個問題的解決需要結合前面在設計時的 數據庫垂直(按時間維度)擴展以及日志按照天的維度來進行維護的方式進行有計劃地轉儲到不同時間段的歷史庫中,并且通過數據的清洗、整理將部分重要數據轉入到OLAP/OLTP系統中,為后續系統基于實時交易數據的聯機分析改進業務提供幫助;
9. 優化階段
? ->業務流程優化:這塊最主要的問題是將購票這個核心業務按照計算機易于執行計算的模型來進行不斷地優化,同時體驗,譬如異步事務提交優化、排隊技術等皆可以使用在用戶的模型上,同時可以向用戶提供預訂業務等來降低某個時段的網站流量壓力,使得流量的整體峰值、谷值差距縮小很多;
? ->架構設計優化:在數據庫的分區(垂直、水平分區)方面不斷地進行優化,同時對于單數據庫,就事務處理能力方面進行優化存儲方面的操作,譬如使用固態硬盤替代傳統的SCSI盤等,并行虛擬寫技術等大幅提升磁盤I/O操作能力、或者采用內存數據庫技術來管理好讀寫分離(讀自內存、寫到內存與磁盤同時),這樣可以在數據庫層面上獲得性能的大幅提升;如果能夠配合系統壓力測試模型來獲取其性能衰減曲線圖針對性地優化,其效果將更加明顯;
?在中間層服務器上,如何將不同的車次分布在大小幾百個數據庫上,并且使用反向搜索引擎技術來連接前端的訪問請求到后端的數據庫服務器之間的映射與集成(這點可以參考MapReduce并行算法);
在應用層服務器上,如何將靜態內容與動態內容予以剝離,并且無需保存的內容(只讀)內容全放在內存中,如何平衡CDN加速與后端Web server的服務架構也是不斷提升單個農場集群服務能力的關鍵與核心;
? ->性能優化: 這些優化是非常之多的,譬如針對Web server的socket連接池優化、日志優化,針對中間集成服務器的并行任務分解與結果集成優化,基于后端數據庫服務器的數據計算模型、訪問方式、冗余與數據同步、傳遞優化、數據分區優化等;
? ->其他調優:其他方面的調優譬如基于監控的優化、基于大并發量的快速響應與擴展優化等等;
寫到此,感覺上似乎已經設計完畢了,不過突然回頭一望,還真發現內容非常之多,可能有實戰經驗的朋友肯定會提到此系統屬于“過度設計”了,不過筆者在此要說的是,確實這個最后的提醒是非常有必要的,任何系統的設計特別是如此復雜的系統的設計只能是需要通過時間來循序漸進,先原型后實際系統并且遵循幾輪研發調優(含架構設計調優),最后逐漸演變到一個真實成熟的系統,任何超前的設計最終都被證明是無用功而遭廢棄;
很多的網友對于12306的網站的技術議論紛紜,并且提出了眾多的創造性想法,筆者在提出自己的想法后還有幾點補充想法供大家參考:
1. 其實此網站的需求不是一個純粹的技術問題,試想一下,真的按照國慶、春節的高峰訪問需求來設計、部署整個系統的時候,在平時的時候大部分機器都是浪費的,如何平衡峰值與谷值時矛盾是個技術問題,可背后掩蓋著的是全中國13億多人口在短短的10-15天內完成眾多的人口遷徙,如此巨大的工程放在任何一個國家都是難于解決的問題,如何從需求層面來化解這個短期內的巨量人口流動問題才是此問題的命根; 正所謂 “ 解決火車票購買過程容易,而解決人人能買到火車票難!!!”
2. 此問題的求解永遠是個迭代過程,需要看到的是很難有人能夠在短期內設計并且實現這么一個巨量系統,這個工程問題的求解是拆解為不同的子模塊來分步實現,并且逐步迭代優化求解的過程;
3. 此問題的解決必須是個系統工程,牽涉到資金、技術、人才、時間 這4個基本要素,很多的同行過于看重人才與技術,而忽略了資金等前提性因素,試想如果只有3000萬預算讓你來設計實現這個巨型交易系統,你能解決么? 不說別的,光性能模擬測試就需要調動數以萬計的前端機器來在全國范圍內不同的典型區域發起海量請求,這些是個小資金能夠解決得了的問題么?
后記: 筆者深知,任何技術的討論必然會引起一些爭議,整個技術的發展必須要經歷這樣的紛爭才能進步與提高,在此博文發布的幾天內,備受各位同行的關注,筆者非常感謝,也發現了諸多不友好的言辭, 對于有類似架構經驗、大項目經歷的同行一看就明白,而無此經歷的同行看起來相對比較而言沒有感覺,筆者在此期望技術紛爭的同行不要爆粗,大家共同的目的是為了推動技術交流,推動你我的技術進步,推動國家與民族的技術發展。
總結
以上是生活随笔為你收集整理的假如我来架构12306网站(一) - 概论的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot源码解析(十一)自定
- 下一篇: 8代9代cpu平台改换win7的实践经验