閘道器中介軟體-Nginx(一)
一、Nginx介紹
1.nginx是一個高效能HTTP伺服器,反向代理伺服器,郵件代理伺服器,TCP/UDP反向代理伺服器.
2.nginx處理請求是非同步非阻塞的,在高併發下nginx 能保持低資源低消耗高效能,主要用在集群系統中用於支援負載均衡.
3.nginx對靜態檔案的處理速度也相當快,也可以用於前端站點的伺服器.
二、為什麼要使用Nginx?
單個系統主要用於處理客戶端請求,一個系統處理客戶端的請求量是有限的,當客戶端的併發量超過了系統的處理能力的時候,就會導致伺服器效能降低,速度變慢,直接影響使用者體驗,所以為了提升效能,我們會建立多個服務例項,形成集群系統
用於保證高可用
那麼什麼樣的系統業務適合使用集群系統呢?我覺得主要從2個方面來看,第一請求人數多,導致次數多,第二請求量密集,例如我們近兩年常用的防疫健康碼
三、查詢分流Nginx原理
1.模組化設計
高度模組化的設計是 Nginx的架構基礎。在Nginx中,除了少量的核心程式碼,其他一切皆為模組,所有模組間是分層次、分類別的,Nginx 官方共有五大型別的模組:核心模組
、配置模組
、事件模組
、HTTP模組
、mail模組
,5種模組中,配置模組
和核心模組
是與 Nginx 框架密切相關的。而事件模組則是 HTTP 模組和 mail 模組的基礎。HTTP 模組
和 mail 模組
的“地位”類似,它們都是更關注於應用層面
2.多程序模型
與Memcached的經典多執行緒模型相比,Nginx是經典的多程序模型,Nginx啟動後在後臺執行,後臺程序包含一個master程序和多個worker程序,可以在配置中設定工作程序數,一般根據伺服器的Cpu核心數,來決定工作程序數是多少,例如我的電腦核心數是12,那可以在配置檔案中設定worker_processes為12,那麼在程序中可以看到 一個13個nginx執行例項。
3.事件驅動架構
處理請求事件時,Nginx 的事件消費者只是被事件分發者程序短期呼叫而已,這種設計使得網路效能、使用者感知的請求時延都得到了提升,每個使用者的請求所產生的事件會及時響應,整個伺服器的網路吞吐量都會由於事件的及時響應而增大。當然,這也帶來一定的要求,即每個事件消費者都不能有阻塞行為,否則將會由於長時間佔用事件分發者程序而導致其他事件得不到及時響應,Nginx 的非阻塞特性就是由於它的模組都是滿足這個要求,其實Nginx最佳的部署應該在linux ,linux的io及事件驅動優於windows,我們可以通過配置檔案中設定events的數量表示當前的nginx能處理多少個請求,這個沒有一個絕對的標準,可以基於服務的效能和本身業務需求而定。
4.虛擬主機、反向代理、負載均衡
1.虛擬主機就是為了對所有應用系統進行反向代理。
2.反向代理是指代理後端伺服器,正向代理代表代理客戶端。
3.負載均衡將流量均分到指定後端例項。
四、落地Nginx
我們首先結合實際業務場景分析,然後對不同的業務用例進行落地實踐的方案選擇。
1.負載均衡業務實踐
1.首先我們應該準備一個業務系統,在這就用上面說的“健康碼查詢”業務,模擬一個查詢的服務,注意在這僅僅只是引用場景示例,不代表健康碼真實場景如此, 因為我沒有參與真正的防疫健康碼的開發和設計,也不瞭解它業務和技術架構上真正的複雜度,單純只是由此引入業務場景而已,如果您在閱讀時覺得這樣不合適,您可以把他當做你想當做的任何系統,或者忘記這件事,都是可以的
接下來我們應該下載Nginx作為我們的伺服器,在這裡我使用的是在Windows環境下的演示,其實不管在Linux或者Docker中部署都可以,但是開發在windows,所以基於Windows比較方便。
- 1.建立健康碼服務
- 2.下載nginx
2.我們應該建立服務叢集,在這為了演示建立2個服務例項,然後使用nginx來進行負載均衡查詢分流
-
1.命令列啟動2個服務例項模擬叢集,分別繫結埠8081和8082,其實真實環境不會只有2個例項或者在同一臺伺服器上部署。
-
2.配置nginx的反向代理和負載均衡
worker_processes 1;
error_log logs/error.log info;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
#虛擬主機
server{
listen 8080;
server_name localhost;
#配置反向代理
location / {
proxy_pass http://HealthCode;
}
error_page 500 502 503 504 /50x.html;
}
}
#負載均衡配置
upstream HealthCode{
server localhost:8081;
server localhost:8082;
}
- 3.啟動nginx,並訪問虛擬伺服器
2.負載均衡業務場景分析
針對上面的業務,我們使用到nginx實現負載均衡,那對於我們來說,應該知道Nginx虛擬主機,是如何將我們的請求轉發到各個不同的服務例項的,下面結合業務用例來介紹Nginx中的各種負載均衡演算法
,並設定對應的配置檔案節點。
1.輪訓演算法
根據字面理解就是輪訓處理 1 2 3 4 周而復始,適合伺服器處理能力相同的例項,也可以加入權重,指定輪詢機率,weight和訪問比率成正比,用於伺服器效能不均的情況下,權重越高,在被訪問的概率越大,如下面分別是20%,80%。
#負載均衡配置
upstream HealthCode{
server localhost:8081;
server localhost:8082;
#server localhost:8081 weight=2;
#server localhost:8082 weight=8;
}
2.最小連線數演算法 least_conn
當客戶端給Nginx傳送查詢健康碼的請求時,Nginx把請求轉發給8081和8082 ,如果8082 處理請求比較慢,會導致請求堆積在8082,那我們就需要解決請求堆積的問題,在這種場景下,我們可以把請求轉發給連線數較少的伺服器處理,能夠達到更好的負載均衡效果,使用least_conn演算法,在nginx配置檔案中,負載均衡節點加入配置least_conn
#負載均衡配置
upstream HealthCode{
#配置最小連線數演算法
least_conn;
server localhost:8081;
server localhost:8082;
}
3. hash一致性演算法 ip_hash
由於查詢壓力過大,為了提升可用性,我們在服務端加入快取,例如3分鐘之內請求,就直接將快取的資訊丟出去,客戶端給Nginx傳送查詢健康碼的請求時,Nginx把請求轉發給8081和8082,甚至更多例項,使用輪訓或者最小連線數時,會導致在快取的情況下命中率下降,基於這種快取狀態丟失
的情況,請求依然會給到沒有快取的服務例項,並去資料庫中去查詢資料,導致效能下降。
(當第一次請求傳送到8081去查詢了資料庫,但是在8082 或者其他的節點沒有快取,如果使用輪訓演算法及其他演算法,會導致下次請求時,並不會訪問快取,所以叫快取命中率下降
)
在這種場景下我們應該使用Hash一致性演算法
,將某一個請求客戶端的ip地址與nginx的負載均衡中的某一個例項繫結。
#負載均衡配置
upstream HealthCode{
#配置iphash演算法
ip_hash;
server localhost:8081;
server localhost:8082;
}
4.容災策略
重試機制
1.當客戶端給Nginx傳送查詢請求時,Nginx把請求轉發給8081和8082 ,如果轉發到8081的時候,8081伺服器被人拉閘,臨時宕機了,會導致請求失敗。如何保證請求成功?
在這種場景下我們應該使用nginx的失敗重試
機制,將某一個請求客戶端的ip地址與nginx的負載均衡中的某一個例項繫結。
#動態負載均衡配置
upstream HealthCode{
ip_hash;
#設定最大失敗次數2次,超時時間10s鍾
server localhost:8081 max_fails=2 fail_timeout=10s;
server localhost:8082 max_fails=2 fail_timeout=10s;
}
主機備份 backup
1.查詢時請求轉發給8081和8082 ,假設此時兩個例項同時宕機了,會導致系統不可用,在這種異常業務情況下,我們可以使用主機備份
來解決,注意在正常節點在執行時 ,備份節點是不工作的,如果使用ip_hash
將不會生效,因為ip和主機已經繫結。
#動態負載均衡配置
upstream HealthCode{
ip_hash;
server localhost:8081 max_fails=2 fail_timeout=10s;
server localhost:8082 max_fails=2 fail_timeout=10s;
#主機備份
server localhost:8083 backup;
}