Nginx在生產(chǎn)中的應(yīng)用
點(diǎn)擊關(guān)注公眾號,Java干貨及時(shí)送達(dá)

反向代理
在很多企業(yè)項(xiàng)目中,nginx都會被拿來做反向代理,那么究竟什么是反向代理呢?我們通過一張圖來理解一下:
當(dāng)用戶發(fā)起網(wǎng)絡(luò)請求時(shí),首先會由系統(tǒng)的網(wǎng)關(guān)接收到該請求,網(wǎng)關(guān)將請求轉(zhuǎn)發(fā)給nginx服務(wù)器,nginx服務(wù)器再將請求轉(zhuǎn)發(fā)給tomcat服務(wù)器,注意這里的網(wǎng)關(guān)是無法直接訪問tomcat服務(wù)器的,這樣做的好處是什么呢?好處在于外網(wǎng)是無法訪問到tomcat的,它只能訪問到nginx服務(wù)器,再由nginx去訪問,這樣就保證了tomcat服務(wù)器的安全。那么與之相反的是正向代理,正向代理就比較簡單了,比如你想訪問Google,你就需要搭建一個(gè)代理服務(wù)器進(jìn)行訪問:
乍一看,正向代理和反向代理好像沒有什么區(qū)別,事實(shí)上,它們兩者只是角度上的不同,對于正向代理,它是對客戶端的代理,即:客戶端需要訪問一個(gè)無法直接訪問的資源,則通過代理服務(wù)器進(jìn)行一個(gè)轉(zhuǎn)發(fā),最終訪問到資源服務(wù)器;而反向代理是對服務(wù)端的代理,即:客戶端在訪問一個(gè)資源時(shí),先將請求發(fā)到服務(wù)器,再由內(nèi)部的代理服務(wù)器進(jìn)行一個(gè)轉(zhuǎn)發(fā)。對于反向代理,客戶端是無感知的,因?yàn)檫@個(gè)代理過程是在服務(wù)端內(nèi)部進(jìn)行的,而正向代理是由客戶端主動配置的,這些就是它們的一些區(qū)別。那么在nginx中如何進(jìn)行反向代理的配置呢?
server?{
??listen?80;
??server_name?localhost;
??
??location?/?{
????proxy_pass?http://www.baidu.com;
??}
}
現(xiàn)在我們?nèi)羰窃L問http://192.168.33.10,則請求會被轉(zhuǎn)發(fā)到百度首頁。
負(fù)載均衡
負(fù)載均衡指的是對某個(gè)服務(wù)進(jìn)行多個(gè)備份,每個(gè)備份都運(yùn)行在一臺服務(wù)器上,當(dāng)請求來到時(shí),nginx可以選擇將請求轉(zhuǎn)發(fā)到某個(gè)服務(wù)器上,這樣做的好處是每個(gè)服務(wù)器能夠均衡地處理請求數(shù),不會發(fā)生某個(gè)服務(wù)器請求量非常多,而某個(gè)服務(wù)器請求量又非常小的情況,如圖:
這里共有三臺機(jī)器部署了服務(wù)A,此時(shí)nginx可以選擇將請求轉(zhuǎn)發(fā)給某臺服務(wù)器,比如將第一個(gè)請求轉(zhuǎn)發(fā)給第一臺服務(wù)器,將第二個(gè)請求轉(zhuǎn)發(fā)給第二臺服務(wù)器,將第三個(gè)請求轉(zhuǎn)發(fā)給第三臺服務(wù)器,將第四個(gè)請求又重新轉(zhuǎn)發(fā)給第一臺服務(wù)器。以此類推,我們可以得到一個(gè)規(guī)律:請求需要轉(zhuǎn)發(fā)到哪臺服務(wù)器上 = 第幾次請求 % 服務(wù)器臺數(shù),這是負(fù)載均衡中比較簡單的輪詢算法。那么負(fù)載均衡在nginx中又該如何配置呢?
http?{
??upstream?alls?{
????server?192.168.33.10:80;
????server?192.168.34.10;
????server?192.168.35.10;
??}
??server?{
????listen?80;
????server_name?localhost;
??
????location?/?{
??????proxy_pass?http://alls;
????}
??}
}
首先通過upstream alls配置一組服務(wù)器,這里的alls是這組服務(wù)器的別名,然后再借助proxy_pass [http://alls](http://alls)進(jìn)行反向代理,因?yàn)閍lls是一組服務(wù)器,所以nginx會進(jìn)行負(fù)載均衡,默認(rèn)為輪詢的方式。
負(fù)載均衡策略
事實(shí)上, 除了輪詢方式,負(fù)載均衡還有很多種策略,分別如下:
權(quán)重分配 IP哈希 最少連接 響應(yīng)時(shí)間 定向流量轉(zhuǎn)發(fā)
權(quán)重分配
當(dāng)服務(wù)器集群中的服務(wù)器出現(xiàn)性能不同的情況時(shí),比如某臺服務(wù)器性能很好,能夠支撐更高的請求量,而有些服務(wù)器性能比較差,能接受的請求量也有限,此時(shí)就不能使用輪詢策略,而是想辦法將多一點(diǎn)的請求轉(zhuǎn)發(fā)給性能好的服務(wù)器,讓性能差的服務(wù)器少處理一點(diǎn)請求。
以上就是基于權(quán)重分配的負(fù)載均衡策略,配置方式如下:
http?{
??upstream?alls?{
????server?192.168.33.10:80?weight=8;
????server?192.168.34.10?weight=5;
????server?192.168.35.10?weight=2;
??}
??server?{
????listen?80;
????server_name?localhost;
??
????location?/?{
??????proxy_pass?http://alls;
????}
??}
}
權(quán)重分配方式是按照比例來進(jìn)行負(fù)載的,比如有90個(gè)請求,則大約有48個(gè)請求會轉(zhuǎn)發(fā)到192.168.33.10服務(wù)器;大約有30個(gè)請求會轉(zhuǎn)發(fā)到192.168.34.10服務(wù)器,大約有12個(gè)請求會轉(zhuǎn)發(fā)到192.168.35.10服務(wù)器。若是不想讓某臺服務(wù)器參與負(fù)載均衡的選擇,則可以使用down參數(shù)進(jìn)行配置:
upstream?alls?{
??server?192.168.33.10:80?weight=8?down;
??server?192.168.34.10?weight=5;
??server?192.168.35.10?weight=2;
}
upstream中還有一個(gè)backup參數(shù):
upstream?alls?{
??server?192.168.33.10:80?weight=8;
??server?192.168.34.10?weight=5;
??server?192.168.35.10?weight=2?backup;
}
它的作用是將某臺服務(wù)器設(shè)置為備用服務(wù)器,一般情況下負(fù)載均衡是不會將請求轉(zhuǎn)發(fā)給備用服務(wù)器的,只有當(dāng)其它服務(wù)器都掛了,沒有其它服務(wù)器可用了,只剩下備用服務(wù)器自己了,請求才會被負(fù)載到它的身上(比如當(dāng)192.168.33.10:80、192.168.34.10服務(wù)器都掛掉時(shí),能夠負(fù)載均衡的選擇就只剩下192.168.35.10了)。
IP哈希
負(fù)載均衡帶來的問題是無法保證會話,比如當(dāng)你進(jìn)行登錄時(shí),請求被轉(zhuǎn)發(fā)到了某臺服務(wù)器,登錄完成后,當(dāng)你進(jìn)行一些需要登錄的操作時(shí),比如下單,此時(shí)下單的請求被轉(zhuǎn)發(fā)到了另外一臺服務(wù)器,因?yàn)檫@臺服務(wù)器是沒有用戶登錄的cookie、session等信息的,所以登錄狀態(tài)就消失了,這是不被允許的。通過IP哈希的方式,可以讓某一個(gè)IP的請求都轉(zhuǎn)發(fā)到同一臺服務(wù)器,這樣便能夠維持用戶會話的狀態(tài),然而隨著互聯(lián)網(wǎng)的發(fā)展,這種方式已經(jīng)無法保證維持會話了,因?yàn)镮P隨時(shí)可能發(fā)生變化。
最少連接
最少連接方式指的是負(fù)載均衡會盡量將請求轉(zhuǎn)發(fā)給連接量更少的服務(wù)器上,目的是使服務(wù)器上的連接數(shù)更加均衡,這種方式一般來說也是不太常用的,因?yàn)榉?wù)器存在性能上的差異,更加均衡勢必會導(dǎo)致一些問題的產(chǎn)生。
響應(yīng)時(shí)間
響應(yīng)時(shí)間方式是根據(jù)后端服務(wù)器的響應(yīng)時(shí)間來轉(zhuǎn)發(fā)請求,當(dāng)某臺服務(wù)器的響應(yīng)時(shí)間更短時(shí),那么更多的請求將轉(zhuǎn)發(fā)給該服務(wù)器。
定向流量轉(zhuǎn)發(fā)
定向流量轉(zhuǎn)發(fā)方式指的是對請求的某個(gè)資源url進(jìn)行哈希得到待轉(zhuǎn)發(fā)的服務(wù)器,這種方式也是無法維護(hù)會話狀態(tài)的,不過在對某些無狀態(tài)的資源進(jìn)行請求時(shí),而這些資源分布在不同的服務(wù)器上,定向流量轉(zhuǎn)發(fā)方式還是適用的,它可以通過url哈希得到資源具體所在的服務(wù)器。
動靜分離
在訪問一個(gè)網(wǎng)站的首頁時(shí),通常會伴隨著非常多的請求,包括圖片、mp3等等資源:
僅僅是訪問一個(gè)淘寶的首頁請求就有100多個(gè),這些內(nèi)容都需要經(jīng)過后臺服務(wù)器的映射:
而對于這些靜態(tài)資源,我們完全可以由nginx代為管理,不用tomcat再去操心了,如下所示:
這就是nginx動靜分離所做的事情。我們假設(shè)現(xiàn)在有一個(gè)項(xiàng)目運(yùn)行在192.168.33.10服務(wù)器上的tomcat中,那么首先通過nginx配置反向代理:
server?{
??listen?80;
??server_name?localhost;
??location?/?{
????proxy_pass?http://192.168.33.10:8080;
??}
}
然后將靜態(tài)資源(css、js、img)放在nginx的html目錄下,并進(jìn)行配置:
server?{
??listen?80;
??server_name?localhost;
??location?/?{
????proxy_pass?http://192.168.33.10:8080;
??}
??
??location?/css{
????root?html;
??}
??
??location?/js{
????root?js;
??}
??
??location?/img{
????root?img;
??}
}
這三個(gè)location的配置其實(shí)可以借助正則表達(dá)式寫成一個(gè):
server?{
??listen?80;
??server_name?localhost;
??location?/?{
????proxy_pass?http://192.168.33.10:8080;
??}
??
??location?~*/(css|js|img){
????root?html;
??}
}
URL Rewrite
這是京東商城關(guān)于手機(jī)方面的商品:
我們隨便點(diǎn)擊一個(gè)進(jìn)去觀察url:
你會發(fā)現(xiàn),對于每一個(gè)商品,都有一個(gè)html頁面與之對應(yīng),難道京東真的提供了這么多的html頁面嗎?可以想象一下京東有多少商品,要為每個(gè)商品提供一個(gè)html顯然是不可能的。事實(shí)上,它用的其實(shí)是URL Rewrite技術(shù),將url地址進(jìn)行了改寫,讓用戶看起來以為每個(gè)商品都是一個(gè)html頁面。配置如下:server?{
??listen?80;
??server_name?localhost;
??location?/?{
????rewrite?^/([0-9]+).html$?/shop?shopId=$1?break;
????proxy_pass?http://192.168.33.10:8080;
??}
}
重點(diǎn)來解讀一下這段配置:rewrite ^/([0-9]+).html$ /shop?shopId=$1 break;,首先^/([0-9]+).html$是正則匹配規(guī)則,也就是說以任意數(shù)字為前綴的.html頁面才能匹配成功,如:1.html、12121.html等;其次/shop?shopId=$1表示轉(zhuǎn)發(fā)到的地址,而$1表示引用第一個(gè)規(guī)則,如果寫$2就表示引用第二個(gè)規(guī)則,這里我們只寫了一個(gè)正則表達(dá)式規(guī)則;最后的break表示本條規(guī)則匹配成功后即結(jié)束,不再匹配后續(xù)的規(guī)則。
所以當(dāng)我們訪問http://192.168.33.10:8080/123.html時(shí),實(shí)際上的url地址是http://192.168.33.10:8080/shop?shopId=123。
? ? ?
往 期 推 薦
1、我在產(chǎn)品上線前不小心刪除了7 TB的視頻 2、程序員最硬大佬,你絕對想不到?。。?/span> 3、IntelliJ IDEA快捷鍵大全 + 動圖演示 4、打不過就加入?微軟強(qiáng)推“親兒子”上位,還是中國特供版 5、活久見!NVIDIA正式開源其Linux GPU內(nèi)核模塊 點(diǎn)分享
點(diǎn)收藏
點(diǎn)點(diǎn)贊
點(diǎn)在看





