如何打造高性能Web應用


Sean Hull是Heavyweight Internet Group的創始人兼高級顧問,擁有20年以上技術顧問相關經驗,曾爲多家知名機構提供諮詢,其中包括The Hollywood Reporter、Billboard、NBC Universal、Zagats、Rent the Runway及ideeli,這些高速增加的公司每月處理接近1億的獨立訪客。Hull在Amazon EC2部署和Linux及MySQL性能上有着豐富的經驗。巨大流量的處理需涉及多個方面,其中包括網站擴展性、業務連續性、安全及架構挑戰等。近日,Hull分享了高性能Web應用打造的經驗,剖析了擴展之路上20個最大的絆腳石。如下爲譯文:
 
1.  二階段提交
 
一般狀況下,當數據庫中的數據發生改變時,它須要同時被寫入內存和硬盤。當一個提交發生時,傳統數據庫須要負責數據在真實存儲媒質上的持久化。牢記,內存的數據在崩潰或者重啓後都會消失。即便數據已經在數據庫中緩存,數據庫仍然須要將其持久化到磁盤上,MySQL的二進制日誌及Oracle的redo日誌都符合這個要求。
 
經過MySQL集羣或者相似DRBD(Distributed Replicated Block Device)或者Amazon Multi-AZ(Multi-Availability Zone)的分佈式文件系統,提交併不只僅是在本地發生,同時也在遠端。二階段提交意味着須要從遠端獲得反饋,鑑於網絡及一些其它的延時,提交速度可能會被毫秒級的下降,彷彿高速公路上的全部汽車都因重載變慢。若有考慮使用Multi-AZ或者讀備份,不妨查看Amazon RDS(Relational Database Service)與MySQL的比較。
 
同步複製一樣會出現這些問題,所以MySQL解決方案是半同步的,這也能夠看作是在二階段提交上的一些讓步。
 
2.  緩存不足
 
在全部層中緩存的做用都相當重要,那麼什麼地方最須要使用緩存:瀏覽器、頁面、對象仍是數據庫存?下面不妨通通試一下。
 
瀏覽器緩存彷佛高不可攀,除非你清楚瀏覽器是從Web Server中取出指令及其渲染的頁面。所以,若是包含的對象有一個比較長的生命週期,瀏覽器將會緩存他們,不須要再次進行讀取。這不只會加快用戶的瀏覽速度,一樣會有益於Server對網站的託管,由於會切實的減小用戶的二次讀取。
 
猛戳這裏查看更多瀏覽器緩存相關,確保設置了期滿頭文件及緩存控制。
 
頁面緩存須要使用相似Varnish的技術,能夠將它當作一個迷你的高速、低開銷Web Server。它不能夠支撐相似Apache能夠的複雜頁面,可是它可讓很是簡單的頁面更快。所以位於Apache以前,用於減小負載,讓Apache能夠處理更加複雜的頁面。就像交通警察,在專一更復雜的機動車前,先給自行車放行。
 
對象緩存由相似memcache的組件完成,能夠把它當作是應用程序的便利貼。作數據庫查詢時會先訪問緩存尋求數據,若是發現了所需的數據,那麼結果返回的時間將比訪問數據庫快10-100倍,這樣就能夠快速的構建頁面,從而在眨眼間爲用戶呈現。若是它沒有發現所需的數據,或者只發現了一部分,那麼將會創建數據庫請求並將返回的數據放於緩存中,讓更多的後來者受益。
 
3.  緩慢的磁盤I/O、RAID 五、多租戶存儲
 
數據庫中的一切都受到存儲的限制,這裏既包含了空間問題,也受設備讀寫的速度掣肘。
 
若是你使用實體服務器,那麼必定要小心RAID 5,獨立磁盤冗餘陣列的一種,數據保護和奇偶性將嚴重的影響寫操做。同時,若是其中一個磁盤損壞,那麼這個陣列在磁盤重建時將變得很是緩慢。
 
這個方案通常使用RAID 10,它將爲你提供獨立的鏡像集。這致使沒有奇偶校驗計算,從而不會影響重建時的速度。
 
雲環境可能會涉及到相似於Amazon EBS(Elastic Block Store,一個相似於SAN的虛擬化磁盤)的技術。鑑於其基於網絡,你必須與其它租戶競爭存儲的讀寫。由於每一個存儲能支撐的讀寫速度是固定的,因此你的鄰居可能會影響到你網站及應用程序的讀寫速度。
 
最近,Amazon又公佈了一個重量級產品Provisioned IOPS(每秒I/O操做)。對於技術專家來講看起來很是不錯,可是對於其它人來講毫無價值。儘管如此,其依然重要,這意味着你能夠鎖定你數據庫所需的磁盤性能。若是你想在Amazon上託管數據庫,那麼不妨多關注一下這個。
 
4.  串行處理
 
