Nginx簡介
Nginx (發音為“Engine-x”)是一種開源軟件,最初被設計為高性能Web服務器。今天,Nginx可以完成其他一些任務,包括緩存服務器,反向代理服務器,負載平衡器等等。
WEB服務器
目前主流使用的web服務器軟件,主要有Apache、nginx、Tomcat、iis等,在全球范圍內來說,Apache是現有的最流行的Web服務器,但是在高流量網站中最流行的Web服務器確實nginx,在我國不管是大中小互聯網公司,主流選擇的也是nginx作為web服務器軟件。一份來?.NETcraft的調查中,發現Apache的使用率為31.54%,Nginx的使用率為26.20%。
HTTP代理服務器
HTTP代理,分兩類:一種的正向代理,一種是反向代理。
正向代理
正向代理(Forward Proxy)最大的特點是,客戶端非常明確要訪問的服務器地址,它代理客戶端,替客戶端發出請求。
假設客戶端想要訪問 google,它明確知道待訪問的服務器地址是 https://www.google.com/,但由于條件限制,它找來了一個能夠訪問到 Google 的”朋友”:代理服務器。客戶端把請求發給代理服務器,由代理服務器代替它請求 Google,最終再將響應返回給客戶端。這便是一次正向代理的過程,該過程中服務器并不知道真正發出請求的是誰。
反向代理
那么,隨著請求量的爆發式增長,服務器覺得自己一個人始終是應付不過來,需要兄弟服務器們幫忙,于是它喊來了自己的兄弟以及代理服務器朋友。此時,來自不同客戶端的所有請求實際上都發到了代理服務器處,再由代理服務器按照一定的規則將請求分發給各個服務器。
這就是反向代理(Reverse Proxy),反向代理隱藏了服務器的信息,它代理的是服務器端,代其接收請求。換句話說,反向代理的過程中,客戶端并不知道具體是哪臺服務器處理了自己的請求。如此一來,既提高了訪問速度,又為安全性提供了保證。
在這之中,反向代理需要考慮的問題是,如何進行均衡分工,控制流量,避免出現局部節點負載過大的問題。通俗的講,就是如何為每臺服務器合理的分配請求,使其整體具有更高的工作效率和資源利用率。
基于nginx的反向代理,可以實現分布式(不同子域名訪問不同的服務后端節點)和負載均衡(相同的域名訪問多個相同的后端節點)
反向代理和正向代理的區別:
- 正向代理:針對客戶端而言,代理服務器代理客戶端,轉發請求,并將獲得的內容返回給客戶端。
- 反向代理:針對客戶端而言,代理服務器就像是原始服務器,代理集群的web節點服務器返回結果。
負載均衡器
負載均衡也是Nginx常用的一個功能,基于nginx反向代理。負載均衡其意思就是分攤到多個操作單元上進行執行,例如Web服務器、FTP服務器、企業關鍵應用服務器和其它關鍵任務服務器等,從而共同完成工作任務。簡單而言就是當有2臺或以上服務器時,根據規則隨機的將請求分發到指定的服務器上處理,負載均衡配置一般都需要同時配置反向代理,通過反向代理跳轉到負載均衡。Nginx目前支持自帶3種負載均衡策略(輪詢、加權輪詢、IP哈希),還有2種常用的第三方策略(fair、url哈希)。
緩存服務器
nginx可以實現圖片、css、js等靜態資源文件的緩存,nginx作為緩存服務器時是搭配nginx作為反向代理服務器一起使用的。當客戶端第一次通過nginx向后端資源服務器請求靜態資源,響應給對應的客戶端同時自身緩存一份,后續如果請求相同的資源,就不需要再次向后端服務器請求了,除非緩存被清理或者緩存過期。
Nginx負載均衡簡介
負載均衡(Load Balance),它在網絡現有結構之上可以提供一種廉價、有效、透明的方法來擴展網絡設備和服務器的帶寬,并可以在一定程度上增加吞吐量、加強網絡數據處理能力、提高網絡的靈活性和可用性等。用官網的話說,它充當著網絡流中“交通指揮官”的角色,“站在”服務器前處理所有服務器端和客戶端之間的請求,從而最大程度地提高響應速率和容量利用率,同時確保任何服務器都沒有超負荷工作。如果單個服務器出現故障,負載均衡的方法會將流量重定向到其余的集群服務器,以保證服務的穩定性。當新的服務器添加到服務器組后,也可通過負載均衡的方法使其開始自動處理客戶端發來的請求。
簡言之,負載均衡實際上就是將大量請求進行分布式處理的策略。
負載均衡是將負載分攤到多個操作單元上執行,從而提高服務的可用性和響應速度,帶給用戶更好的體驗。對于Web應用,通過負載均衡,可以將一臺服務器的工作擴展到多臺服務器中執行,提高整個網站的負載能力。其本質采用一個調度者,保證所有后端服務器都將性能充分發揮,從而保持服務器集群的整體性能最優,這就是負載均衡。
負載均衡是 Nginx 比較常用的一個功能,可優化資源利用率,最大化吞吐量,減少延遲,確保容錯配置,將流量分配到多個后端服務器。
Nginx 在 AKF 可擴展立方體上的應用:
- 在 x 軸上,可以通過橫向擴展應用服務器集群,Nginx 基于 Round-Robin 或者 Least-Connected 算法分發請求。但是橫向擴展并不能解決所有問題,當數據量大的情況下,無論擴展多少臺服務,單臺服務器數據量依然很大。
- 在 y 軸上,可以基于 URL 進行不同功能的分發。需要對 Nginx 基于 URL 進行 location 的配置,成本較高。
- 在 z 軸上可以基于用戶信息進行擴展。例如將用戶 IP 地址或者其他信息映射到某個特定的服務或者集群上去。
這就是 Nginx 的負載均衡功能,它的主要目的就是為了增強服務的處理能力和容災能力。
- 當一個應用單位時間內訪問量激增,服務器的帶寬及性能受到影響,影響大到自身承受能力時,服務器就會宕機奔潰,為了防止這種現象發生,以及實現更好的用戶體驗,我們可以通過配置 Nginx 負載均衡的方式來分擔服務器壓力。
- 當有一臺服務器宕機時,負載均衡器就分配其他的服務器給用戶,極大的增加的網站的穩定性。當用戶訪問 Web 時候,首先訪問到的是負載均衡器,再通過負載均衡器將請求轉發給后臺服務器。
Nginx 作為負載均衡主要有以下幾個理由:
- 高并發連接
- 內存消耗少
- 配置文件非常簡單
- 成本低廉
- 支持 Rewrite 重寫規則
- 內置的健康檢查功能
- 節省帶寬
- 穩定性高
Nginx 工作在網絡的 7 層,可以針對 HTTP 應用本身來做分流策略。支持七層 HTTP、HTTPS 協議的負載均衡。對四層協議的支持需要第三方插件 -yaoweibin 的 ngx_tcp_proxy_module 實現了 TCP upstream。
Nginx被稱為動態負載均衡的主要原因:
- 自身監控。 內置了對后端服務器的健康檢查功能。如果 Nginx Proxy 后端的某臺服務器宕機了,會把返回錯誤的請求重新提交到另一個節點,不會影響前端訪問。它沒有獨立的健康檢查模塊,而是使用業務請求作為健康檢查,這省去了獨立健康檢查線程,這是好處。壞處是,當業務復雜時,可能出現誤判,例如后端響應超時,這可能是后端宕機,也可能是某個業務請求自身出現問題,跟后端無關。
- 可擴展性。 Nginx 屬于典型的微內核設計,其內核非常簡潔和優雅,同時具有非常高的可擴展性。
- Nginx 是純 C 語言的實現,其可擴展性在于其模塊化的設計。目前,Nginx 已經有很多的第三方模塊,大大擴展了自身的功能。nginx_lua_module可以將 Lua 語言嵌入到 Nginx 配置中,從而利用 Lua 極大增強了 Nginx 本身的編程能力,甚至可以不用配合其它腳本語言(如 php 或 Python/ target=_blank class=infotextkey>Python 等),只靠 Nginx 本身就可以實現復雜業務的處理。
- 配置修改。 Nginx 支持熱部署,幾乎可以做到 7*24 不間斷運行,即使運行數個月也不需要重新啟動。能夠在不間斷服務的情況下,對軟件版本進行進行升級。Nginx 的配置文件非常簡單,風格跟程序一樣通俗易懂,能夠支持 perl 語法。使用nginx –s reload 可以在運行時加載配置文件,便于運行時擴容/減容。重新加載配置時,master 進程發送命令給當前正在運行的 worker 進程 worker 進程接到命令后會在處理完當前任務后退出。同時,master 進程會啟動新的 worker 進程來接管工作。
Nginx負載均衡策略
Nginx 作為一款優秀的反向代理服務器,可以通過不同的負載均衡算法來解決請求量過大情況下的服務器資源分配問題。Nginx 的負載均衡策略可以劃分為兩大類:內置策略 和 擴展策略。
- 內置策略包含輪詢、加權輪詢和ip hash等,在默認情況下這兩種策略會編譯進 Nginx 內核,只需在 Nginx 配置中指明參數即可。
- 擴展策略有很多,如fair、通用 hash、consistent hash 等,默認不編譯進 Nginx 內核。
策略 |
作用 |
輪詢 |
按時間順序逐一分配到不同的后端服務器,如果后端服務掛了,能自動剔除 |
加權輪詢 |
權重分配,指定輪詢幾率,weight 值越大,分配到的訪問幾率越高,用于后端服務器性能不均的情況 |
ip_hash |
每個請求按訪問 IP 的 hash 結果分配,這樣每個訪客固定訪問一個后端服務器,可以解決動態網頁 session 共享問題。負載均衡每次請求都會重新定位到服務器集群中的某一個,那么已經登錄某個服務器的用戶再重新定位到另一個服務器,其登錄信息將會丟失,這樣顯然是不妥的 |
least_conn |
最少鏈接數,那個機器連接數少就分支 |
url_hash |
按照訪問的 url 的 hash 結果來分配請求,是每個 url 定向到同一個后端服務器 |
hash 關鍵值 |
hash 自定義的 key |
fair(第三方) |
按后端服務器的響應時間分配,響應時間短的優先分配,依賴第三方插件 nginx-upstream-fair,需要先安裝 |
這里舉出常用的幾種調度算法策略:
輪詢策略
輪詢策略(默認),請求按時間順序,逐一分配到 Web 層服務,然后周而復始,如果 Web 層服務掛掉,自動剔除
輪詢為負載均衡中較為基礎也較為簡單的算法,它不需要配置額外參數。假設配置文件中共有 M 臺服務器,該算法遍歷服務器節點列表,并按節點次序每輪選擇一臺服務器處理請求。當所有節點均被調用過一次后,該算法將從第一個節點開始重新一輪遍歷。
特點:由于該算法中每個請求按時間順序逐一分配到不同的服務器處理,因此適用于服務器性能相近的集群情況,其中每個服務器承載相同的負載。但對于服務器性能不同的集群而言,該算法容易引發資源分配不合理等問題。
upstream backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
weight=number 設置服務器的權重,默認為 1,權重大的會被優先分配。
加權輪詢
為了避免普通輪詢帶來的弊端,加權輪詢應運而生。在加權輪詢中,每個服務器會有各自的權重 weight。一般情況下,weight 的值越大意味著該服務器的性能越好,可以承載更多的請求。該算法中,客戶端的請求按權值比例分配,當一個請求到達時,優先為其分配權值最大的服務器。
特點:加權輪詢可以應用于服務器性能不等的集群中,使資源分配更加合理化。
Nginx 加權輪詢源碼可見:
ngx_http_upstream_round_robin.c ,源碼分析可參考: 關于輪詢策略原理的自我理解 。其核心思想是,遍歷各服務器節點,并計算節點權值,計算規則為 current_weight 與其對應的 effective_weight 之和,每輪遍歷中選出權值最大的節點作為最優服務器節點。其中 effective_weight 會在算法的執行過程中隨資源情況和響應情況而改變。
upstream backend {
server 127.0.0.1:3000 weight=2;
server 127.0.0.1:3001 weight=1;
}
backup 標記為備份服務器。當主服務器不可用時,將傳遞與備份服務器的連接。
upstream backend {
server 127.0.0.1:3000 backup;
server 127.0.0.1:3001;
}
IP 哈希(IP hash)
客戶端 IP 綁定:ip_hash 保持會話,保證同一客戶端始終訪問一臺服務器。
ip_hash 依據發出請求的客戶端 IP 的 hash 值來分配服務器,該算法可以保證同 IP 發出的請求映射到同一服務器,或者具有相同 hash 值的不同 IP 映射到同一服務器。
特點:該算法在一定程度上解決了集群部署環境下 Session 不共享的問題。
Session 不共享問題是說,假設用戶已經登錄過,此時發出的請求被分配到了 A 服務器,但 A 服務器突然宕機,用戶的請求則會被轉發到 B 服務器。但由于 Session 不共享,B 無法直接讀取用戶的登錄信息來繼續執行其他操作。
實際應用中,我們可以利用 ip_hash,將一部分 IP 下的請求轉發到運行新版本服務的服務器,另一部分轉發到舊版本服務器上,實現灰度發布。再者,如遇到文件過大導致請求超時的情況,也可以利用 ip_hash 進行文件的分片上傳,它可以保證同客戶端發出的文件切片轉發到同一服務器,利于其接收切片以及后續的文件合并操作。
upstream backend {
ip_hash;
server 127.0.0.1:3000 backup;
server 127.0.0.1:3001;
}
最小連接數策略
least_conn 優先分配最少連接數的服務器,避免服務器超載請求過多。
假設共有 M 臺服務器,當有新的請求出現時,遍歷服務器節點列表并選取其中連接數最小的一臺服務器來響應當前請求。連接數可以理解為當前處理的請求數。
upstream backend {
least_conn;
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
最快響應時間策略
fair 依賴于 Nginx Plus,有限分配給響應時間最短的服務器
當我們需要代理一個集群時候可以通過下面這種方式實現。
http {
upstream backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
server {
listen 9000;
server_name localhost;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass backend;
}
}
}
標準配置:
# upstream:該指令用于設置可以再 proxy_pass 和 fastcgi_pass 指令中使用的代理服務器
# weight:設置服務器的權重,權重數值越高,被分配到的客戶端請求數越多,默認為 1
# max_fails:指定的時間內對后端服務器請求失敗的次數,如果檢測到后端服務器無法連接及發生服務器錯誤(404 錯誤除外),則標記為失敗,默認為 1,設為數值 0 將關閉這項檢測
# fail_timeout:在經歷參數 max_fails 設置的失敗次數后,暫停的時間
# down:標記服務器為永久離線狀態,用于 ip_hash 指令
# backup:僅僅非在 backup 服務器全部繁忙的時候才會啟用
upstream imooc {
server 116.62.103.228:8001 weight=1 max_fails=2 fail_timeout=30s;
server 116.62.103.228:8002;
server 116.62.103.228:8003;
}
server {
listen 80;
server_name localhost jeson.t.imooc.io;
#charset koi8-r
access_log /var/log/nginx/test_proxy.access.log main;
location / {
proxy_pass http://imooc;
include proxy_params;
}
# error_page 404 /404.html
}
服務器在負載均衡調度中的狀態:
- down:當前的 Server 暫時不參與負載均衡
- backup:預留的備份服務器
- max_fails:允許請求失敗的次數
- fail_timeout:經過max_fails 失敗后,服務暫停的時間
- max_conns:限制最大的接收的連接數