一、Nginx介紹
1.nginx是一個高性能HTTP服務器,反向代理服務器,郵件代理服務器,TCP/UDP反向代理服務器.
2.nginx處理請求是異步非阻塞的,在高並發下nginx 能保持低資源低消耗高性能,主要用在集群系統中用於支持負載均衡.
3.nginx對靜態文件的處理速度也相當快,也可以用於前端站點的服務器.
二、為什么要使用Nginx?
單個系統主要用於處理客戶端請求,一個系統處理客戶端的請求量是有限的,當客戶端的並發量超過了系統的處理能力的時候,就會導致服務器性能降低,速度變慢,直接影響用戶體驗,所以為了提升性能,我們會創建多個服務實例,形成集群系統用於保證高可用
那么什么樣的系統業務適合使用集群系統呢?我覺得主要從2個方面來看,第一請求人數多,導致次數多,第二請求量密集,例如我們近兩年常用的防疫健康碼查詢,我們排除與其他的業務系統接入的因素,可以說他的99%針對用戶的業務其實就是查詢,而且並發量和請求數也是非常龐大的,所以就很適合使用集群系統。
三、查詢分流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 周而復始,它是upstream模塊默認的負載均衡默認策略,適合服務器處理能力相同的實例,在輪詢中,如果某個服務實例宕機了,會自動剔除該服務器。,也可以加入權重,指定輪詢幾率,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;
}
五、配置HTTPS
我們要保證我們的請求的安全,所以需要使用Https通信,同樣需要對我們的虛擬主機設置https,設置https的前提需要證書,一個是秘鑰(server-key.pem),一個是證書(server-cert.pem)。
1.基本設置
1.下載openSSL,然后使用openSSL工具生成,教程連接
2.找到證書生成路徑
3.然后在nginx配置文件添加對應的虛擬主機節點,然后配置Https
# https 虛擬主機
server {
listen 4435 ssl;
server_name localhost;
ssl_certificate D:/cert/server-cert.pem;
ssl_certificate_key D:/cert/server-key.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
location / {
proxy_pass http://HealthCode;
}
}
2.http轉https
系統當中總是有很多默認的Http請求,我們需要使用nginx的ngx_http_rewrite_module模塊來將http請求轉換成https
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;
#默認重定向到https
if($scheme = http)
{
return 301 https://$host:4435$request_url
}
#配置反向代理
location / {
proxy_pass http://HealthCode;
}
error_page 500 502 503 504 /50x.html;
}
}
#負載均衡配置
upstream HealthCode{
server localhost:8081;
server localhost:8082;
}