在超市結帳時,若是有10個收銀臺開放,那麼從事的是並行處理。若是每一個收銀臺都在休息,只有一個登記處開放,那麼從事的是串行操做。那麼結帳的隊伍將變得很是長,不只是結帳人的心情受到影響,購物者也一樣如此。這點常常發生在線路不夠的大橋收費站以及許多人一塊兒離場的體育場所。
 
網絡應用須要嚴格的避免串行,因等待API調用而產生的阻塞,全部的後端節點都在等待一個搜索服務器,只要你應用程序的某處造成一個線就表明了串行化的發生,那麼必須不惜一切代價去清除它。
 
5.  缺乏Feature Flag
 
在給業務部門創建應用時,開發者通常從特性和功能入手。Feature Flag將相當重要,它讓人們能夠經過後端配置文件或管理員UI頁面關閉或者打開特性。
 
爲何他們如此重要?若是你有早上4點的救火經驗,那麼你將明白啓動應急計劃的必要性。你須要能夠關閉評級、評論以及應用程序其它的一些特性,這將不會致使整個系統崩潰。更重要的是,在新特性發布時,有些時候問題並不明顯,直到一羣互聯網用戶同時涌入。Feature Flag讓你能夠選擇性的關閉一些功能,而不是關掉整個網站。
 
 
6.  單一的數據庫副本
 
你必須使用一個以上的讀副本或者MySQL從節點,這容許在主節點出問題時的快速故障轉移。
 
擁有數據庫的多個副本意味着橫向擴展。若是你有兩個,你就會看到3-4個會對你基礎設施的提高。
 
7. 使用數據庫進行排隊
 
MySQL數據庫很是適合儲存表格、數據以及他們之間的關係,不幸的是,它並不適合處理應用程序的隊列。儘管如此,許多開發者都習慣使用一個表格來達到這個目的。好比,讓你的應用程序包含一些做業表格,或者一個狀態列,擁有一些相似「in-process」、「in-queue」 及「finished」的值。
 
由於鎖競爭、scan及 poll進程將形成更多的工做,這些解決方案會帶來一些擴展性問題,它們將會顯著的下降數據庫速度。幸運的是這裏存在不少有效的開源解決方案,好比RabbitMQ及Amazon的SQS。
 
8.  使用一個作全文查詢的數據庫
 
頁面搜索是掣肘應用程序的另外一個方面,儘管MySQL一段時間也支撐了full-text索引。可是它們只對MyISAM表格有效,其它類型表格都不買帳,一直困擾着開發者。
 
一個解決方案是使用相似Solr的專業搜索引擎,這些技術擁有許多很好的庫去支撐你的編程語言,同時會提供一個更快的搜索速度。這些方案一樣易於擴展,而且不會讓你的數據庫成爲累贅。
 
替代方案是Sphinx SE,一個MySQL存儲引擎,將Sphinx服務器整合進數據庫。此外,MySQL 5.6版本中還使用了InnoDB作全文搜索的默認搜索引擎。
 
9.  對象關係模型
 
ORM,就像毒藥同樣,一旦進行使用,就很難擺脫。有利的一面是ORM有益於快速原型,而且容許非專家級MySQL開發者使用對象或者內存模式進行讀寫訪問。若是你不進行擴展,那麼他們的速度將很是快,並讓功能的快速交付獲得保障。
 
而後DBA(數據庫管理員)會由於緩慢且醜陋的查詢來到開發團隊而且說:「這個查詢在應用程序什麼地方,咱們須要進行修復,它須要被重寫。」開發團隊則會說:「咱們也不知道!」從而會收到來自運營組一些質疑的眼神。
 
有能力對bad sql進行跟蹤並將其指出是很是重要的。DBA團隊須要必定的指引找到bad sql的源頭。若是查詢是來自ORM,他們並不具有這些指引。這樣你的團隊將面對一個巨大的技術負債,一樣也是個很是難以解決的挑戰。
 
10.  缺乏Instrumentation
 
Instrumentation(儀表盤)爲應用程序提供了碼錶和油表,這是汽車不可缺乏的兩個部分。他們提供了應用程序的內部工做信息:他們記錄了時間信息,而且提供了應用程序耗時最多的環節。
 
一個很是人氣的網絡解決方案就是New Relic,它提供了一個很是全面的可視化界面,針對各個領域工做者——項目經理、開發者、運營團隊,甚至是業務部門均可以從圖中發現問題所在。固然,如今已經有不少的開源Instrumentation。
 
11.  缺乏代碼倉庫及版本管理
 
儘管如今這個問題已很是少見,可是還有有些互聯網公司在沒有版本控制下去創建應用程序。固然那些使用了的人,很清楚它將給團隊帶來的平常優點和組織控制。
 
若是你沒有使用,隨着應用程序變得更加複雜,你將被捲入技術負債的漩渦,爲應用不一樣部分添加員工將變得異常困難。
 
一旦你使用版本控制,確保囊括了全部的組件,包含配置文件以及其它要素。而丟失部署時須要用到的部分,將帶來額外的風險。
 
12.  單點故障
 
