- 《構建高性能web站點》筆記--基礎架構篇
- 《構建高性能web站點》筆記--應用程序篇
起因
大概花了一個月不到的時間,看完了這本400頁不到的書《構建高性能web站點》,不得不說這是我第一次真正意義上完全看完一本書,盡管曾經看過許多技術類的書。其中一個原因,就是大部分的技術類書籍偏向枯燥,即使是本着某種虔誠的目的和願望去閱讀,仍然很容易中途放棄。但是這本書卻不同,它十分能吸引我的閱讀願望,幾乎在所有的環節上能夠引起我的共鳴思考,於是便快速的閱讀了一遍此書。
作者主要以典型的LAMP為例子,我幾乎沒有接觸過這方面,但是相信思想是一致的,學思想打基礎才是關鍵。因此,本文是以概要性的總結為主。
概覽圖
下面這張圖我花了比較長的時間繪制,提煉了書中關於基礎架構設計方面的部分,希望能把它們濃縮在一張圖中,而且圖中包含image-map,可以通過點擊虛框鏈接到下文的對應部分。不過需要強調的是,這張圖僅僅是一個雜燴,並不是實際的架構,切勿對號入座。
組件分離
DNS負載均衡
不同的web內容分布到不同的服務器上,並划分子域,利用DNS將請求自然轉移到不同的服務器上。主要可以分為兩大內容:
- 動態內容,CPU、IO密集型
- 靜態內容,IO密集型
通過在DNS中配置多個A記錄,將請求轉移到集群中不同的服務器,這有助於具有地域性問題的大型web站點上,DNS可以使用戶就近訪問相應的web服務器。像BIND這樣的DNS服務軟件提供豐富的調度策略。但是,如果集群中的主機出現故障的話,需要更新DNS緩存,這通常需要一定的時間。另外,客戶端也可以通過設置host來繞開DNS調度。
跨域共享cookie:將cookie的范圍擴大到父域
HTTP重定向
通過使客戶端重定向,來分散和轉移請求壓力,比如一些下載服務通常都有幾個鏡像服務器。
分布式緩存
無法使用頁面級別緩存時,需要考慮直接緩存數據,比如使用memcached作為緩存。此時,需要考慮並發寫memcached的問題。 另外,當memcached橫向規模擴大,服務器數量增加時,需要一種對應算法,能夠使應用程序知道應該鏈接哪個memcached服務器(比如,取模運算)。分布式緩存能夠自動重建緩存,不必擔心down機。
負載均衡
負載均衡就是將請求分散,這涉及到應當如何設計調度策略,以讓集群發揮最大的性能。當集群中的主機能力相當時應當盡量平均調度,能力不均時應當能者多勞。隨着問題的復雜,要時刻關注調度的性能,不要讓調度成為性能瓶頸。
反向代理負載均衡
反向代理服務器工作在HTTP層,類似代理服務器,與普通的代理服務器不同的是,服務器在代理的后端,而不是客戶端在代理的后端,這類似於NAT,只是NAT工作在網絡層。同樣是負載均衡,反向代理服務器強調“轉發”而不是“轉移”,因為它不僅要轉發客戶端的請求,還要轉發服務端的響應。可以用作反向代理服務器的軟件有Nginx、lighttp、Apache,另外目前也有一些專業的代理轉發設備能夠工作在應用層,例如A10。
使用代理轉發要注意以下問題:
- 由於反向代理的轉發特性,使得代理本身很可能成為性能瓶頸。一般對於CPU密集型請求,使用代理比較合適,如果是IO密集型的話,這種集群方式很可能無法發揮最大性能
- 在代理上要開啟健康檢查,及時發現集群中的故障機,從而調整轉發策略,這通常比DNS方式實時性更好
- 黏滯會話:對於啟動session保存用戶信息,或者后端服務器使用動態內容緩存的應用,必須將用戶在一段會話中的的請求保持在同一台服務器上。代理服務器一般支持類似的配置。然而,盡量不要使應用過於本地化,比如可以使用cookie保存用戶數據,或者分布式Session或分布式緩存。
IP負載均衡
字面上看,便是利用網絡層進行請求轉發,類似NAT網關。然而,使用網關轉發在帶寬上可能出現瓶頸,因為出口只有一個,所以出口的帶寬要求較高。Linux中的Netfilter模塊可以通過iptables的配置。比如:對外網端口8001的請求轉發給內網某台服務器,而對外網端口8002的請求轉發給內網另一台服務器。這種方式簡單易行,但是無法對調度做太多配置。LVS-NAT同樣是Linux中的在網絡層進行轉發的方式,與Netfilter不同,它支持一些動態調度算法,比如最小鏈接、帶權重的最小鏈接、最短期望延遲等。
直接路由
直接路由是通過調度器修改數據包的目的MAC地址,轉發請求數據包,但是響應數據包可以直接發送給外網的方式。這樣做顯而易見的好處就是無需擔心網關瓶頸,但是實際的服務器和調度服務器都需要鏈接在WAN交換機上,並且擁有獨立的外網IP地址。
這種方式的工作原理略微復雜:
首先每台服務器都需要設置一個IP別名,這個IP別名是面向客戶端的一個虛擬IP,只有代理服務器對這個IP別名的ARP請求做出響應,這樣客戶端發給這個IP的請求包首先會到代理服務器。然后代理服務器將這個請求包的目的MAC地址填寫為實際服務器的MAC地址(通過某種調度算法決定目的服務器),由於目標服務器也具有這個IP別名,因此,轉發過來的數據包能夠被實際的服務器接收並處理。最后由於數據包的源IP地址還是客戶端請求的IP地址,因此,實際的服務器將通過交換機直接將響應包轉發給客戶端而無需通過代理服務器。
Linux下可以通過LVS-DR實現直接路由方式
IP隧道
IP隧道的意思是,調度器將原始的IP數據包封裝在新的IP數據包中,以實現調度,實際的服務器可以將響應數據包直接轉發給用戶端。
共享文件系統
對於一些簡單的提供文件下載的服務(包括html中靜態資源等),自然要考慮利用集群來減壓,但是如何使這些資源在集群中的主機上同步呢。
NFS
一種方案是讓這些主機從同一個地方取數據。比如采用NFS(Network File System),基於PRC。這種方式簡單易行,但是由於NFS服務器本身的磁盤吞吐率,或者並發處理能力以及帶寬等問題,往往很有局限性。
冗余分發
另一個方案就是在主機上冗余存儲資源,這樣主機無需訪問共享文件系統,只需讀取本地磁盤上的資源即可。但是這也帶來了一個同步的問題,如何同步這些數據呢:
主動分發式,還分為單級分發和多級分發,分發可以借助SCP、SFTP、HTTP擴展協議WebDAV
- 單級分發:通過一次分發,就達到目的,這樣的方案簡單易行,但是性能瓶頸會出現在磁盤壓力和網絡帶寬,難以擴展
- 多級分發:通過多次分發,才達到目的地,這樣的方案能夠分散磁盤壓力和網絡帶寬壓力,而且容易擴展,壞處是成本高
被動同步式容易理解,可以使用rsync,rsync同步時是根據最后更新時間進行判定是否需要同步的條件的,因此,如果一個文件夾中有的文件數量太多的話,rsync掃描的時間就很長了,可以通過給文件夾設置最后更新時間,並合理的規划文件目錄,來加快rsync的掃描時間。即使不使用rsync,自己開發同步程序也可以借助這樣的思想來提升性能。
分布式文件系統
分布式文件系統工作在用戶進程層面上,它是一個管理文件的平台,內部維護冗余,檢索,追蹤、調度等工作,通常包含一個物理層面的組織結構和邏輯層面的組織結構。物理層面的組織結構由分布式文件系統自行維護,邏輯層面的組織結構面向用戶。其中“追蹤器”起到了關鍵的作用。
MogileFS就是一個開源分布式文件系統,用Perl編寫,包含追蹤器、存儲節點、管理工具,它使用MySQL分布式文件系統的所有信息、使用WebDAV實現文件復制。其他著名的還有Hadoop。
每個文件由一個key定義,需要讀取文件時,指定一個key,追蹤器會返回一個實際的路徑,在訪問這個地址即可獲得文件。甚至可以將這個key對應的path用分布式緩存緩存起來,這樣可以減少追蹤器的查詢開銷,但這樣也會失去分布式文件系統的調度策略的優越性。另外,可以利用支持reproxy的反向代理服務器(比如:Perlbal)讓路徑重定向的工作由反向代理服務器完成。
數據庫擴展
主從復制,讀寫分離
這種方式是指利用數據庫的復制或鏡像功能,同時在多台數據庫上保存相同的數據,並且將讀操作和寫操作分開,寫操作集中在一台主數據庫上,讀操作集中在多台從數據庫上,對於讀取比寫更多的站點適合使用這種方式。如果不想在應用程序層面維護這種分離映射,那么可以使用數據庫反向代理來自動完成對讀寫的分離。
垂直分區
對於不需要進行聯合查詢的數據表可以分散到不同的數據庫服務器上,這稱為垂直分區;當然每個分區自身也可以使用讀寫分離。
水平分區
將同一個表的記錄拆分到不同的表甚至是服務器上,稱為水平分區,這往往需要一個穩定的算法來保證讀取時能正確從不同的服務器上取得數據,比如簡單的對ID取模、范圍划分、亦或者是保存映射關系。 也可以使用類似代理的產品spock。
總結
本文概括了《構建高性能web站點》書中關於基礎架構部分的內容,只是一個簡明的概要,幾乎每個地方都有很大的學問值得深究。
勞動果實,轉載請注明出處:http://www.cnblogs.com/P_Chou/archive/2012/10/10/high-performance-web-site-infrastructure.html

