酒濃碼濃 - 前端HTTP性能優化

HTTP性能優化

衡量服務器性能的主要指標有三個:

吞吐量(requests per second)

吞吐量就是我們常說的 RPS,每秒的請求次數,也有叫 TPS、QPS,它是服務器最基本的性能指標,RPS 越高就說明服務器的性能越好。

併發數(concurrency)

併發數反映的是服務器的負載能力,也就是服務器能夠同時支持的客戶端數量,當然也是越多越好,能夠服務更多的用戶。

響應時間(time per request)

響應時間反映的是服務器的處理能力,也就是快慢程度,響應時間越短,單位時間內服務器就能夠給越多的用戶提供服務,提高吞吐量和併發數。

 

分析問題 :

除了上面的三個基本性能指標,服務器還要考慮 CPU、內存、硬盤和網卡等系統資源的佔用程度,利用率過高或者過低都可能有問題。

服務器接入互聯網的傳輸線路,它的帶寬直接決定了網站對外的服務能力,也就是吞吐量等指標。顯然,優化性能應該在這加大投入,儘量購買大帶寬,接入更多的運營商網絡。

  • 地理因素,因爲地理距離而訪問數千公里外的網站顯然會有更大的延遲。

由許多小網絡組成的實際的互聯網,非常非常龐大和複雜的網絡,地理距離、網絡互通都嚴重影響了傳輸速度。好在這裏面有一個 HTTP 的“好幫手”——CDN。

  • 帶寬,它又包括接入互聯網時的電纜、WiFi、4G 和運營商內部網絡、運營商之間網絡的各種帶寬,每一處都有可能成爲數據傳輸的瓶頸,降低傳輸速度,增加延遲。

用戶訪問互聯網的入口,對於固網用戶就是光纖、網線,對於移動用戶就是 WiFi、基站。以前它是客戶端性能的主要瓶頸,延遲大帶寬小,但隨着近幾年 4G 和高速寬帶的普及,情況已經好了很多,不再是制約性能的主要因素了。

  • DNS 查詢,如果域名在本地沒有緩存,就必須向 DNS 系統發起查詢,引發一連串的網絡通信成本,而在獲取 IP 地址之前客戶端只能等待,無法訪問網站。

前端可以用link標籤對域名預讀取DNS https://blog.csdn.net/mx18519142864/article/details/105973641

  • TCP 握手,你應該對它比較熟悉了吧,必須要經過 SYN、SYN/ACK、ACK 三個包之後才能建立連接,它帶來的延遲由光速和帶寬共同決定。建立 TCP 連接之後,就是正常的數據收發了,後面還有解析 HTML、執行 JavaScript、排版渲染等等,這些也會耗費一些時間。不過它們已經不屬於 HTTP 了,所以不在今天的討論範圍之內。


解決問題 :

  • 我們應該選用高性能的 Web 服務器

最佳選擇當然就是 Nginx/OpenResty 了,儘量不要選擇基於 Java、Python、Ruby 的其他服務器,它們用來做後面的業務邏輯服務器更好。利用 Nginx 強大的反向代理能力實現“動靜分離”,動態頁面交給 Tomcat、Django、Rails,圖片、樣式表等靜態資源交給 Nginx。

  • 減少客戶端和服務器之間收發的數據量,在有限的帶寬裏傳輸更多的內容。

使用 HTTP 協議內置的“數據壓縮”編碼,不僅可以選擇標準的 gzip,還可以積極嘗試新的壓縮算法 br,它有更好的壓縮效果。

不過在數據壓縮的時候應當注意選擇適當的壓縮率,不要追求最高壓縮比,否則會耗費服務器的計算資源,增加響應時間,降低服務能力,反而會“得不償失”。

gzip 和 br 是通用的壓縮算法,對於 HTTP 協議傳輸的各種格式數據,我們還可以有針對性地採用特殊的壓縮方式。

HTML/CSS/JavaScript 屬於純文本,就可以採用特殊的“壓縮”,去掉源碼裏多餘的空格、換行、註釋等元素。這樣“壓縮”之後的文本雖然看起來很混亂,對“人類”不友好,但計算機仍然能夠毫無障礙地閱讀,不影響瀏覽器上的運行效果。