若是你的數據只存在一個主數據庫上,這就是一個單點故障。若是你的服務器位於一個單獨的磁盤上,這也是個單點故障。單點故障能夠比做「阿基里斯之踵」技術用語。
 
不惜任何代價,單點故障都要在應用程序中移除。麻煩的是如何去認識單點故障,即便是選擇單一的雲供應商均可以稱爲單點故障,若是擁有多個供應商,或者使用Amazon不一樣的部分,那麼AirBNB的服務將倖免Amazon 2012年10月的部分宕機。
 
13.  缺少只瀏覽模式
 
若是你深夜在Yelp、Facebook或者是Tumblr上發佈評論,你可能就會收到這樣的信息:「該特性不可用,請稍後再試」。稍後多是50或者60分鐘,也許可能還需多試幾回。對於非技術用戶,他們仍然感受網站在正常運行,只是奇怪了一點而已。
 
實際狀況是,應用程序只容許你去瀏覽網站,可是不能夠作任何改變。多是主數據庫或者是一些存儲組件不可用了。
 
只瀏覽模式能夠經過保留主數據庫的多個讀備份來實現,使用MySQL副本或者是Amazon讀副本相似途徑。這樣就能夠在沒有主數據庫狀況下,保留網站所有瀏覽功能正常,這一點很是重要。
 
14.  脆弱的溝通
 
在擴展上談溝通可能很是奇怪,可是應用程序技術層不可能由於團隊間社交和文化上的差別分離。
 
強大的通訊線路是必要的,隊員必需要知道在錯誤發生時將找誰。好的交流須要自信及知識淵博的領導,普遍的聽取意見並加以改善。
 
15.  缺乏文檔
 
當Web應用程序包含許多層時,文檔相當重要。開發者須要給程序、功能、頁面作文檔,讓後來者看代碼時能夠清晰的發現所需的提示及看法。當有程序發生故障時,運營程序須要在配置文件上添加評論去代表更改歷史。業務流程及關係一樣應該出如今公司的wiki裏,讓人們發現本身問題的解決方案。
 
文檔能夠在各個層次起到幫助做用,每一個人都應該擁抱這個愛好。
 
16  缺乏應急演習
 
應急一般狀況下總會被忽視,團隊可能會有「咱們覆蓋的地方都有備份」這類的說辭。不錯備份、恢復的途徑很通吃,關鍵是確保備份的文件萬無一失。一旦在故障轉移時發現備份有缺失,那麼你不肯意發生的事情必然發生。
 
應急演習讓事情發生以前有了相應的經驗,公司應該將此做爲運營團隊工做的一部分,每一年都須要進行幾回。在雲時代,應急演習已經變得比之前輕鬆許多。爲保證全部組件都被備份而啓動服務器是很是值得的,在這個過程當中你將學到這項操做該持續多長時間,以及困難所在的地方,更知道須要當心些什麼。
 
17.  缺乏監視和指標
 
監視有着與版本控制一樣的重要性:很是基本,缺乏它工做將沒法進行;然而確實有一些網站沒有監視,或者是監視力度不夠——有些服務器或者是核心組件並未被監視。
 
不間斷的收集系統及服務器數據,同時,應用程序和業務級別的可用性也同等重要。若是你不想親自動手,不妨考慮一個Web服務方案。
 
18.  莽撞的運營
 
你騎着馬在街道上飛奔,明着帶槍進入酒吧,你認爲這是在交朋友?確定不是,你在暴力的脅迫別人遵循,全部人都不會有歸屬感。強大的信心是好的,可是團隊的合做是不可缺乏的,團隊的智慧高於任何我的。
 
團隊須要不斷的對改變作交流,用管理的角度進行,準備好應對失敗等等。採起當心及規避風險的態度,永遠都有備用計劃,你應該有能力撤銷全部改變,而且認真對待破壞性的改變,以及那些不可恢復的地方。
 
19.  日益增加的技術負債
 
隨着應用不斷的增加,隊伍須要花愈來愈多的時間在老代碼的維護和支持上,消除漏洞及缺陷。所以,花在新特性上的時間將愈來愈少。必須謹慎的維護好新特性與技術負債上投入時間的平衡。若是你發現你的技術負債增長,可能就是橫下決心重寫的時候了。重寫可能會影響到短時間新特性及客戶特性的開發,可是從長遠的角度上看是很是好的。
 
技術負債並不老是能被輕易的認知,在你創建特性或者是修復bug時,你更習慣於聚焦局部的細節,很是容易失去全局觀,這也是爲何全面人才更益於Web擴展的緣由。
 
20.  不足的日誌
 
日誌直接影響到度量及監視。你在尋找故障和排錯時確定但願獲得更多的日誌,可是在一個不間斷運行的狀況下,你一樣會須要一些關鍵服務的日誌。服務器系統日誌、Apache及MySQL日誌、緩存日誌等,這些都須要被保存。而在日誌太多時,你老是會減小一些地方的日誌,或者裁剪及循環日誌文件,從而丟棄舊的。
 
相關文章
相關標籤/搜索