2021-03-04

為什么nginx轉發后端默認使用1.0而不是1.1

在 Nginx 的官網文檔中,有這樣一個指令:

Syntax: gzip_http_version 1.0 | 1.1;
Default: gzip_http_version 1.1;
Context: http, server, location
Sets the minimum HTTP version of a request required to compress a response.

很明顯,這個指令是用來設置 Nginx 啟用 GZip 所需的 HTTP 最低版本,默認是 HTTP/1.1。

也就是說 Nginx 默認不壓縮 HTTP/1.0 是因為這個指令,將它的值改為?1.0?就能解決問題。

對于文本文件,GZip 的效果非常明顯,開啟后傳輸所需流量大約會降至 1/4 ~ 1/3。這么好的事情,Nginx 改一下配置就可以支持,為什么它默認不開啟?

Nginx 對于滿足條件(請求頭中有 Accept-Encoding: gzip,響應內容的 Content-Type 存在于 gzip_types 列表)的請求會采用即時壓縮(On-The-Fly Compression),整個壓縮過程在內存中流式完成。也就是說,Nginx 不會等文件 GZip 完成再返回響應,而是邊壓縮邊響應,這樣可以顯著提高 TTFB(Time To First Byte,首字節時間,WEB 性能優化重要指標)。這樣唯一的問題是,Nginx 開始返回響應時,它無法知道將要傳輸的文件最終有多大,也就是無法給出?Content-Length?這個響應頭部。

我們還知道,HTTP/1.1 默認支持 TCP 持久連接(Persistent Connection),HTTP/1.0 也可以通過顯式指定?Connection: keep-alive?來啟用持久連接。HTTP 運行在 TCP 連接之上,自然也有著跟 TCP 一樣的三次握手、慢啟動等特性,要想提高 HTTP 性能,啟用持久連接就顯得尤為重要。

明白以上兩點,馬上就能水落石出了:對于 TCP 持久連接上的 HTTP 報文,客戶端需要一種機制來準確判斷結束位置。而在 HTTP/1.0 中,這種機制只有?Content-Length。于是,對于本文前面提出的情況,HTTP Server 只能要么不壓縮,要么不啟用持久連接(對于非持久連接,TCP 斷開就可以認為 HTTP 報文結束),而 Nginx 默認選擇的是前者。

?

不啟用 Nginx 的 HTTP/1.0 GZip 功能,使用 HTTP/1.0 請求報文測試:

請求報文中指明了可以接受 GZip,但是返回的內容依然是未壓縮的;

同時服務端響應了?Content-Length?和?Connection: keep-alive,連接并沒有斷開。

也就是說對于 HTTP/1.0 請求,Nginx 為了盡可能啟用持久連接,放棄了 GZip,這是 Nginx 的默認策略。

?

啟用 Nginx 的 HTTP/1.0 GZip 功能,使用 HTTP/1.0 請求報文測試:

?

返回的內容被壓縮了,連接也被斷開了,服務端返回了?Connection: close。原因就是之前說過的,動態壓縮導致無法事先得知響應內容長度,在 HTTP/1.0 中只能依靠斷開連接來讓客戶端知道響應結束了。

?

使用 HTTP/1.1 請求報文測試:

請求報文是 HTTP/1.1 的,Nginx 能知道這個客戶端支持 HTTP/1.1 的?Transfer-Encoding: chunked,于是通過分塊傳輸解決了所有問題:既啟用了壓縮,也啟用了持久連接。

那么,對于 HTTP/1.0 請求,我們是讓 Nginx 放棄持久連接好,還是放棄 GZip 好呢?

實際上,由于 HTML 文檔或 JSON 接口一般都是用 PHP、Node.js 等服務端語言動態輸出,即使不壓縮,Nginx 也無法事先得知它的?Content-Length,在 HTTP/1.0 中無論如何都無法啟用持久連接,這時還不如啟用 GZip 省點流量。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383189.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383189.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383189.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

字符串題目---2判斷兩個字符串是否為變形詞

