天天看點

前端開發者必備的Nginx知識

解決跨域

請求過濾

配置gzip

負載均衡

靜态資源伺服器

nginx是一個高性能的HTTP和反向代理伺服器,也是一個通用的TCP/UDP代理伺服器,最初由俄羅斯人Igor Sysoev編寫。

nginx現在幾乎是衆多大型網站的必用技術,大多數情況下,我們不需要親自去配置它,但是了解它在應用程式中所擔任的角色,以及如何解決這些問題是非常必要的。

下面我将從nginx在企業中的真實應用來解釋nginx在應用程式中起到的作用。

為了便于了解,首先先來了解一下一些基礎知識,<code>nginx是一個高性能的反向代理伺服器</code>那麼什麼是反向代理呢?

代理是在伺服器和用戶端之間假設的一層伺服器,代理将接收用戶端的請求并将它轉發給伺服器,然後将服務端的響應轉發給用戶端。

不管是正向代理還是反向代理,實作的都是上面的功能。

正向代理

正向代理,意思是一個位于用戶端和原始伺服器(origin server)之間的伺服器,為了從原始伺服器取得内容,用戶端向代理發送一個請求并指定目标(原始伺服器),然後代理向原始伺服器轉交請求并将獲得的内容傳回給用戶端。

正向代理是為我們服務的,即為用戶端服務的,用戶端可以根據正向代理通路到它本身無法通路到的伺服器資源。

正向代理對我們是透明的,對服務端是非透明的,即服務端并不知道自己收到的是來自代理的通路還是來自真實用戶端的通路。

反向代理

反向代理(Reverse Proxy)方式是指以代理伺服器來接受internet上的連接配接請求,然後将請求轉發給内部網絡上的伺服器,并将從伺服器上得到的結果傳回給internet上請求連接配接的用戶端,此時代理伺服器對外就表現為一個反向代理伺服器。

反向代理是為服務端服務的,反向代理可以幫助伺服器接收來自用戶端的請求,幫助伺服器做請求轉發,負載均衡等。

反向代理對服務端是透明的,對我們是非透明的,即我們并不知道自己通路的是代理伺服器,而伺服器知道反向代理在為他服務。

配置結構

下面是一個nginx配置檔案的基本結構:

<code>main</code>:nginx的全局配置,對全局生效。

<code>events</code>:配置影響nginx伺服器或與使用者的網絡連接配接。

<code>http</code>:可以嵌套多個server,配置代理,緩存,日志定義等絕大多數功能和第三方子產品的配置。

<code>server</code>:配置虛拟主機的相關參數,一個http中可以有多個server。

<code>location</code>:配置請求的路由,以及各種頁面的處理情況。

<code>upstream</code>:配置後端伺服器具體位址,負載均衡配置不可或缺的部分。

内置變量

下面是<code>nginx</code>一些配置中常用的内置全局變量,你可以在配置的任何位置使用它們。

| 變量名 | 功能 | 

| ------ | ------ | 

| <code>$host</code>| 請求資訊中的<code>Host</code>,如果請求中沒有<code>Host</code>行,則等于設定的伺服器名 |

| <code>$request_method</code> | 用戶端請求類型,如<code>GET</code>、<code>POST</code>

| <code>$remote_addr</code> | 用戶端的<code>IP</code>位址 |

|<code>$args</code> | 請求中的參數 |

|<code>$content_length</code>| 請求頭中的<code>Content-length</code>字段 |

|<code>$http_user_agent</code> | 用戶端agent資訊 |

|<code>$http_cookie</code> | 用戶端cookie資訊 |

|<code>$remote_addr</code> | 用戶端的IP位址 |

|<code>$remote_port</code> | 用戶端的端口 |

