去哪兒網機票搜索系統的高併發架構設計(要點節選)

  • 前端作靜態文件的壓縮,優化Http請求鏈接數,以減少帶寬,讓頁面更快加載出來。
  • 先後端作了數據分離,讓搜索服務解耦,在高併發狀況下更靈活作負載均衡。
  • 後端數據(航班數據)99%以上來自緩存,加載快,給用戶更快的體驗。

搜索系統設計架構


前臺搜索

主要讀取緩存,解析,合併航班數據返回給用戶端。
前臺搜索是基於Web服務,高峯期時候最大啓動了50臺左右的Tomcat實例。搜索的URL規則是:出發城市+到達城市+出發日期,這和緩存系統存儲最小單元:出發城市+到達城市+出發日期是一致的。
Tomcat服務咱們是經過Nginx來作負載均衡,用Lua腳本區分是國際航線仍是國內航線,基於航線類型,Nginx會跳轉不一樣搜索服務器:主要是國際搜索、國內搜索(基於業務、數據模型、商業模式,徹底分開部署)。不光如此,Lua還用來敏捷開發一些基本服務:好比維護城市列表、機場列表等。

高併發多線程應用


Java的多線程對於高併發系統有下面的優點:
  • Java Executor框架提供了完善線程池管理機制:譬如newCachedThreadPool、 SingleThreadExecutor 等線程池。
  • FutureTask類靈活實現多線程的並行、串行計算。
  • 在高併發場景下,提供了保證線程安全的對象、方法。好比經典的ConcurrentHashMap,它比起HashMap,有更小粒度的鎖,併發讀寫性能更好。

高併發下數據傳輸

最先航班數據用標準的XML、JSON存儲,不過隨着搜索量不斷飆升,CPU和帶寬壓力很大了。後來採起本身定義一種txt格式來傳輸數據:一方面數據壓縮到原來30%~40%,極大的節約了帶寬。同時CPU的運算量大大減低,服務器數量也隨之減少。
在大用戶量、高併發的狀況下,是特別能看出開源系統的特色:好比機票的數據解析用到了不少第三方庫,當時咱們也用了Fastjson。在正常狀況下,Fastjson 確實解析很快,一旦併發量上來,就會愈來愈吃內存,甚至JVM很快出現內存溢出。緣由呢,很簡單,Fastjson設計初衷是:先把整個數據裝載到內存,而後解析,因此執行很快,但很費內存。

後臺搜索

後臺搜索系統的核心任務是從外部的GDS系統抓取航班數據,而後異步寫入緩存。
機票的源數據都來自於各類GDS系統,但每一個GDS卻千差萬別:
  1. 服務器遍及全球各地:國內GDS主要有中航信的IBE系統、黑屏數據(去機場、火車站看到售票員輸入的電腦終端系統),國際GDS遍及於東南亞、北美、歐洲等等。
  2. 通信協議不同,HTTP(API、Webservice)、Socket等等。
  3. 服務不穩定,尤爲國外的GDS,受網路鏈路影響,訪問很慢(十幾分鍾長鏈接很常見),服務白天常常性掛掉。
  4. 更麻煩的是:GDS通常付費按次查詢,在大搜索量下,實時付費用它,估計哪家公司都得破產。並且就算有錢 , 各類歷史悠久的GDS是沒法承載任何的高併發查詢。更苦的是,由於是創業公司,咱們大都只能用免費的GDS,它們都是極其不穩定的。

引入NIO框架

考慮GDS訪問慢,不穩定,致使不少長鏈接。咱們大量使用NIO技術:
NIO,是爲了彌補傳統I/O工做模式的不足而研發的,NIO的工具包提出了基於Selector(選擇器)、Buffer(緩衝區)、Channel(通道)的新模式;Selector(選擇器)、可選擇的Channel(通道)和SelectionKey(選擇鍵)配合起來使用,能夠實現併發的非阻塞型I/O能力。
HTTP、Socket 都支持了NIO方式,在和GDS通訊過程當中,和過去相比:
  • 通訊從同步變成異步模式:CPU的開銷、內存的佔用都減低了一個數量級。
  • 長鏈接能夠支持更長超時時間,對國外GDS通訊要可靠多了。
  • 提升了後臺搜索服務器的穩定性。

消息隊列

爲了異步完成航班數據更新到緩存,咱們採用消息隊列方式(主備AMQ)來管理這些異步任務。具體實現以下:

具體原理:按照每一個GDS服務器穩定性(經過輪休方式,不斷Check它們的可用性)和查詢性能,咱們算出一個合理的權重,給它分配對應的一組虛擬的Node節點,這些Node節點由一個Node池統一管理。這樣,不一樣的GDS系統都抽象成了資源池裏面的一組相同的Node節點。
那麼它具體如何運轉的呢?
當緩存系統相關航班數據過時後,前臺搜索告知MQ有實時搜索任務,MQ統一把異步任務交給Router,這個時候Router並不會直接請求GDS數據,而是去找Node池。Node池會動態分配一個Node節點給Router,最後Router查找Node節點映射的GDS,而後去請求數據,最後異步更新對應的緩存數據。經過技術的實現,咱們把哪些不穩定的,甚至半癱瘓的GDS充分利用了起來(包含付費的一種黑屏終端,咱們把它用成了免費模式,這裏用到了某些黑科技,政策緣由不方便透露),同時知足了前臺上億次搜索查詢!

監控系統

鑑於機票系統的複雜度和大業務量,完備監控是很必要的:
一、整個Qunar系統架構層級複雜,第三方服務調用較多(譬如GDS),早期監控系統基於CACTI+NAGIOS ,CACTI有很豐富的DashBoard,能夠多維度的展現監控數據。除此之外,公司爲了保證核心業務快速響應,埋了不少報警閾值。並且Qunar還有一個NOC小組,是專門24小時處理線上報警:記得當時手機天天會有各類系統上百條的報警短信。
二、複雜系統來源於複雜的業務,Qunar除了對服務器CPU、內存、IO系統監控之外,遠遠是不夠的。咱們更關心,或者說更容易出問題是業務的功能缺陷。因此,爲了知足業務須要,咱們當時研發了一套業務監控的插件,它的核心原理以下圖:

它把監控數據先保存到內存中,內部定時程序每分鐘上傳數據到監控平臺。同時它做爲一個Plugin,能夠即插即用。接入既有的監控系統,它幾乎實時作到監控,設計上也避免了性能問題。後期,產品、運營還基於此係統,作數據分析和預測:好比統計出票正態分佈等。由於它支持自定義統計,有很方便DashBoard實時展現。對於整個公司業務是一個頗有力的支撐。

轉載地址:http://mp.weixin.qq.com/s/1ipdByfsaTcHpo_W5gJVug
相關文章
相關標籤/搜索