爲什麼要使用HTTP2
原因就是慢
影響一個網絡請求的因素主要有兩個,帶寬和延遲。今天的網絡基礎建設已經使得帶寬得到極大的提升,大部分時候都是延遲在影響。
**爲什麼延遲??**
- 瀏覽器阻塞(HOL blocking):瀏覽器會因爲一些原因阻塞請求。瀏覽器對於同一個域名,同時只能有 4
個連接(這個根據瀏覽器內核不同可能會有所差異),超過瀏覽器最大連接數限制,後續請求就會被阻塞。 - DNS 查詢(DNS Lookup):瀏覽器需要知道目標服務器的 IP 才能建立連接。將域名解析爲 IP的這個系統就是 DNS。這個通常可以利用DNS緩存結果來達到減少這個時間的目的。
- 建立連接(Initial connection):HTTP 是基於 TCP 協議的,瀏覽器最快也要在第三次握手時才能捎帶 HTTP 請求報文,達到真正的建立連接,但是這些連接無法複用會導致每次請求都經歷三次握手和慢啓動。三次握手在高延遲的場景下影響較明顯,慢啓動則對文件類大請求影響較大。
- 連接無法複用。每回請求個資源就會有一個請求連接跟斷開連接操作,大量請求不斷的請求連接跟斷開連接時間開銷大。
如何高響應速度?pipelining的出現
前文介紹,HTTP 連接無法複用會導致每次請求都經歷三次握手和慢啓動。由圖可知pipelining可有效減少握手時間。
不過pipelining並不是救世主,它也存在不少缺陷:
- pipelining只能適用於http1.1,一般來說,支持http1.1的server都要求支持pipelining
- 只有冪等的請求(GET,HEAD)能使用pipelining,非冪等請求比如POST不能使用,因爲請求之間可能會存在先後依賴關係。
- head of line blocking並沒有完全得到解決,server的response還是要求依次返回,遵循FIFO(first in first out)原則。也就是說如果請求1的response沒有回來,2,3,4,5的response也不會被送回來。
- 絕大部分的http代理服務器不支持pipelining。
- 和不支持pipelining的老服務器協商有問題。
- 可能會導致新的Front of queue blocking問題。
普通的 HTTPS 網站瀏覽會比 HTTP 網站稍微慢一些,因爲需要處理加密任務。
HTTP2 VS HTTP1.1
- 多路複用。
多路複用通過多個請求stream共享一個tcp連接的方式(即所有的HTTP2.0的請求都在一個TCP鏈接上),解決了http1.x holb(head of line blocking)的問題,降低了延遲同時提高了帶寬的利用率。 - 壓縮頭部。
HTTP/2.0規定了在客戶端和服務器端會使用並且維護「首部表」來跟蹤和存儲之前發送的鍵值對,對於相同的頭部,不必再通過請求發送,只需發送一次。
如果首部發生變化了,那麼只需要發送變化了數據在Headers幀裏面,新增或修改的首部幀會被追加到“首部表”。首部表在 HTTP2.0的連接存續期內始終存在,由客戶端和服務器共同漸進地更新。
由於減少了大量請求頭數據的傳輸,緩解了網絡壓力,也提高了響應速度。 - 二進制分幀
在應用層與傳輸層之間增加一個二進制分幀層,以此達到“在不改動HTTP的語義,HTTP 方法、狀態碼、URI及首部字段的情況下,突破HTTP1.1的性能限制,改進傳輸性能,實現低延遲和高吞吐量。”
在二進制分幀層上,HTTP2.0會將所有傳輸的信息分割爲更小的消息和幀,並對它們採用二進制格式的編碼,其中HTTP1.x的首部信息會被封裝到Headers幀,而我們的request body則封裝到Data幀裏面。 - 並行雙向字節流的請求和響應
在HTTP2.0上,客戶端和服務器可以把HTTP消息分解爲互不依賴的幀,然後亂序發送,最後再在另一端把它們重新組合起來。注意,同一鏈接上有多個不同方向的數據流在傳輸。客戶端可以一邊亂序發送stream,也可以一邊接收服務器的響應,而服務器那端同理。 - 請求優先級
多路複用導致所有資源都是並行發送,那麼就需要「優先級」的概念了,這樣就可以對重要的文件進行先傳輸,加速頁面的渲染。 - 服務器推送
服務器推送是指在客戶端請求之前發送數據的機制。(根據請求資源猜測你可能還需要某某資源,提前推送資源緩存提高響應效率)
nginx升級HTTP2
1、升級準備
1、安裝編譯器
yum -y install gc gcc gcc-c++ pcre* perl*
2、下載安裝包
cd /usr/local
wget http://nginx.org/download/nginx-1.12.2.tar.gz
wget https://www.openssl.org/source/openssl-1.0.2e.tar.gz
wget http://zlib.net/zlib-1.2.11.tar.gz
3、解壓安裝包
tar -zxvf nginx-1.12.2.tar.gz
tar -zxvf openssl-1.0.2e.tar.gz
tar -zxvf zlib-1.2.11.tar.gz
2、安裝zlib
*1、cd zlib 2、./configure 3、make 4、make install
3、安裝openssl
1、cd openssl
2、安裝
./config shared zlib make make install cd /usr/local/ssl/ ./bin/openssl version -a
3、替換舊版OpenSSL
mv /usr/bin/openssl /usr/bin/openssl.old mv /usr/include/openssl /usr/include/openssl.old ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl ln -s /usr/local/ssl/include/openssl/ /usr/include/openssl
4、配置庫文件搜索路徑
echo "/usr/local/ssl/lib" >> /etc/ld.so.conf ldconfig
5、測試新版本的OpenSSL是否正常工作
openssl version -a
4、安裝nginx
1、查看ngixn版本及其編譯參數,複製你已經編譯安裝好的模塊。
nginx -V
2、進入nginx源碼目錄
cd nginx 執行(在原有的參數上加上--with-zlib=/usr/local/zlib-1.2.11 --with-openssl=/usr/local/openssl-1.0.2e重編譯,如下例:) ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-zlib=/usr/local/zlib-1.2.11 --with-openssl=/usr/local/openssl-1.0.2e --with-pcre
3、然後
make //千萬別make install,否則就覆蓋安裝了 make完之後在objs目錄下就多了個nginx,這個就是新版本的程序了
4、驗證新nginx是否可用驗證編譯後的nginx是否可以使用已有的配置
./objs/nginx -t
5、備份舊的nginx:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
6、把新的nginx程序覆蓋舊的:
cp ./objs/nginx /usr/sbin/nginx
7、測試新的nginx程序是否正確
nginx -t
8、修改Nginx的 .conf 文件
在監聽443的後面加上http2,如下: ``` server { listen 443 ssl http2 default_server; server_name www.jiezaizone.cn; ssl on; ssl_certificate /etc/nginx/1_jiezaizone.cn_bundle.crt; ssl_certificate_key /etc/nginx/2_jiezaizone.cn.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { root /; index index.html index.htm; } } ``` 注:某些服務開啓http2後不能訪問,在http2 後面加上 default_server 就可以了
9、重新加載nginx
nginx -s reload
安裝異常及其解決方法
異常1:
/usr/bin/ld: /usr/local/lib/libz.a(crc32.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC/usr/local/lib/libz.a: could not read symbols: Bad value
處理方法:
cd zlib-1.2.3 //進入zlib目錄CFLAGS="-O3 -fPIC" ./configure //使用64位元的方法進行編譯
make
異常2:
/usr/bin/ld: /etc/nginx/openssl-1.0.2e/.openssl/lib/libssl.a(s23_meth.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
解決方法:
cd openssl
./config -fPIC --prefix=/usr/local/openssl/ enable-shared
make
測試環境運營系統已經全面支持https
1、倉庫已經push了nginx1.11.1,直接支持http2,可通過下述命令直接拉取下拉使用
docker pull docker.oa.isuwang.com:5000/system/nginx:1.11.1
2、在我們的nginx項目http2分支,已經寫好了構建支持http2的nginx dockerdile,可直接下載下拉查看。
http://git.oa.isuwang.com/isuwang-docker/nginx.git
提問:
1. HTTPS有併發嗎,如何實現的?一個連接怎麼實現併發呢
2. http2的長連接是怎麼回事
答:
1. http2有併發。它支持多路複用,並行雙向字節流的請求和響應,它以“流”的形式在客戶端和服務器間獨立的雙向的交換的幀序列。流具有一些重要的特性:
- 單個的HTTP/2連接可以包含多個併發打開的流,各個終端多個流的幀可以交叉。
- 流可以單方面地建立和使用,或由客戶端或服務器共享。
- 流可以被任何一端關閉。
- 流中幀的發送順序是值得注意的。接收者以它們收到幀的順序處理。特別的,HEADERS幀和DATA幀在語義上是非常重要的。
- 流由一個整數標識。流標識符由發起流的一端來賦值。
雖然只有一個TCP連接,卻能夠在這個連接同時處理客戶端和服務端的多個數據傳輸。
2. HTTP2只有一個TCP連接,它並不像http1.1中的TCP連接一樣,在處理當前傳輸數據後就關閉,而是一直連通的,客戶端和服務端可以通過它持續往返傳輸數據。這個TCP流的傳輸通道,是可以被任何一端給關閉的。
作者:劉榮傑