|<code>$server_protocol</code> | 請求使用的協定,如<code>HTTP/1.0</code>、·HTTP/1.1` |

|<code>$server_addr</code> | 伺服器位址 |

|<code>$server_name</code>| 伺服器名稱|

|<code>$server_port</code>|伺服器的端口号|

先追本溯源以下,跨域究竟是怎麼回事。

跨域的定義

同源政策限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行互動。這是一個用于隔離潛在惡意檔案的重要安全機制。通常不允許不同源間的讀操作。

同源的定義

如果兩個頁面的協定,端口(如果有指定)和域名都相同,則兩個頁面具有相同的源。

nginx解決跨域的原理

例如:

前端server的域名為:<code>fe.server.com</code>

後端服務的域名為:<code>dev.server.com</code>

現在我在<code>fe.server.com</code>對<code>dev.server.com</code>發起請求一定會出現跨域。

現在我們隻需要啟動一個nginx伺服器,将<code>server_name</code>設定為<code>fe.server.com</code>,然後設定相應的location以攔截前端需要跨域的請求,最後将請求代理回<code>dev.server.com</code>。如下面的配置:

這樣可以完美繞過浏覽器的同源政策:<code>fe.server.com</code>通路<code>nginx</code>的<code>fe.server.com</code>屬于同源通路,而<code>nginx</code>對服務端轉發的請求不會觸發浏覽器的同源政策。

根據狀态碼過濾

根據URL名稱過濾,精準比對URL,不比對的URL全部重定向到首頁。

根據請求類型過濾。

<code>GZIP</code>是規定的三種标準HTTP壓縮格式之一。目前絕大多數的網站都在使用<code> GZIP </code>傳輸 <code>HTML</code>、<code>CSS</code>、<code>JavaScript</code> 等資源檔案。

對于文本檔案,<code>GZip</code> 的效果非常明顯,開啟後傳輸所需流量大約會降至 <code>1/4 ~ 1/3</code>。

并不是每個浏覽器都支援<code>gzip</code>的,如何知道用戶端是否支援<code>gzip</code>呢,請求頭中的<code>Accept-Encoding</code>來辨別對壓縮的支援。

啟用<code>gzip</code>同時需要用戶端和服務端的支援,如果用戶端支援<code>gzip</code>的解析,那麼隻要服務端能夠傳回<code>gzip</code>的檔案就可以啟用<code>gzip</code>了,我們可以通過<code>nginx</code>的配置來讓服務端支援<code>gzip</code>。下面的<code>respone</code>中<code>content-encoding:gzip</code>,指服務端開啟了<code>gzip</code>的壓縮方式。

gzip

開啟或者關閉<code>gzip</code>子產品

預設值為<code> off</code>

可配置為<code> on / off</code>

gzip_http_version

啟用 <code>GZip</code> 所需的<code> HTTP</code> 最低版本

預設值為<code> HTTP/1.1</code>

這裡為什麼預設版本不是<code>1.0</code>呢?

<code>HTTP</code> 運作在<code> TCP</code> 連接配接之上,自然也有着跟<code> TCP</code> 一樣的三次握手、慢啟動等特性。

啟用持久連接配接情況下,伺服器發出響應後讓<code>TCP</code>連接配接繼續打開着。同一對客戶/伺服器之間的後續請求和響應可以通過這個連接配接發送。

為了盡可能的提高 <code>HTTP</code> 性能,使用持久連接配接就顯得尤為重要了。

<code>HTTP/1.1 </code>預設支援<code> TCP </code>持久連接配接,<code>HTTP/1.0</code> 也可以通過顯式指定 <code>Connection: keep-alive</code> 來啟用持久連接配接。對于<code> TCP </code>持久連接配接上的<code> HTTP</code> 封包,用戶端需要一種機制來準确判斷結束位置,而在 <code>HTTP/1.0 </code>中,這種機制隻有<code>Content-Length</code>。而在<code>HTTP/1.1 </code>中新增的 <code>Transfer-Encoding: chunked</code> 所對應的分塊傳輸機制可以完美解決這類問題。

<code>nginx</code>同樣有着配置<code>chunked的</code>屬性<code>chunked_transfer_encoding</code>,這個屬性是預設開啟的。

<code>Nginx </code>在啟用了<code>GZip</code>的情況下,不會等檔案 <code>GZip</code> 完成再傳回響應,而是邊壓縮邊響應,這樣可以顯著提高 <code>TTFB</code>(<code>Time To First Byte</code>,首位元組時間,WEB 性能優化重要名額)。這樣唯一的問題是,<code>Nginx</code> 開始傳回響應時,它無法知道将要傳輸的檔案最終有多大,也就是無法給出<code> Content-Length </code>這個響應頭部。

是以,在<code>HTTP1.0</code>中如果利用<code>Nginx </code>啟用了<code>GZip</code>,是無法獲得<code> Content-Length </code>的,這導緻HTTP1.0中開啟持久連結和使用<code>GZip</code>隻能二選一,是以在這裡<code>gzip_http_version</code>預設設定為<code>1.1</code>。

gzip_comp_level

壓縮級别,級别越高壓縮率越大,當然壓縮時間也就越長(傳輸快但比較消耗cpu)。

預設值為 <code>1</code>

壓縮級别取值為<code>1-9</code>

gzip_min_length

設定允許壓縮的頁面最小位元組數,<code>Content-Length</code>小于該值的請求将不會被壓縮

預設值:<code>0</code>

當設定的值較小時,壓縮後的長度可能比原檔案大,建議設定<code>1000</code>以上

gzip_types

要采用gzip壓縮的檔案類型(<code>MIME</code>類型)

預設值:<code>text/html</code>(預設不壓縮<code>js</code>/<code>css</code>)

什麼是負載均衡

如上面的圖,前面是衆多的服務視窗,下面有很多使用者需要服務,我們需要一個工具或政策來幫助我們将如此多的使用者配置設定到每個視窗,來達到資源的充分利用以及更少的排隊時間。

把前面的服務視窗想像成我們的後端伺服器,而後面終端的人則是無數個用戶端正在發起請求。負載均衡就是用來幫助我們将衆多的用戶端請求合理的配置設定到各個伺服器,以達到服務端資源的充分利用和更少的請求時間。

nginx如何實作負載均衡

Upstream指定後端伺服器位址清單

在server中攔截響應請求,并将請求轉發到Upstream中配置的伺服器清單。

上面的配置隻是指定了nginx需要轉發的服務端清單,并沒有指定配置設定政策。

nginx實作負載均衡的政策

輪詢政策

預設情況下采用的政策,将所有用戶端請求輪詢配置設定給服務端。這種政策是可以正常工作的,但是如果其中某一台伺服器壓力太大,出現延遲,會影響所有配置設定在這台伺服器下的使用者。

最小連接配接數政策

将請求優先配置設定給壓力較小的伺服器,它可以平衡每個隊列的長度,并避免向壓力大的伺服器添加更多的請求。

最快響應時間政策

依賴于NGINX Plus,優先配置設定給響應時間最短的伺服器。

用戶端ip綁定

來自同一個ip的請求永遠隻配置設定一台伺服器,有效解決了動态網頁存在的session共享問題。

比對以<code>png|gif|jpg|jpeg</code>為結尾的請求,并将請求轉發到本地路徑,<code>root</code>中指定的路徑即nginx本地路徑。同時也可以進行一些緩存的設定。

nginx的功能非常強大,還有很多需要探索,上面的一些配置都是公司配置的真實應用(精簡過了),如果您有什麼意見或者建議,歡迎在下方留言...

繼續閱讀