nginx在應(yīng)用程序中的作用
nginx現(xiàn)在幾乎是眾多大型網(wǎng)站的必用技術(shù),大多數(shù)情況下,我們不需要親自去配置它,但是了解它在應(yīng)用程序中所擔(dān)任的角色,以及如何解決這些問題是非常必要的。 下面我將從nginx在企業(yè)中的真實(shí)應(yīng)用來解釋nginx在應(yīng)用程序中起到的作用。 為了便于理解,首先先來了解一下一些基礎(chǔ)知識(shí),nginx是一個(gè)高性能的反向代理服務(wù)器那么什么是反向代理呢? 正向代理與反向代理 代理是在服務(wù)器和客戶端之間假設(shè)的一層服務(wù)器,代理將接收客戶端的請(qǐng)求并將它轉(zhuǎn)發(fā)給服務(wù)器,然后將服務(wù)端的響應(yīng)轉(zhuǎn)發(fā)給客戶端。 不管是正向代理還是反向代理,實(shí)現(xiàn)的都是上面的功能。
正向代理是為我們服務(wù)的,即為客戶端服務(wù)的,客戶端可以根據(jù)正向代理訪問到它本身無法訪問到的服務(wù)器資源。 正向代理對(duì)我們是透明的,對(duì)服務(wù)端是非透明的,即服務(wù)端并不知道自己收到的是來自代理的訪問還是來自真實(shí)客戶端的訪問。 反向代理
反向代理是為服務(wù)端服務(wù)的,反向代理可以幫助服務(wù)器接收來自客戶端的請(qǐng)求,幫助服務(wù)器做請(qǐng)求轉(zhuǎn)發(fā),負(fù)載均衡等。 反向代理對(duì)服務(wù)端是透明的,對(duì)我們是非透明的,即我們并不知道自己訪問的是代理服務(wù)器,而服務(wù)器知道反向代理在為他服務(wù)。 基本配置 配置結(jié)構(gòu) 下面是一個(gè)nginx配置文件的基本結(jié)構(gòu): events { }http { server { location path { ... } location path { ... } } server { ... }}
內(nèi)置變量 下面是nginx一些配置中常用的內(nèi)置全局變量,你可以在配置的任何位置使用它們。 變量名 功能 $host 請(qǐng)求信息中的Host,如果請(qǐng)求中沒有Host行,則等于設(shè)置的服務(wù)器名 $request_method 客戶端請(qǐng)求類型,如GET、POST $remote_addr 客戶端的IP地址 $args 請(qǐng)求中的參數(shù) $content_length 請(qǐng)求頭中的Content-length字段 $http_user_agent 客戶端agent信息 $http_cookie 客戶端cookie信息 $remote_port 客戶端的端口 $server_protocol 請(qǐng)求使用的協(xié)議,如HTTP/1.0、·HTTP/1.1` $server_addr 服務(wù)器地址 $server_name 服務(wù)器名稱 $server_port 服務(wù)器的端口號(hào) 解決跨域 先追本溯源以下,跨域究竟是怎么回事。 跨域的定義 同源策略限制了從同一個(gè)源加載的文檔或腳本如何與來自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的重要安全機(jī)制。通常不允許不同源間的讀操作。 同源的定義 如果兩個(gè)頁面的協(xié)議,端口(如果有指定)和域名都相同,則兩個(gè)頁面具有相同的源。 nginx解決跨域的原理 例如:
現(xiàn)在我在fe.server.com對(duì)dev.server.com發(fā)起請(qǐng)求一定會(huì)出現(xiàn)跨域。 現(xiàn)在我們只需要啟動(dòng)一個(gè)nginx服務(wù)器,將server_name設(shè)置為fe.server.com,然后設(shè)置相應(yīng)的location以攔截前端需要跨域的請(qǐng)求,最后將請(qǐng)求代理回dev.server.com。如下面的配置: server { listen 80; server_name fe.server.com; location / { proxy_pass dev.server.com; }} 這樣可以完美繞過瀏覽器的同源策略:fe.server.com訪問nginx的fe.server.com屬于同源訪問,而nginx對(duì)服務(wù)端轉(zhuǎn)發(fā)的請(qǐng)求不會(huì)觸發(fā)瀏覽器的同源策略。 請(qǐng)求過濾 根據(jù)狀態(tài)碼過濾 error_page 500 501 502 503 504 506 /50x.html; location = /50x.html { #將跟路徑改編為存放html的路徑。 root /root/static/html; } 根據(jù)URL名稱過濾,精準(zhǔn)匹配URL,不匹配的URL全部重定向到主頁。 location / { rewrite ^.*$ /index.html redirect;} 根據(jù)請(qǐng)求類型過濾。 if ( $request_method !~ ^(GET|POST|HEAD)$ ) { return 403; } 配置gzip GZIP是規(guī)定的三種標(biāo)準(zhǔn)HTTP壓縮格式之一。目前絕大多數(shù)的網(wǎng)站都在使用GZIP傳輸 HTML、CSS、JavaScript 等資源文件。 對(duì)于文本文件,GZip 的效果非常明顯,開啟后傳輸所需流量大約會(huì)降至 1/4 ~ 1/3。 并不是每個(gè)瀏覽器都支持gzip的,如何知道客戶端是否支持gzip呢,請(qǐng)求頭中的Accept-Encoding來標(biāo)識(shí)對(duì)壓縮的支持。 啟用gzip同時(shí)需要客戶端和服務(wù)端的支持,如果客戶端支持gzip的解析,那么只要服務(wù)端能夠返回gzip的文件就可以啟用gzip了,我們可以通過nginx的配置來讓服務(wù)端支持gzip。下面的respone中content-encoding:gzip,指服務(wù)端開啟了gzip的壓縮方式。 gzip on; gzip_http_version 1.1; gzip_comp_level 5; gzip_min_length 1000; gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml; gzip
gzip_http_version
這里為什么默認(rèn)版本不是1.0呢? HTTP 運(yùn)行在TCP 連接之上,自然也有著跟TCP 一樣的三次握手、慢啟動(dòng)等特性。 啟用持久連接情況下,服務(wù)器發(fā)出響應(yīng)后讓TCP連接繼續(xù)打開著。同一對(duì)客戶/服務(wù)器之間的后續(xù)請(qǐng)求和響應(yīng)可以通過這個(gè)連接發(fā)送。 為了盡可能的提高 HTTP 性能,使用持久連接就顯得尤為重要了。 HTTP/1.1默認(rèn)支持TCP持久連接,HTTP/1.0 也可以通過顯式指定 Connection: keep-alive 來啟用持久連接。對(duì)于TCP持久連接上的HTTP 報(bào)文,客戶端需要一種機(jī)制來準(zhǔn)確判斷結(jié)束位置,而在 HTTP/1.0中,這種機(jī)制只有Content-Length。而在HTTP/1.1中新增的 Transfer-Encoding: chunked 所對(duì)應(yīng)的分塊傳輸機(jī)制可以完美解決這類問題。 nginx同樣有著配置chunked的屬性chunked_transfer_encoding,這個(gè)屬性是默認(rèn)開啟的。 Nginx在啟用了GZip的情況下,不會(huì)等文件 GZip 完成再返回響應(yīng),而是邊壓縮邊響應(yīng),這樣可以顯著提高 TTFB(Time To First Byte,首字節(jié)時(shí)間,WEB 性能優(yōu)化重要指標(biāo))。這樣唯一的問題是,Nginx 開始返回響應(yīng)時(shí),它無法知道將要傳輸?shù)奈募罱K有多大,也就是無法給出Content-Length這個(gè)響應(yīng)頭部。 所以,在HTTP1.0中如果利用Nginx啟用了GZip,是無法獲得Content-Length的,這導(dǎo)致HTTP1.0中開啟持久鏈接和使用GZip只能二選一,所以在這里gzip_http_version默認(rèn)設(shè)置為1.1。 gzip_comp_level
gzip_min_length
gzip_types
負(fù)載均衡 什么是負(fù)載均衡 如上面的圖,前面是眾多的服務(wù)窗口,下面有很多用戶需要服務(wù),我們需要一個(gè)工具或策略來幫助我們將如此多的用戶分配到每個(gè)窗口,來達(dá)到資源的充分利用以及更少的排隊(duì)時(shí)間。 把前面的服務(wù)窗口想像成我們的后端服務(wù)器,而后面終端的人則是無數(shù)個(gè)客戶端正在發(fā)起請(qǐng)求。負(fù)載均衡就是用來幫助我們將眾多的客戶端請(qǐng)求合理的分配到各個(gè)服務(wù)器,以達(dá)到服務(wù)端資源的充分利用和更少的請(qǐng)求時(shí)間。 nginx如何實(shí)現(xiàn)負(fù)載均衡 Upstream指定后端服務(wù)器地址列表 upstream balanceServer { server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; } 在server中攔截響應(yīng)請(qǐng)求,并將請(qǐng)求轉(zhuǎn)發(fā)到Upstream中配置的服務(wù)器列表。 server { server_name fe.server.com; listen 80; location /api { proxy_pass http://balanceServer; } } 上面的配置只是指定了nginx需要轉(zhuǎn)發(fā)的服務(wù)端列表,并沒有指定分配策略。 nginx實(shí)現(xiàn)負(fù)載均衡的策略 輪詢策略 默認(rèn)情況下采用的策略,將所有客戶端請(qǐng)求輪詢分配給服務(wù)端。這種策略是可以正常工作的,但是如果其中某一臺(tái)服務(wù)器壓力太大,出現(xiàn)延遲,會(huì)影響所有分配在這臺(tái)服務(wù)器下的用戶。 upstream balanceServer { server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345;} ![]() 最小連接數(shù)策略 將請(qǐng)求優(yōu)先分配給壓力較小的服務(wù)器,它可以平衡每個(gè)隊(duì)列的長度,并避免向壓力大的服務(wù)器添加更多的請(qǐng)求。 upstream balanceServer { least_conn; server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345;} ![]() 最快響應(yīng)時(shí)間策略 依賴于NGINX Plus,優(yōu)先分配給響應(yīng)時(shí)間最短的服務(wù)器。 upstream balanceServer { fair; server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345;} 客戶端ip綁定 來自同一個(gè)ip的請(qǐng)求永遠(yuǎn)只分配一臺(tái)服務(wù)器,有效解決了動(dòng)態(tài)網(wǎng)頁存在的session共享問題。 upstream balanceServer { ip_hash; server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345;} 靜態(tài)資源服務(wù)器 location ~* \.(png|gif|jpg|jpeg)$ { root /root/static/; autoindex on; access_log off; expires 10h;# 設(shè)置過期時(shí)間為10小時(shí) } 匹配以png|gif|jpg|jpeg為結(jié)尾的請(qǐng)求,并將請(qǐng)求轉(zhuǎn)發(fā)到本地路徑,root中指定的路徑即nginx本地路徑。同時(shí)也可以進(jìn)行一些緩存的設(shè)置。 |
|