upstream 主要是配置均衡池和調度方法
proxy_pass 主要是配置代理服務器ip或服務器組的名字
upstream testTomcat{
server 127.0.0.1:81 weight=1;
server 127.0.0.1:82 weight=1;
server 127.0.0.1:83 weight=1;
}
server {
listen 80;
server_name test.xm;
location /test/ {
proxy_pass http://testTomcat;
proxy_set_header Host $host;
}
}
proxy_pass配置的4種方式
假如訪問:http://192.168.1.1/test/index.php
第一種:
location /test/ {
proxy_pass http://testTomcat/;
}
代理到URL:http://127.0.0.1:81/index.php
第二種(相對於第一種,最后少一個 / )
location /test/ {
proxy_pass http://testTomcat;
}
代理到URL:http://127.0.0.1:81/test/index.php
第三種:
location /test/ {
proxy_pass http://testTomcat/abc/;
}
代理到URL:http://127.0.0.1:81/abc/index.php
第四種(相對於第三種,最后少一個 / )
location /test/ {
proxy_pass http://testTomcat/abc;
}
代理到URL:http://127.0.0.1:81/abcindex.php
問題1:
假如正訪問購物網,看中一款商品,網頁一刷新,就被代理到台后端另一台服務器上了,這就會出現問題。希望的是能識別主機,也就是:當一個客戶端訪問前端,被代理到后台一台服務器后,以后就始終被代理到這台服務器。這里用到ip_hash 通過客戶端ip進行hash,再通過hash值選擇后端server
upstream testTomcat{
ip_hash; ##客戶端ip進行hash
server 127.0.0.1:89 weight=1;
server 61.155.141.13:888 weight=1;
server 61.155.141.14:81 weight=1;
}
ps:其實 ip_hash也還是有一定問題,比如用戶在下單時,突然切換網絡了(這個問題下次討論。。。。。。)
問題2:
服務器性能不一樣,有的配置較高,有的已經老舊,配置較低,采用上面輪詢方式顯然不符合負載均衡要求。解決這個問題的辦法是:采用比重的方式,在前端配置文件里加入比重參數(weight)
upstream testTomcat{
server 127.0.0.1:81 weight=1;
server 127.0.0.1:82 weight=2;
server 127.0.0.1:83 weight=3;
}
問題3:
如果其中的一台服務器發生錯誤或超時時,通常希望Nginx自動重試其他的服務。
實際上Nginx本身默認會有錯誤重試機制,並且可以通過proxy_next_upstream
來自定義配置,其默認值是proxy_next_upstream error timeout,即發生網絡錯誤以及超時,才會重試其他服務器
如果想其他服務器其他狀態重試,
location /test/ {
proxy_pass http://testTomcat;
## 配置http 404 http502
proxy_next_upstream error timeout http_404 http_502;
}
注意: 如果get 請求 http://127.0.0.1:81/test/index.php Nginx默認會失敗重試,但是如果是post請求時 Nginx默認不會失敗重試
如果想post也默認會失敗重試,可以加上選項 non_idempotent
location /test/ {
proxy_pass http://testTomcat;
## 配置http 404 http502 non_idempotent
proxy_next_upstream error timeout http_404 http_502 non_idempotent;
}
ps:通常情況下,如果請求使用非等冪方法(POST、LOCK、PATCH),請求失敗后不會再到其他服務器進行重試。加上non_idempotent
選項后,即使是非冪等請求類型(例如POST請求),發生錯誤后也會重試。
什么是冪等方法
如果使用該方法的多個相同請求對服務器的預期效果與單個請求的效果相同,則認為請求方法是冪等的。常見的HTTP請求方法中,GET是冪等的,而POST是非冪等的。如果在回答面試題"GET和POST區別"時能答出這一點,才能說明對HTTP協議有一定的理解
在做業務開發是如何理解冪等性,舉個最簡單的例子:GET方法一般用於獲取數據,如果獲取的是數據庫數據,對應的是SELECT語句。同樣的SELECT語句執行一次還是多次,都不會影響數據。而POST一般對應INSERT,如果執行多次后,可能會造成數據重復插入的問題。所以不要使用GET方法做一些INSERT操作,在業務開發時要遵循HTTP協議規范。
注意:生產環境中不建議加上non_idempotent
選項,因為無論是發生500錯誤還是timeout,服務器上的業務可能已經執行過了,而重試會導致非冪等方法重復執行,從而導致業務問題,例如一個請求會創建了多個訂單,或者收到多條短信的問題。