題目描述 給定兩個字符串str1和str2,如果str1和str2中出現的字符種類出現的一樣且每種字符出現的次數也一樣,那么str1和str2互為變形詞。請判斷str1和str2是否為變形詞 輸入描述: 輸入包括3行,第一行包含兩個整數n,m(1 \leq n,…

設計模式7----代理模式

代理模式 概念 Proxy 模式又叫做代理模式,是結構型的設計模式之一,它可以為其他對象提供一 種代理(Proxy)以控制對這個對象的訪問。 所謂代理,是指具有與代理元(被代理的對象)具有相同的接口的…

網絡基礎3-1(細談IP協議頭, 網絡層,子網劃分,路由選擇,數據鏈路層,以太網幀格式,MAC地址,再談ARP協議)

IP協議 IP協議頭格式 4位版本號(version): 指定IP協議的版本, 對于IPv4來說, 就是44位頭部長度(header length): IP頭部的長度是多少個。32bit, 也就是 length * 4 的字節數. 4bit表示大 的數字是15, 因此IP頭部大長度是60字節8位服務類型(Type Of Service): 3位優先權字段(已…

c++常見并且必須記住的問題

一、基礎知識 基本語言 1、說一下static關鍵字的作用 ?2、說一下C和C的區別 3、說一說c中四種cast轉換 4、請說一下C/C 中指針和引用的區別? 5、給定三角形ABC和一點P(x,y,z),判斷點P是否在ABC內,給出思路并手寫代碼 6、怎么判斷一個…

網絡中典型協議--(DNS,輸入url后, 發生的事情. ,ICMP,NAT)

DNS(Domain Name System) DNS是一整套從域名映射到IP的系統 域名服務器發展背景 TCP/IP中使用IP地址和端口號來確定網絡上的一臺主機的一個程序. 但是IP地址不方便記憶. 于是人們發明了一種叫主機名的東西, 是一個字符串, 并且使用hosts文件來描述主機…

高級IO--1 ---(五種典型IO,阻塞IO,非阻塞IO,信號驅動IO,異步IO, IO多路轉接)

高級IO: 五種典型IO: 阻塞IO/非阻塞IO/信號驅動IO/異步IO/IO多路轉接 IO多路轉接模型:select/poll/epoll 五種典型IO 阻塞IO IO操作的流程:等待IO操作條件具備,然后進行數據拷貝 為了完成IO操作發起調用&#xff…

IO多路轉接模型----(select的模型,select的優缺點,poll的模型,poll的優缺點)

IO多路轉接模型:select/poll/epoll 對大量描述符進行事件監控(可讀/可寫/異常) select模型 用戶定義描述符的事件監控集合 fd_set(這是一個位圖,用于存儲要監控的描述符); 用戶將需要監控的描述符添加到集合中,這個描…

IO多路轉接模型-----epoll

epoll: Linux下性能最高的多路轉接模型 epoll 有3個相關的系統調用. epoll_create 功能:創建epoll,在內核中創建eventpoll結構體,size決定了epoll最多監控多少個描述符,在Linux2.6.8之后被忽略,但是必須…

再寫順序表(c語言實現,外加冒泡排序,二分查找)

概念 順序表是用一段物理地址連續的存儲單元依次存儲數據元素的線性結構,一般情況下采用數組存儲。在數組 上完成數據的增刪查改。 順序表一般可以分為: 靜態順序表:使用定長數組存儲。動態順序表:使用動態開辟的數組存儲。 頭…

再寫單鏈表(不帶頭單鏈表)

單鏈表 實際中鏈表的結構非常多樣,以下情況組合起來就有8種鏈表結構: 單向、雙向帶頭、不帶頭循環、非循環 雖然有這么多的鏈表的結構,但是我們實際中最常用還是兩種結構: 無頭單向非循環鏈表:結構簡單&#xff0…

再寫雙向循環鏈表

#pragma once #include<assert.h> #include<malloc.h> #include<stdio.h> typedef int DLDataType;//定義鏈表結點結構 typedef struct DListNode{DLDataType value;struct DListNode *prev; //指向前一個結點struct DListNode *next; //指向后一個結點 } DL…

鏈表題目--1 刪除鏈表中所有等于val的值

注意事項 要刪除的結點相鄰第一個結點就是要刪除的結點 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* removeElements(struct ListNode* head, int val){if(headNULL){return NULL;}struct …

鏈表題目--2 求鏈表的中間結點 和 求鏈表中倒數第k個結點

求鏈表的中間結點 思路 一個走兩步&#xff0c;一個走一步。一個走到尾&#xff0c;另外一個就走到了中間 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* middleNode(struct ListNode* head…

鏈表題目---3 合并兩個有序單鏈表 和 分割鏈表

合并兩個有序單鏈表 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){if(l1 NULL){return l2;}else if(l2 NULL){return l1;}struc…

鏈表題目---4 刪除鏈表中重復的結點 和 判斷鏈表是否為回文鏈表

刪除鏈表中重復的結點 /* struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {} }; */ class Solution { public:ListNode* deleteDuplication(ListNode* pHead){if(pHead NULL){return NULL;}ListNode *prev NULL; //用于刪除的結點, 是…

鏈表題目----5 相交鏈表 和 環形鏈表 和 返回鏈表開始入環的第一個節點

相交鏈表 思路 鏈表交叉不可能是x型因為有可能兩個鏈表不等長&#xff0c;所以我們必須讓他們從同一起跑位置去起跑從同一起跑位置出發&#xff0c;依次比較每個結點的地址是否相同 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct L…

鏈表題目---6 復制帶隨機指針的鏈表

思路 將新結點放在老結點的后面 復制random 將鏈表拆開 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node() {}Node(int _val, Node* _next, Node* _random) {val _val;next _next;random _random;} }; */ class Solution { publi…

括號匹配問題(c和c++版本實現)

括號匹配問題 思路 遇見左括號入棧&#xff0c;遇見一個右括號彈出棧頂元素右括號入棧前如果棧已經為空&#xff0c;則不匹配如果不為空則讀取并彈出&#xff0c;彈出來的元素與右括號做比較&#xff0c;必須匹配&#xff0c;不匹配返回false;如果最后棧里還有元素&#xff0c…

用隊列實現棧 AND 用棧實現隊列

用隊列實現棧 思路 入隊列就是入棧出隊列的時候&#xff0c;就是把前面size-1個隊列中的元素先出&#xff0c;這樣最后一個元素就成隊首元素了&#xff0c;再把出去的元素再次入隊列讀棧頂元素&#xff0c;過程和第二步是一樣的&#xff0c;就是彈出后&#xff0c;再把它入隊列…

最小棧的實現(設計一個支持 push,pop,top 操作,并能在常數時間內檢索到最小元素的棧。)

最小棧的實現 思路 兩個棧&#xff0c;左邊棧接受元素&#xff0c;右邊棧存最小的元素入棧時&#xff0c;先入左邊棧&#xff0c;隨后進行比較&#xff0c;左邊和右邊棧頂元素進行比較&#xff0c;如果新元素小&#xff0c;就把新元素放在右邊的棧頂位置&#xff0c;如果新元素…