前言css
在前一篇隨筆《大型網站系統架構的演化》中,介紹了大型網站的演化過程,期間穿插了一些技術和手段,咱們能夠從中看出一個大型網站的輪廓,但想要掌握設計開發維護大型網站的技術,須要咱們一步一步去研究實踐。因此我打算寫一個系列,從理論到實踐講述大型網站的點滴,這也是一個共同窗習的過程,但願本身能堅持下去。系列大概會分爲兩部分,理論和實踐,理論部分儘可能通俗易懂,也要講一些細節。實踐部分會抽取一些技術作實踐,將方法、解決問題過程分享出來。html
本文將講述大型網站中一個重要的要素,性能。java
什麼是性能web
有人說性能就是訪問速度快慢,這是最直觀的說法,也是用戶的真實體驗。一個用戶從輸入網址到按下回車鍵,看到網頁的快慢,這就是性能。對於咱們來講,須要去挖掘這個過程,由於這決定咱們怎麼去作性能優化。算法
這中間發生了什麼?數據庫
用戶訪問網站的整個流程:用戶輸入網站域名,經過DNS解析,找到目標服務器IP,請求數據經互聯網達到目標服務器,目標服務器收到請求數據,進行處理(執行程序、訪問數據庫、文件服務器等)。處理完成,將響應數據又經互聯網返回給用戶瀏覽器,瀏覽器獲得結果進行計算渲染顯示給用戶。瀏覽器
咱們把整個過程,分爲三段路徑:緩存
一、第一段在用戶和瀏覽器端,主要負責發出用戶請求,以及接受響應數據進行計算渲染顯示給用戶;性能優化
二、第二段在網絡上,負責對請求數據、響應數據的傳輸;服務器
三、第三段在網站服務器端,負責對請求數據進行處理(執行程序、訪問數據庫、文件等),並將結果返回;
第一路徑
第一路徑花費的時間包括輸入域名發起請求的時間和瀏覽器收到響應後計算渲染的時間。
輸入域名發起請求,實質過程是:
一、用戶在瀏覽器輸入要訪問的網站域名;
二、本地DNS請求網站受權的DNS服務器對域名進行解析,並獲得解析結果即IP地址(並將IP地址緩存起來)。
三、向目標IP地址發出請求。
從這個過程咱們能夠看到,優化的地方主要是減小DNS解析次數,而若是用戶瀏覽器設置了緩存,則再第二次訪問相同域名的時候就不會去請求DNS服務器,直接用緩存中的IP地址發出請求。所以這個過程主要取決於瀏覽器的設置。如今主流的瀏覽器默認設置了DNS的預取功能(DNS Prefetch),固然你也能夠主動告知瀏覽器個人網站須要作DNS預取:
<meta http-equiv="x-dns-prefetch-control" content="on" />
瀏覽器將數據進行計算渲染的過程:
一、瀏覽器解析響應數據;
二、瀏覽器建立DOM樹;
三、瀏覽器下載CSS樣式,並應用到DOM樹,進行渲染;
四、瀏覽器下載JS文件,開始解析執行;
五、顯示給用戶。
從這個過程,咱們能夠找出很多能夠優化的地方。首先咱們能夠儘可能控制頁面大小,使得瀏覽器解析的時間更短;而且將多個CSS文件、JS文件文件合併壓縮減小文件下載的次數和大小;另外注意將CSS放在頁面前面,JS訪問頁面後面,這樣便於頁面首先能渲染出來,再執行js腳本,對於用戶來講有更好的體驗。最後我還能夠設置瀏覽器緩存,下次訪問時從緩存讀取內容,減小http請求。
<meta http-equiv="Cache-Control" content="max-age=5" />
該代碼說明了瀏覽器啓用了緩存並在5秒內不會再次訪問服務器。注意緩存的設置須要結合你的業務特性來適當配置。
如下是京東商城的HTML簡圖:
css樣式放在html前面,而且進行了合併。
大多數的JS文件放在頁尾。
第二路徑
第二路徑在網絡上,花費的時間一樣包括請求數據的傳輸時間和響應數據的傳輸時間,這個兩個時間取決於數據傳輸的速度,這裏咱們要講一個名詞「帶寬」。什麼是帶寬,咱們常常說帶寬10M,20M是什麼意思?個人帶寬20M,這意味着什麼?咱們知道帶寬速度分爲上行、下行速度,也就是上傳和下載的速度。帶寬20M對於用戶來講則是下載速度20M(20×1024×1024比特率),換算成字節20M/8=2.5M。也就是說20M的帶寬下載速度理論可達2.5M/s,而對於家庭用戶而言上傳速度通常比下載速度小的多,大約是不到十分之一。而對於網站服務器(企業用戶)來講,則否則,通常上行速度等於下載速度。這也是運營商根據實際需求分配的,畢竟用戶的主要需求是下載數據,而不是上傳數據。
整個流程從傳輸方式看就是:用戶發送請求數據(上傳),網站服務器接受請求數據(下載),網站服務器返回響應數據(上傳),用戶接受響應數據(下載)。對於用戶來講,上傳數據是很小的(Url參數),而下載數據是較大的(響應數據);對於服務器來講,下載數據是很小的(url參數),上傳數據是較大(響應數據)。理解了這個,咱們能夠解釋爲何有時用戶反映爲何本身的帶寬足夠,但打開某些網站仍然很慢,就是由於儘管用戶的下載速度很快,但網站服務器的上傳速度很慢,這就像一個抽水管和一個出水管,無論抽水管再大,但出水管很小,一樣抽到的水量是有限的。瞭解了這個原理咱們來看怎麼提升數據傳輸的速度,首先用戶的上傳、下載速度咱們是沒法決定的,咱們能決定的是網站服務器的上傳、下載速度,因此咱們能夠作的是適當的增長服務器帶寬(帶寬是很貴的,盲目的增長只會增長沒必要要成本)。購買合適的帶寬須要根據網站業務特性、規模以及結合運維人員的經驗來選擇。一般能夠考慮的算法,即根據一次響應數據的大小,乘以PV數,除以對應的高峯時間段,從而大體估算出網站帶寬的需求。
下面咱們繼續進一步研究第二路徑:
上圖表示用戶訪問網站服務器時網絡的大體狀況,從圖上能夠看出假設網站服務器從電信網絡接入,而用戶A做爲電信的寬帶用戶,則能夠經過電信骨幹網快速的訪問到網站服務器。用戶B,用戶C做爲移動和聯通用戶須要經過運營商的互聯互通通過較長路徑才能訪問到服務器。
針對這種狀況,咱們能夠採起如下方法來優化:
一、在各運營商發達的地區的IDC(互聯網數據中心,能夠理解成機房)部署網站服務器,各運營商的用戶便可經過各自的骨幹網訪問服務器。
二、購買代理服務,也就是原來聯通用戶須要經過聯通骨幹網——>聯通互聯互通路由器——>電信骨幹網——>網站服務器的過程。經過代理服務,代理服務器直連到電信骨幹網,訪問網站服務器。
二、在主要地區城市購買CDN服務,緩存對應的數據,用戶可先從最近的CDN運營商獲取請求數據。
第三路徑
第三路徑主要是網站服務器內部處理的過程,當中包括執行程序、訪問文件、數據庫等資源。
這是對於咱們來講最能夠發揮的地方:
一、使用緩存,根據須要使用本地緩存或分佈式緩存;
二、使用異步操做,這種方式不只能夠提升性能,也提升了系統的擴展性;
三、代碼優化;
四、存儲優化;
緩存
若是緩存數據較少,能夠利用OSCache實現本地緩存:
當緩存數據過多時,利用Memcached實現分佈式緩存:
Memcached實現分佈式緩存,緩存服務器之間是互不通訊的,也就是咱們能夠方便的經過增長Memcached服務器對系統進行擴展。
異步操做
使用同步請求的方式,在高併發的狀況下,會對數據庫形成很大的壓力,也會讓用戶感受響應時間過長。異步請求方式,則能夠快速的對用戶作出響應,而具體的數據庫操做請求,則經過消息隊列服務器發送給數據庫服務器,作具體的插入操做。插入操做的結果則已其餘方式通知客戶端。例如通常在訂票系統當中,出票行爲就是異步完成,最終的出票結果會以郵件或其餘方式告知用戶。
代碼優化
這裏就不在詳細描述,另外一篇隨筆《怎樣編寫高質量的java代碼》對代碼質量和風格作過大體的介紹,有興趣能夠看一下。
存儲優化
大型網站中海量的數據讀寫對磁盤形成很大壓力,系統最大的瓶頸仍是在磁盤的讀寫。能夠考慮使用磁盤陣列、分佈式儲存來改善存儲的性能。
性能的指標和測試
上面經過解析用戶訪問網站的過程來思考怎麼提升用戶感知的性能,對於用戶來言性能就是快和慢。但對於咱們來講,不能這樣簡單描述,咱們須要去量化他,用一些數據指標去衡量它。這裏講到幾個名詞:響應時間、併發量、吞吐量。
響應時間:就是用戶發出請求到收到響應數據的時間;
併發量:就是系統同時能處理多少用戶請求;
吞吐量:就是單位時間內系統處理的請求數量;
爲了通俗的瞭解這三個概念,咱們以高速公路的收費站爲例子:響應時間是指一輛車通過收費站的時間,也就是車輛從進入收費站、付錢、開閘、離開收費站的時間;併發量是指這個收費站同時能通行多少輛車,能夠理解爲收費站的出口數量。吞吐量是指:在一段時間內,這個收費站通往了多少了車。
這個例子不曉得恰不恰當。
對於性能測試來講,基本也是圍繞這些方面來測試,下圖說明了性能測試的過程:
左圖表示響應時間和併發用戶量的二維座標圖,從圖上能夠看出,併發用戶量在必定量增長時,響應時間很短,而且沒有太大的起伏,這表示系統目前處於平常運行期,能夠很快處理用戶請求(A點以前);隨着併發量的增長,系統處於請求高峯期,但仍然能夠有序的處理用戶請求,響應時間較平常有所增長(A、B之間);當併發量增長到必定數量時,超過了系統的負載能力,系統處於瀕臨崩潰的邊緣(B、C之間),響應時間嚴重過長,直到系統崩潰。
右圖表示吞吐量與併發用戶量的二維座標圖,能夠看出,隨着併發用戶量的增長,吞吐量逐漸增長;在併發量到達必定量時,因爲系統處理能力達到最大,吞吐量增長放緩;當併發量超過系統負載時(E點),系統處理能力開始降低,不能再請求增長的用戶請求,吞吐量反而下降。
小結
本文經過用戶訪問網站的過程,分析了三個路徑過程當中提升性能的想法和手段,最後介紹了描述性能的指標,並對性能測試作了簡要說明。
參考資料:
《海量運維運營規劃》
《大型網站技術架構》
《構建高性能web站點》