一华畏、哪些地方存在性能問題
- 從 HTTP 最基本的“請(qǐng)求 - 應(yīng)答”模型看谨敛,這個(gè)模型有兩個(gè)角色:客戶端和服務(wù)器媳荒,還有中間的傳輸鏈路抗悍,考查性能就可以看這三個(gè)部分。
1. HTTP服務(wù)器
- 它一般運(yùn)行在 Linux 操作系統(tǒng)上钳枕,用 Apache缴渊、Nginx 等 Web 服務(wù)器軟件對(duì)外提供服務(wù),所以鱼炒,性能的含義就是它的服務(wù)能力衔沼,也就是盡可能多、盡可能快地處理用戶的請(qǐng)求。
- 衡量服務(wù)器性能的主要指標(biāo)有三個(gè):吞吐量(requests per second)俐巴、并發(fā)數(shù)(concurrency)和響應(yīng)時(shí)間(time per request)骨望。
1. 吞吐量
- 吞吐量就是我們常說的 RPS,每秒的請(qǐng)求次數(shù)欣舵,也有叫 TPS擎鸠、QPS,它是服務(wù)器最基本的性能指標(biāo)缘圈,RPS 越高就說明服務(wù)器的性能越好劣光。
2. 并發(fā)數(shù)
- 并發(fā)數(shù)反映的是服務(wù)器的負(fù)載能力,也就是服務(wù)器能夠同時(shí)支持的客戶端數(shù)量糟把,當(dāng)然也是越多越好绢涡,能夠服務(wù)更多的用戶。
3. 響應(yīng)時(shí)間
- 響應(yīng)時(shí)間反映的是服務(wù)器的處理能力遣疯,也就是快慢程度雄可,響應(yīng)時(shí)間越短,單位時(shí)間內(nèi)服務(wù)器就能夠給越多的用戶提供服務(wù)缠犀,提高吞吐量和并發(fā)數(shù)数苫。
4. 其他
- 服務(wù)器還要考慮 CPU、內(nèi)存辨液、硬盤和網(wǎng)卡等系統(tǒng)資源的占用程度虐急,利用率過高或者過低都可能有問題。
5. 性能測(cè)試工具
- 在 Linux 上滔迈,最常用的性能測(cè)試工具可能就是 ab
#指定了并發(fā)數(shù) 100止吁,總共發(fā)送 10000 個(gè)請(qǐng)求:
ab -c 100 -n 10000 'http://www.xxx.com'
-
系統(tǒng)資源監(jiān)控方面,Linux 自帶的工具也非常多
- uptime燎悍、top敬惦、vmstat、netstat间涵、sar 等等
服務(wù)器的性能優(yōu)化方向:合理利用系統(tǒng)資源仁热,提高服務(wù)器的吞吐量和并發(fā)數(shù),降低響應(yīng)時(shí)間勾哩。
2. HTTP客戶端
- 客戶端是信息的消費(fèi)者抗蠢,一切數(shù)據(jù)都要通過網(wǎng)絡(luò)從服務(wù)器獲取,所以它最基本的性能指標(biāo)就是“延遲”(latency)思劳。
1. 延遲的可能原因
-
“不可逾越”的障礙——光速
- 因?yàn)榈乩砭嚯x而導(dǎo)致的延遲是無法克服的迅矛,訪問數(shù)千公里外的網(wǎng)站顯然會(huì)有更大的延遲。
-
寬帶
- 包括接入互聯(lián)網(wǎng)時(shí)的電纜潜叛、WiFi秽褒、4G 和運(yùn)營(yíng)商內(nèi)部網(wǎng)絡(luò)壶硅、運(yùn)營(yíng)商之間網(wǎng)絡(luò)的各種帶寬
- 每一處都有可能成為數(shù)據(jù)傳輸?shù)钠款i,降低傳輸速度销斟,增加延遲庐椒。
-
DNS 查詢
- 如果域名在本地沒有緩存,就必須向 DNS 系統(tǒng)發(fā)起查詢蚂踊,引發(fā)一連串的網(wǎng)絡(luò)通信成本约谈,而在獲取 IP 地址之前客戶端只能等待,無法訪問網(wǎng)站犁钟。
-
TCP 握手
- 必須要經(jīng)過 SYN棱诱、SYN/ACK、ACK 三個(gè)包之后才能建立連接涝动,它帶來的延遲由光速和帶寬共同決定迈勋。
2. 測(cè)試
-
WebPageTest
- 它的特點(diǎn)是在世界各地建立了很多的測(cè)試點(diǎn),可以任意選擇地理位置醋粟、機(jī)型靡菇、操作系統(tǒng)和瀏覽器發(fā)起測(cè)試,非常方便昔穴,用法也很簡(jiǎn)單
-
- 圖里面的這些指標(biāo)都是含義
- 因?yàn)橛小瓣?duì)頭阻塞”镰官,瀏覽器對(duì)每個(gè)域名最多開 6 個(gè)并發(fā)連接(HTTP/1.1),當(dāng)頁面里鏈接很多的時(shí)候就必須排隊(duì)等待(Queued吗货、Queueing),這里它就等待了 1.62 秒狈网,然后才被瀏覽器正式處理宙搬;
- 瀏覽器要預(yù)先分配資源,調(diào)度連接拓哺,花費(fèi)了 11.56 毫秒(Stalled);
- 連接前必須要解析域名勇垛,這里因?yàn)橛斜镜鼐彺妫灾幌牧?0.41 毫秒(DNS Lookup)士鸥;
- 與網(wǎng)站服務(wù)器建立連接的成本很高闲孤,總共花費(fèi)了 270.87 毫秒,其中有 134.89 毫秒用于 TLS 握手烤礁,那么 TCP 握手的時(shí)間就是 135.98 毫秒(Initial connection讼积、SSL);
- 際發(fā)送數(shù)據(jù)非辰抛校快勤众,只用了 0.11 毫秒(Request sent);
- 之后就是等待服務(wù)器的響應(yīng)鲤脏,專有名詞叫 TTFB(Time To First Byte)们颜,也就是“首字節(jié)響應(yīng)時(shí)間”吕朵,里面包括了服務(wù)器的處理時(shí)間和網(wǎng)絡(luò)傳輸時(shí)間,花了 124.2 毫秒窥突;
- 接收數(shù)據(jù)也是非撑#快的亿遂,用了 3.58 毫秒(Content Dowload)唁情。
- 圖里面的這些指標(biāo)都是含義
3. HTTP 傳輸鏈路
- 客戶端和服務(wù)器之間的傳輸鏈路,它也是影響 HTTP 性能的關(guān)鍵弄喘。
1. 三公里
-
第一公里
- 指網(wǎng)站的出口则拷,也就是服務(wù)器接入互聯(lián)網(wǎng)的傳輸線路贡蓖,它的帶寬直接決定了網(wǎng)站對(duì)外的服務(wù)能力,也就是吞吐量等指標(biāo)
- 顯然煌茬,優(yōu)化性能應(yīng)該在這“第一公里”加大投入斥铺,盡量購買大帶寬,接入更多的運(yùn)營(yíng)商網(wǎng)絡(luò)坛善。
-
中間一公里
- 由許多小網(wǎng)絡(luò)組成的實(shí)際的互聯(lián)網(wǎng)晾蜘,其實(shí)它遠(yuǎn)不止“一公里”,而是非常非常龐大和復(fù)雜的網(wǎng)絡(luò)眠屎,地理距離剔交、網(wǎng)絡(luò)互通都嚴(yán)重影響了傳輸速度
- 好在這里面有一個(gè) HTTP 的“好幫手”——CDN,它可以幫助網(wǎng)站跨越“千山萬水”改衩,讓這段距離看起來真的就好像只有“一公里”岖常。
-
最后一公里
- 用戶訪問互聯(lián)網(wǎng)的入口,對(duì)于固網(wǎng)用戶就是光纖葫督、網(wǎng)線竭鞍,對(duì)于移動(dòng)用戶就是 WiFi、基站
-
第零公里
- 網(wǎng)站內(nèi)部的 Web 服務(wù)系統(tǒng)
- 它其實(shí)也是一個(gè)小型的網(wǎng)絡(luò)(當(dāng)然也可能會(huì)非常大)橄镜,中間的數(shù)據(jù)處理偎快、傳輸會(huì)導(dǎo)致延遲,增加服務(wù)器的響應(yīng)時(shí)間洽胶,也是一個(gè)不可忽視的優(yōu)化點(diǎn)晒夹。
二、性能優(yōu)化
- 可優(yōu)化的環(huán)節(jié)姊氓,分別是服務(wù)器丐怯、客戶端和傳輸鏈路(“第一公里”和“中間一公里”),
- 但因?yàn)槲覀兪菬o法完全控制客戶端的他膳,實(shí)際上的優(yōu)化工作通常是在服務(wù)器端响逢。這里又可以細(xì)分為后端和前端,后端是指網(wǎng)站的后臺(tái)服務(wù)棕孙,而前端就是 HTML舔亭、CSS些膨、圖片等展現(xiàn)在客戶端的代碼和數(shù)據(jù)。
1. 花錢
1. 投資購買現(xiàn)成的硬件最簡(jiǎn)單的優(yōu)化方式
- 比如換上更強(qiáng)的 CPU钦铺、更快的網(wǎng)卡订雾、更大的帶寬、更多的服務(wù)器矛洞,效果也會(huì)“立竿見影”洼哎,直接提升網(wǎng)站的服務(wù)能力,也就實(shí)現(xiàn)了 HTTP 優(yōu)化沼本。
2. 花錢購買外部的軟件或者服務(wù)也是一種行之有效的優(yōu)化方式
- 最“物有所值”的應(yīng)該算是 CDN 了
2. 不花錢
1. 開源
- 指抓“源頭”噩峦,開發(fā)網(wǎng)站服務(wù)器自身的潛力,在現(xiàn)有條件不變的情況下盡量挖掘出更多的服務(wù)能力抽兆。
- 選用高性能的 Web 服務(wù)器识补,最佳選擇當(dāng)然就是 Nginx/OpenResty
- 盡量不要選擇基于 Java、Python辫红、Ruby 的其他服務(wù)器凭涂,它們用來做后面的業(yè)務(wù)邏輯服務(wù)器更好。
- 利用 Nginx 強(qiáng)大的反向代理能力實(shí)現(xiàn)“動(dòng)靜分離”贴妻,動(dòng)態(tài)頁面交給 Tomcat切油、Django、Rails名惩,圖片澎胡、樣式表等靜態(tài)資源交給 Nginx。
- Nginx 或者 OpenResty 自身也有很多配置參數(shù)可以用來進(jìn)一步調(diào)優(yōu)
- 比如說禁用負(fù)載均衡鎖绢片、增大連接池滤馍,綁定 CPU 等等
- 特別要說的是,對(duì)于 HTTP 協(xié)議一定要啟用長(zhǎng)連接
- 在現(xiàn)代操作系統(tǒng)上都已經(jīng)支持 TCP 的新特性“TCP Fast Open”(Win10底循、iOS9、Linux 4.1)槐瑞,它的效果類似 TLS 的“False Start”,可以在初次握手的時(shí)候就傳輸數(shù)據(jù)困檩,也就是 0-RTT祠挫,所以我們應(yīng)該盡可能在操作系統(tǒng)和 Nginx 里開啟這個(gè)特性,減少外網(wǎng)和內(nèi)網(wǎng)里的握手延遲悼沿。
- 個(gè)簡(jiǎn)短的 Nginx 配置示例 , 啟用了長(zhǎng)連接等優(yōu)化參數(shù)等舔,實(shí)現(xiàn)了動(dòng)靜分離
server {
listen 80 deferred reuseport backlog=4096 fastopen=1024;
keepalive_timeout 60;
keepalive_requests 10000;
location ~* \.(png)$ {
root /var/images/png/;
}
location ~* \.(php)$ {
proxy_pass http://php_back_end;
}
}
2. 節(jié)流
- 減少客戶端和服務(wù)器之間收發(fā)的數(shù)據(jù)量,在有限的帶寬里傳輸更多的內(nèi)容糟趾。
2.1 壓縮
-
”最基本的做法就是使用 HTTP 協(xié)議內(nèi)置的“數(shù)據(jù)壓縮”編碼慌植,不僅可以選擇標(biāo)準(zhǔn)的 gzip甚牲,還可以積極嘗試新的壓縮算法 br,它有更好的壓縮效果蝶柿。
- 不過在數(shù)據(jù)壓縮的時(shí)候應(yīng)當(dāng)注意選擇適當(dāng)?shù)膲嚎s率丈钙,不要追求最高壓縮比,否則會(huì)耗費(fèi)服務(wù)器的計(jì)算資源交汤,增加響應(yīng)時(shí)間雏赦,降低服務(wù)能力,反而會(huì)“得不償失”芙扎。
-
有針對(duì)性地采用特殊的壓縮方式星岗。
- HTML/CSS/JavaScript 屬于純文本,就可以采用特殊的“壓縮”戒洼,去掉源碼里多余的空格俏橘、換行、注釋等元素施逾。
- 圖片在 HTTP 傳輸里占有非常高的比例敷矫,雖然它本身已經(jīng)被壓縮過了,不能被 gzip汉额、br 處理曹仗,但仍然有優(yōu)化的空間。
- 去除圖片里的拍攝時(shí)間蠕搜、地點(diǎn)怎茫、機(jī)型等元數(shù)據(jù),適當(dāng)降低分辨率妓灌,縮小尺寸轨蛤。
- 圖片的格式也很關(guān)鍵,盡量選擇高壓縮率的格式虫埂,有損格式應(yīng)該用 JPEG祥山,無損格式應(yīng)該用 Webp 格式。
- 對(duì)于小文本或者小圖片掉伏,還有一種叫做“資源合并”(Concatenation)的優(yōu)化方式
- 把許多小資源合并成一個(gè)大資源缝呕,用一個(gè)請(qǐng)求全下載到客戶端,然后客戶端再用 JavaScript斧散、CSS 切分后使用供常,好處是節(jié)省了請(qǐng)求次數(shù),但缺點(diǎn)是處理比較麻煩鸡捐。
-
在 HTTP/1 里沒有辦法可以壓縮 header栈暇,采取一些手段來減少 header 的大小,不必要的字段就盡量不發(fā)
- 例如 Server箍镜、X-Powered-By
盡可能減少 Cookie 的傳輸源祈。如果客戶端是現(xiàn)代瀏覽器煎源,還可以使用 HTML5 里定義的 Web Local Storage,避免使用 Cookie新博。
2.2 域名
- DNS 解析域名會(huì)耗費(fèi)不少的時(shí)間薪夕,如果網(wǎng)站擁有多個(gè)域名,那么域名解析獲取 IP 地址就是一個(gè)不小的成本赫悄,
- 適當(dāng)“收縮”域名原献,限制在兩三個(gè)左右,減少解析完整域名所需的時(shí)間埂淮,讓客戶端盡快從系統(tǒng)緩存里獲取解析結(jié)果
2.3 重定向
- 重定向引發(fā)的客戶端延遲也很高姑隅,
- 它不僅增加了一次請(qǐng)求往返,還有可能導(dǎo)致新域名的 DNS 解析倔撞,是 HTTP 前端性能優(yōu)化的“大忌”讲仰。除非必要,應(yīng)當(dāng)盡量不使用重定向痪蝇,或者使用 Web 服務(wù)器的“內(nèi)部重定向”鄙陡。
3. 緩存
-
在“中間一公里”,緩存更是性能優(yōu)化的重要手段
- CDN 的網(wǎng)絡(luò)加速功能就是建立在緩存的基礎(chǔ)之上的躏啰,可以這么說趁矾,如果沒有緩存,那就沒有 CDN给僵。
-
利用好緩存功能的關(guān)鍵是理解它的工作原理
- 為每個(gè)資源都添加 ETag 和 Last-modified 字段毫捣,再用 Cache-Control、Expires 設(shè)置好緩存控制屬性帝际。
- 其中最基本的是 max-age 有效期蔓同,標(biāo)記資源可緩存的時(shí)間。對(duì)于圖片蹲诀、CSS 等靜態(tài)資源可以設(shè)置較長(zhǎng)的時(shí)間斑粱,比如一天或者一個(gè)月,對(duì)于動(dòng)態(tài)資源脯爪,除非是實(shí)時(shí)性非常高珊佣,也可以設(shè)置一個(gè)較短的時(shí)間,比如 1 秒或者 5 秒披粟。
- 這樣一旦資源到達(dá)客戶端,就會(huì)被緩存起來冷冗,在有效期內(nèi)都不會(huì)再向服務(wù)器發(fā)送請(qǐng)求守屉,也就是:“沒有請(qǐng)求的請(qǐng)求,才是最快的請(qǐng)求蒿辙∧捶海”
4. 升級(jí)HTTP/2
- 它消除了應(yīng)用層的隊(duì)頭阻塞滨巴,擁有頭部壓縮、二進(jìn)制幀俺叭、多路復(fù)用恭取、流量控制、服務(wù)器推送等許多新特性熄守,大幅度提升了 HTTP 的傳輸效率蜈垮。