一. 負(fù)載均衡1. 用法
通過proxy_pass 可以把請求代理至后端服務(wù),但是為了實(shí)現(xiàn)更高的負(fù)載及性能, 我們的后端服務(wù)通常是多個(gè), 這個(gè)是時(shí)候可以通過upstream 模塊實(shí)現(xiàn)負(fù)載均衡。
使用的模塊為:【ngx_http_upstream_module】,具體配置可以根據(jù)模塊名去查找文檔。
負(fù)載均衡的算法有:
- ll:輪詢
- ll+weight:輪詢加權(quán)重
- ip_Hash :基于Hash 計(jì)算,用于保持session 一至性該算法下權(quán)重失效
- url_hash:靜態(tài)資源緩存,節(jié)約存儲,加快速度(第三方)該算法下權(quán)重配置失效
- least_conn:最小鏈接數(shù)
- least_time:最小的響應(yīng)時(shí)間,計(jì)算節(jié)點(diǎn)平均響應(yīng)時(shí)間,然后取響應(yīng)最快的那個(gè),分配更高權(quán)重
2. 參數(shù)
upstream 相關(guān)參數(shù)如下:
- server反向服務(wù)地址加端口
- weight權(quán)重,默認(rèn)是1,越大權(quán)重就越大
- max_fAIls失敗多少次認(rèn)為主機(jī)已掛掉則,踢出(默認(rèn)配置10s,即服務(wù)器宕掉,會自動剔除)
- fail_timeout踢出后重新探測時(shí)間
- backup備用服務(wù),當(dāng)其他非backup的機(jī)器全部宕機(jī)或者繁忙的時(shí)候,才會啟動這臺機(jī)器。
- down表示當(dāng)前Server不參與負(fù)載
- max_conns允許最大連接數(shù)
- slow_start當(dāng)節(jié)點(diǎn)恢復(fù),不立即加入,而是等待 slow_start 后加入服務(wù)對列。
upstream myApiTest {server localhost:9001 weight=10;server localhost:9002 weight=5;server localhost:9003 max_fails=3 fail_timeout=30s;server localhost:9004 backup;server localhost:9005 down;
3. 案例
事先準(zhǔn)備:
有三個(gè)同樣的api服務(wù),分別部署在9001、9002、9003端口下,比如:訪問 http://localhost:9001/Home/GetMsg,會返回 【 獲取成功,當(dāng)前端口為:9001】,其它端口類似。
要求:
Nginx監(jiān)聽8080端口,接收到8080端口的請求,按照響應(yīng)的算法進(jìn)行轉(zhuǎn)發(fā)到9001-9003端口。
(1). 輪詢
訪問地址:http://localhost:8080/Home/GetMsg ,會依次轉(zhuǎn)發(fā)到9001、9002、9003端口上。【最新版本測試,輪詢的時(shí)候一個(gè)服務(wù)器連續(xù)淪陷兩次,才到下一個(gè)服務(wù)器,繼續(xù)連續(xù)兩次】??
配置如下:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type Application/octet-stream;sendfile on;keepalive_timeout 65;upstream myApiTest {server localhost:9001;server localhost:9002;server localhost:9003;server {listen 8080;server_name xxx; #隨意配置一個(gè)即可,優(yōu)先走代理地址location / {proxy_pass http://myApiTest;error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
補(bǔ)充其他參數(shù)說明:
下面配置,當(dāng)請求 http://localhost:8080/Home/GetMsg 時(shí)候,只會被轉(zhuǎn)發(fā)到9003端口上,此時(shí)把9003端口的服務(wù)關(guān)掉,再次請求,則會被轉(zhuǎn)發(fā)到9001端口上,其中9002端口,全程不參與負(fù)載。
upstream myApiTest {server localhost:9001 backup;server localhost:9002 down;server localhost:9003;
(2).輪詢+權(quán)重
下面配置,被轉(zhuǎn)發(fā)到9001 9002端口的概率要大于9003端口。
配置如下:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;upstream myApiTest {server localhost:9001 weight=10;server localhost:9002 weight=5;server localhost:9003;server {listen 8080;server_name xxx; #隨意配置一個(gè)即可,優(yōu)先走代理地址location / {proxy_pass http://myApiTest;error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
(3). ip_hash
同一個(gè)ip永遠(yuǎn)會被分配到同一個(gè)Server上,主要用來解決Session不一致的問題,但該策略也有弊端,weight權(quán)重?zé)o效,所以該方案會導(dǎo)致某個(gè)Server壓力可能過大,請求分配不均勻問題。
配置如下:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;upstream myApiTest {ip_hash; #開啟ip_hash策略server localhost:9001;server localhost:9002;server localhost:9003;server {listen 8080;server_name xxx; #隨意配置一個(gè)即可,優(yōu)先走代理地址location / {proxy_pass http://myApiTest;error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
(4). url_hash
主要用于節(jié)省空間,比如我有9G的圖片資源,服務(wù)器集群有三臺,因?yàn)椴淮_定請求會被轉(zhuǎn)發(fā)到哪一臺上,所以每臺服務(wù)器都存放9G,顯然這樣是不合理的。
我們可以在存儲的時(shí)候,將圖片進(jìn)行urlhash算法,分別存放到三臺服務(wù)器上,這樣請求的時(shí)候也是用urlhash,去指定服務(wù)器請求即可,節(jié)省了服務(wù)器空間,也就是3臺服務(wù)器總共用了9G。
PS:上面只是舉例方便理解,生產(chǎn)中,大量圖片資源存放cdn第三方,然后在自己的服務(wù)器上做一層臨時(shí)緩存,為了提高緩存的命中率,通常用urlhash算法。
更多C++后臺開發(fā)技術(shù)點(diǎn)知識內(nèi)容包括C/C++,linux,Nginx,ZeroMQ,MySQL,redis,MongoDB,ZK,流媒體,音視頻開發(fā),Linux內(nèi)核,TCP/IP,協(xié)程,DPDK多個(gè)高級知識點(diǎn)。
C/C++后臺開發(fā)架構(gòu)師免費(fèi)學(xué)習(xí)地址:C/C++Linux鏈嶅姟鍣ㄥ紑鍙?/鍚庡彴鏋舵瀯甯堛€愰浂澹版暀鑲層€?-瀛︿範(fàn)瑙嗛鏁欑▼-鑵捐璇懼爞
【文章福利】另外還整理一些C++后臺開發(fā)架構(gòu)師 相關(guān)學(xué)習(xí)資料,面試題,教學(xué)視頻,以及學(xué)習(xí)路線圖,免費(fèi)分享有需要的可以點(diǎn)擊 Linux C++鍚庡彴寮€鍙戠浉鍏寵棰戯紝鏂囨。浠g爜璧勬枡鍖咃紝瀛︿範(fàn)璺嚎鎬濈淮瀵煎浘鍏嶈垂棰嗗彇 免費(fèi)領(lǐng)取
二. 限流配置1. 說明
(1). 限流的作用
限流主要用作安全目的,比如可以減慢暴力密碼破解的速率。
通過將傳入請求的速率限制為真實(shí)用戶的典型值,并標(biāo)識目標(biāo)URL地址(通過日志),
還可以用來抵御DDoS攻擊。更常見的情況,該功能被用來保護(hù)上游應(yīng)用服務(wù)器不被同時(shí)太多用戶請求所壓垮。
(2). 原理
令牌桶算法
漏桶算法
(3). 涉及到的模塊
A. 用來限制同一時(shí)間連接數(shù),即并發(fā)限制 【不常用】
【ngx_http_limit_conn_module】 對應(yīng)文檔:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
B. 用來限制單位時(shí)間內(nèi)的請求數(shù),即速率限制,采用的漏桶算法 【推薦使用】
【ngx_http_limit_req_module】 對應(yīng)文檔:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
2. 環(huán)境準(zhǔn)備
(1). Api接口
啟動指令如下:
【do.NET NginxTest.dll --urls="http://*:7061" --ip="127.0.0.1" --port=7061】
【dotnet NginxTest.dll --urls="http://*:7062" --ip="127.0.0.1" --port=7062】
接口地址為: http://localhost:7061/api/Home/GetNowTime 【Post請求】
接口代碼如下:
[Route("api/[controller]/[action]")][ApiController]public class HomeController : ControllerBase[HttpPost]public string GetNowTime()string nowTime = DateTime.Now.ToString();Console.WriteLine($"當(dāng)前時(shí)間為:{nowTime}");return $"當(dāng)前時(shí)間為:{nowTime}";
(2). nginx服務(wù)
使用到的指令
啟動服務(wù):【start nginx】
強(qiáng)制關(guān)閉服務(wù):【nginx -s stop】
重載服務(wù):【nginx -s reload】
nginx監(jiān)聽7000端口,然后進(jìn)行代理配置,這里重點(diǎn)測試的是限流,只用7061一個(gè)api端口即可。
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 7000; #監(jiān)聽端口server_name xxx; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
通過post請求訪問:http://localhost:7000/api/Home/GetNowTime ,返回當(dāng)前時(shí)間,表示配置成功。
(3). jmeter測試工具
添加線程組,然后在線程組的基礎(chǔ)上添加:http請求、察看結(jié)果樹、聚合報(bào)告、用表格查結(jié)果。
配置請求的并發(fā)數(shù)、請求地址。
測試結(jié)果:10個(gè)請求全部成功。
3. 限流-限制并發(fā)連接數(shù)【不常用】
聲明格式:
limit_conn_zone $server_name zone=myLimit0:10m;limit_conn_zone $binary_remote_addr zone=myLimit1:10m;
(1). $server_name:表示虛擬主機(jī)(server) 同時(shí)能處理并發(fā)連接的總數(shù)。 (數(shù)量在啟用時(shí)配置)
(2). $binary_remote_addr:表示限制每個(gè)客戶端IP(單個(gè)ip)連接到服務(wù)器的鏈接數(shù)量。 (數(shù)量在啟用時(shí)配置)
(3). zone=myLimit1:10m :表示內(nèi)存區(qū)域名稱 和 空間大小。
調(diào)用格式:
limit_conn myLimit1 2; #啟用限流
(1). myLimit1 :表示用上述聲明的哪個(gè)配置進(jìn)行限制,myLimit1與上述聲明的名稱相對應(yīng)。
(2). 2: 表示配置的數(shù)量限制。
(1). 限制-虛擬主機(jī)同時(shí)能處理的并發(fā)鏈接總數(shù)
分析:
虛擬主機(jī)(server) 同時(shí)能處理并發(fā)連接的總數(shù)為5.
測試條件:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 限流配置聲明limit_conn_zone $server_name zone=myLimit0:10m;server {listen 7000; #監(jiān)聽端口server_name xxx; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {limit_conn myLimit0 5; #啟用限流proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
測試結(jié)果:
忽略
(2). 限制-單個(gè)ip鏈接到服務(wù)器的數(shù)量
剖析:
單個(gè)IP同時(shí)最多能持有8個(gè)連接
測試條件:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 限流配置聲明limit_conn_zone $binary_remote_addr zone=myLimit1:10m;server {listen 7000; #監(jiān)聽端口server_name xxx; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {limit_conn myLimit1 8; #啟用限流proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
測試結(jié)果:忽略
4. 限流-限制速率【推薦使用】
聲明格式:
limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=5r/s;
(1). $binary_remote_addr : 表示限制同一客戶端ip地址,即限制速率是以ip為分類的,限制每個(gè)ip的速度。
(2). zone=myLimit2:10m: myLimit2表示內(nèi)存區(qū)域的名稱,10m表示內(nèi)存空間的大小。
(3). rate=5r/s : 表示1s允許5個(gè)請求,注意這里需要拆分理解,即200ms允許1個(gè)請求,當(dāng)?shù)谝粋€(gè)請求處理完成,如果200ms內(nèi)又進(jìn)來一個(gè)請求,該請求將被拒絕處理,只有過了200ms后,才會處理第2個(gè)請求,一次類推。
調(diào)用格式 :
limit_req zone=myLimit2 burst=5 nodelay;
(1). zone=myLimit2:表示用上述聲明的哪個(gè)配置進(jìn)行限制,myLimit2與上述聲明的名稱相對應(yīng)。
(2). burst=5 :設(shè)置一個(gè)大小為5的緩沖區(qū),當(dāng)有大量請求(瞬間爆發(fā))過來時(shí),超過了上述配置的訪問頻次限制的請求,可以先放到這個(gè)緩沖區(qū)內(nèi)。
注:burst的作用是讓多余的請求可以先放到隊(duì)列里,慢慢處理。如果不加nodelay參數(shù),隊(duì)列里的請求不會立即處理,而是按照rate設(shè)置的速度,以毫秒級精確的速度慢慢處理。
(3). nodelay : 設(shè)置后,burst緩沖區(qū)中排隊(duì)的請求立即被處理,超過頻次限制 并且 緩沖區(qū)滿了的情況下,直接返回503狀態(tài)碼;如不設(shè)置,那么額外的請求將進(jìn)入等待排隊(duì)的狀態(tài)
注:通過設(shè)置burst參數(shù),我們可以允許Nginx緩存處理一定程度的突發(fā),多余的請求可以先放到隊(duì)列里,慢慢處理,不報(bào)錯(cuò),這起到了平滑流量的作用。
但是如果隊(duì)列設(shè)置的比較大,請求排隊(duì)的時(shí)間就會比較長,從用戶角度看來就是響應(yīng)變長了,這對用戶很不友好,所以引入nodelay參數(shù)。
nodelay參數(shù)允許請求在排隊(duì)的時(shí)候就立即被處理,也就是說只要請求能夠進(jìn)入burst隊(duì)列,就會立即被后臺處理,請注意,這意味著burst設(shè)置了nodelay時(shí),系統(tǒng)瞬間的QPS可能會超過rate設(shè)置的閾值。
所以:nodelay參數(shù)要跟burst一起使用才有作用。
(1). 實(shí)操1-限制速率
分析:
使用jmeter發(fā)送10個(gè)請求進(jìn)行測試,nginx的限制速率設(shè)置為 2r/s,意味著第1個(gè)請求處理完后,500ms內(nèi)接收的請求都將拒絕,過了500ms后,才能處理下一個(gè)請求。 詳見下面的測試結(jié)果。
測試條件:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 限流配置聲明limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=2r/s;server {listen 7000; #監(jiān)聽端口server_name xxx; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {limit_req zone=myLimit2; #啟用限流proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
測試結(jié)果:
第1個(gè)成功的請求的是008ms,接下來第 2-6個(gè)請求,由于是在500ms內(nèi),所有都請求失?。?第2個(gè)成功的請求為608ms,正好過了500ms了,所以成功了。
(2). 限制速率+設(shè)置緩沖區(qū)
分析:
使用jmeter發(fā)送10個(gè)請求進(jìn)行測試,nginx的限制速率設(shè)置為 2r/s,burst=5,意味著第1個(gè)請求處理完后,接下來的5個(gè)請求都是存放到緩存中,第7個(gè)請求如果在第1個(gè)的500ms后,則請求成功,反之失敗。
測試條件:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 限流配置聲明limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=2r/s;server {listen 7000; #監(jiān)聽端口server_name xxx; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {limit_req zone=myLimit2 burst=5; #啟用限流proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
測試結(jié)果:
第1個(gè)成功的請求為343ms,接下來第2-6個(gè)加入到緩存區(qū),依次執(zhí)行成功; 第7個(gè)請求為944,與第一個(gè)成功的請求相比,已經(jīng)超過了500ms,所以執(zhí)行成功,接下來的8-10個(gè)請求,均在第7個(gè)成功后的500ms內(nèi),所以均失敗。
(3). 限制速率+設(shè)置緩沖區(qū)+立即處理
分析:
使用jmeter發(fā)送10個(gè)請求進(jìn)行測試,nginx的限制速率設(shè)置為 2r/s,burst=5 nodelay,意味著第1個(gè)請求處理完后,接下來的5個(gè)請求立即執(zhí)行,第7個(gè)請求如果在第1個(gè)的500ms后,則請求成功,反之失敗。
測試條件:
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 限流配置聲明limit_req_zone $binary_remote_addr zone=myLimit2:10m rate=1r/s;server {listen 7000; #監(jiān)聽端口server_name xxx; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {limit_req zone=myLimit2 burst=5 nodelay; #啟用限流proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;
測試結(jié)果:
第1個(gè)成功的請求為278ms,接下來2-6個(gè)立即執(zhí)行,第7個(gè)請求為879,距離第一個(gè)成功的已經(jīng)超過500ms,所以執(zhí)行成功,接下來的8-10個(gè)請求,均在500ms內(nèi),所以執(zhí)行失敗。
三. Https配置1. 準(zhǔn)備
(1). 生成證書
OpenSSL工具下載地址:http://slproweb.com/products/Win32OpenSSL.html 【這里以3.0.5為例】
OpenSSL生成證書步驟:https://jingyan.baidu.com/article/6c67b1d6be538c2787bb1e06.html
(2). 相關(guān)模塊
【ngx_http_rewrite_module】 參考文檔:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
2. 實(shí)操
(1). 配置https的Server
開啟一個(gè)新的虛擬主機(jī),用來配置https監(jiān)聽8000端口,配置證書的物理地址即可,就可以通過https://localhost:8000/api/Home/GetNowTime ,訪問代理地址下7061的api了。
(PS:下面配置同時(shí)開啟了 http的主機(jī),所以通過http://localhost:7000/api/Home/GetNowTime,也可以訪問)
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;#http主機(jī)server {listen 7000; #監(jiān)聽端口server_name test1; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {proxy_pass http://localhost:7061; #代理地址error_page 500 502 503 504 /50x.html;location = /50x.html {root html;#https主機(jī)server {listen 8000 ssl;server_name test2;#證書目錄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;location / {proxy_pass http://localhost:7061;
(2). 將http跳轉(zhuǎn)到https
上述http監(jiān)聽的7000端口,https監(jiān)聽的8000端口,如何讓http請求自動跳轉(zhuǎn)到https請求上呢?
加個(gè)return 301 xxxxx跳轉(zhuǎn)即可。
worker_processes 1;events {worker_connections 1024;http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;#http主機(jī)server {listen 7000; #監(jiān)聽端口server_name test1; #隨意配置一個(gè)地址即可,優(yōu)先走代理location / {proxy_pass http://localhost:7061; #代理地址#跳轉(zhuǎn)到https (test2是https主機(jī)的server_name)return 301 https://test2$request_uri;#或者#return 301 https://$host:8000$request_uri;error_page 500 502 503 504 /50x.html;location = /50x.html {root html;#https主機(jī)server {listen 8000 ssl;server_name test2;#證書目錄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;location / {proxy_pass http://localhost:7061;
原文鏈接:第二節(jié):Nginx負(fù)載均衡配置、限流配置、Https配置詳解 - Yaopengfei - 博客園