圖片在 HTTP 傳輸裏佔有非常高的比例,雖然它本身已經被壓縮過了,不能被 gzip、br 處理,但仍然有優化的空間。比如說,去除圖片裏的拍攝時間、地點、機型等元數據,適當降低分辨率,縮小尺寸。圖片的格式也很關鍵,儘量選擇高壓縮率的格式,有損格式應該用 JPEG,無損格式應該用 Webp 格式。

  • 對於小文本或者小圖片,還有一種叫做“資源合併”(Concatenation)的優化方式

就是把許多小資源合併成一個大資源,用一個請求全下載到客戶端,然後客戶端再用 JavaScript、CSS 切分後使用,好處是節省了請求次數,但缺點是處理比較麻煩。

  • 減少 header 的大小

剛纔說的幾種數據壓縮針對的都是 HTTP 報文裏的 body,在 HTTP/1 裏沒有辦法可以壓縮 header,但我們也可以採取一些手段來減少 header 的大小,不必要的字段就儘量不發(例如 Server、X-Powered-By)。

  • 避免使用 Cookie

網站經常會使用 Cookie 來記錄用戶的數據,瀏覽器訪問網站時每次都會帶上 Cookie,冗餘度很高。所以應當少使用 Cookie,減少 Cookie 記錄的數據量,總使用 domain 和 path 屬性限定 Cookie 的作用域,儘可能減少 Cookie 的傳輸。如果客戶端是現代瀏覽器,還可以使用 HTML5 裏定義的 Web Local Storage。

  • 域名和重定向

DNS 解析域名會耗費不少的時間,如果網站擁有多個域名,那麼域名解析獲取 IP 地址就是一個不小的成本,所以應當適當“收縮”域名,限制在兩三個左右,減少解析完整域名所需的時間,讓客戶端儘快從系統緩存裏獲取解析結果。

重定向引發的客戶端延遲也很高,它不僅增加了一次請求往返,還有可能導致新域名的 DNS 解析,是 HTTP 前端性能優化的“大忌”。除非必要,應當儘量不使用重定向,或者使用 Web 服務器的“內部重定向”。

  • 緩存 —— 沒有請求的請求,纔是最快的請求。

網站系統內部,可以使用 Memcache、Redis、Varnish 等專門的緩存服務,把計算的中間結果和資源存儲在內存或者硬盤裏,Web 服務器首先檢查緩存系統,如果有數據就立即返回給客戶端,省去了訪問後臺服務的時間。

使用CDN 。

使用 max-age 有效期,標記資源可緩存的時間。對於圖片、CSS 等靜態資源可以設置較長的時間,比如一天或者一個月,對於動態資源,除非是實時性非常高,也可以設置一個較短的時間,比如 1 秒或者 5 秒。

緩存是無論何時都不能忘記的性能優化利器,應該總使用 Etag 或 Last-modified 字段標記資源

  • HTTP/1 升級到 HTTP/2

HTTP/2 的很多優點,它消除了應用層的隊頭阻塞,擁有頭部壓縮、二進制幀、多路複用、流量控制、服務器推送等許多新特性,大幅度提升了 HTTP 的傳輸效率。因爲這些都已經內置在了協議內,所以只要換上 HTTP/2,網站就能夠立刻獲得顯著的性能提升。

注意:一些在 HTTP/1 裏的優化手段到了 HTTP/2 裏會有“反效果”。

對於 HTTP/2 來說,一個域名使用一個 TCP 連接才能夠獲得最佳性能,如果開多個域名,就會浪費帶寬和服務器資源,也會降低 HTTP/2 的效率,所以“域名收縮”在 HTTP/2 裏是必須要做的。

“資源合併”在 HTTP/1 裏減少了多次請求的成本,但在 HTTP/2 裏因爲有頭部壓縮和多路複用,傳輸小文件的成本很低,所以合併就失去了意義。而且“資源合併”還有一個缺點,就是降低了緩存的可用性,只要一個小文件更新,整個緩存就完全失效,必須重新下載。所以在現在的大帶寬和 CDN 應用場景下,應當儘量少用資源合併(JavaScript、CSS 圖片合併,數據內嵌),讓資源的粒度儘可能地小,才能更好地發揮緩存的作用。


有很多工具可以測量這些指標:

服務器端有 ab、top、sar 等,

客戶端可以使用瀏覽器的開發者工具、如下測試網站

https://gtmetrix.com/

https://developers.google.cn/speed/pagespeed/insights/

圖片壓縮網站

https://tinypng.com/

 

本文學習自 https://time.geekbang.org/column/article/127808

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章