前端的Nginx知識(shí)梳理
本文已獲得原作者的獨(dú)家授權(quán),有想轉(zhuǎn)載的朋友們可以在后臺(tái)聯(lián)系我申請(qǐng)開白哦! PS:歡迎掘友們向我投稿哦,被采用的文章還可以送你掘金精美周邊!
因?yàn)殚_發(fā)中有很多環(huán)境,開發(fā)環(huán)境,測(cè)試環(huán)境,預(yù)生產(chǎn)環(huán)境等,所以會(huì)經(jīng)常會(huì)用到 nginx 來配置代理。但是我也只是會(huì)用,想仔細(xì)梳理一下 nginx 的知識(shí)。
1. 什么是 Nginx
Nginx (engine x) 是一個(gè)高性能的 HTTP 和反向代理 web 服務(wù)器。
Nginx 以事件驅(qū)動(dòng)的方式編寫,所以有非常好的性能,同時(shí)也是一個(gè)非常高效的反向代理、負(fù)載平衡服務(wù)器。在性能上,Nginx 占用很少的系統(tǒng)資源,能支持更多的并發(fā)連接,達(dá)到更高的訪問效率;在功能上,Nginx 是優(yōu)秀的代理服務(wù)器和負(fù)載均衡服務(wù)器;在安裝配置上,Nginx 安裝簡單、配置靈活。
Nginx 支持熱部署,啟動(dòng)速度特別快,還可以在不間斷服務(wù)的情況下對(duì)軟件版本或配置進(jìn)行升級(jí),即使運(yùn)行數(shù)月也無需重新啟動(dòng)。
在微服務(wù)的體系之下,Nginx 正在被越來越多的項(xiàng)目采用作為網(wǎng)關(guān)來使用,配合 Lua 做限流、熔斷等控制。

這里提到了反向代理,什么是反向代理?
Nginx 根據(jù)接收到的請(qǐng)求的端口,域名,url,將請(qǐng)求轉(zhuǎn)發(fā)給不同的機(jī)器,不同的端口(或直接返回結(jié)果),然后將返回的數(shù)據(jù)返回給客戶端。
在 Java 設(shè)計(jì)模式中,代理模式是這樣定義的:給某個(gè)對(duì)象提供一個(gè)代理對(duì)象,并由代理對(duì)象控制原對(duì)象的引用。
反向代理: 客戶端 一 > 代理 <一> 服務(wù)端
反向代理用一個(gè)租房的例子:
A(客戶端) 想租一個(gè)房子, B(代理) 就把這個(gè)房子租給了他。
這時(shí)候?qū)嶋H上 C(服務(wù)端) 才是房東。
B(代理) 是中介把這個(gè)房子租給了 A(客戶端)。
這個(gè)過程中 A(客戶端) 并不知道這個(gè)房子到底誰才是房東
他都有可能認(rèn)為這個(gè)房子就是 B(代理) 的
反向代理特點(diǎn)
Nginx 沒有自己的地址,它的地址就是服務(wù)器的地址,如 www.baidu.com,對(duì)外部來講,它就是數(shù)據(jù)的生產(chǎn)者。 Ngxin 明確的知道應(yīng)該去哪個(gè)服務(wù)器獲取數(shù)據(jù)(在未接收到請(qǐng)求之前,已經(jīng)確定應(yīng)該連接哪臺(tái)服務(wù)器)
有反向就應(yīng)該有正向。
所謂正向代理就是順著請(qǐng)求的方向進(jìn)行的代理,即代理服務(wù)器他是由你配置為你服務(wù),去請(qǐng)求目標(biāo)服務(wù)器地址。正向代理最大的特點(diǎn)是客戶端非常明確要訪問的服務(wù)器地址;服務(wù)器只清楚請(qǐng)求來自哪個(gè)代理服務(wù)器,而不清楚來自哪個(gè)具體的客戶端;正向代理模式屏蔽或者隱藏了真實(shí)客戶端信息
正向代理: 客戶端 <一> 代理 一 > 服務(wù)端
正向代理也簡單地打個(gè)租房的比方:
A(客戶端) 想租 C(服務(wù)端) 的房子, 但是 A(客戶端) 并不認(rèn)識(shí) C(服務(wù)端) 租不到。
B(代理) 認(rèn)識(shí) C(服務(wù)端) 能租這個(gè)房子所以你找了 B(代理) 幫忙租到了這個(gè)房子。
這個(gè)過程中 C(服務(wù)端) 不認(rèn)識(shí) A(客戶端) 只認(rèn)識(shí) B(代理)
C(服務(wù)端) 并不知道 A(客戶端) 租了房子,只知道房子租給了 B(代理)。

2.? Nginx 應(yīng)用場(chǎng)景
1、 http 服務(wù)器。Nginx 是一個(gè) http 服務(wù)可以獨(dú)立提供 http 服務(wù)??梢宰鼍W(wǎng)頁靜態(tài)服務(wù)器。
2、 虛擬主機(jī)??梢詫?shí)現(xiàn)在一臺(tái)服務(wù)器虛擬出多個(gè)網(wǎng)站。例如個(gè)人網(wǎng)站使用的虛擬主機(jī)。
基于端口的,不同的端口 基于域名的,不同域名
3、 反向代理,負(fù)載均衡。當(dāng)網(wǎng)站的訪問量達(dá)到一定程度后,單臺(tái)服務(wù)器不能滿足用戶的請(qǐng)求時(shí),需要用多臺(tái)服務(wù)器集群可以使用 nginx 做反向代理。并且多臺(tái)服務(wù)器可以平均分擔(dān)負(fù)載,不會(huì)因?yàn)槟撑_(tái)服務(wù)器負(fù)載高宕機(jī)而某臺(tái)服務(wù)器閑置的情況。
3. 安裝 Nginx
blog.s135.com/nginx_php_v…

4. 命令
nginx?-s?reopen?#重啟Nginx
nginx?-s?reload?#重新加載Nginx配置文件,然后以優(yōu)雅的方式重啟Nginx
nginx?-s?stop?#強(qiáng)制停止Nginx服務(wù)
nginx?-s?quit?#優(yōu)雅地停止Nginx服務(wù)(即處理完所有請(qǐng)求后再停止服務(wù))
nginx?-?,-h?#打開幫助信息
nginx?-v?#顯示版本信息并退出
nginx?-V?#顯示版本和配置選項(xiàng)信息,然后退出
nginx?-t?#檢測(cè)配置文件是否有語法錯(cuò)誤,然后退出
nginx?-T?#檢測(cè)配置文件是否有語法錯(cuò)誤,轉(zhuǎn)儲(chǔ)并退出
nginx?-q?#在檢測(cè)配置文件期間屏蔽非錯(cuò)誤信息
nginx?-p?prefix?#設(shè)置前綴路徑(默認(rèn)是:/usr/share/nginx/)nginx?-c?filename?#設(shè)置配置文件(默認(rèn)是:/etc/nginx/nginx.conf)
nginx?-g?directives?#設(shè)置配置文件外的全局指令
killall?nginx?#殺死所有nginx進(jìn)程
轉(zhuǎn)儲(chǔ): 在內(nèi)存、CPU、I/O 等設(shè)備上的數(shù)據(jù)都是動(dòng)態(tài)的(或者說是易失的),也就是說數(shù)據(jù)使用完或者發(fā)生異常就會(huì)丟掉。如果我想得到某些時(shí)刻的數(shù)據(jù)(有可能是調(diào)試程序 Bug 或者收集某些信息),就要把他轉(zhuǎn)儲(chǔ)(dump)為靜態(tài)(如文件)的形式。否則,這些數(shù)據(jù)你永遠(yuǎn)都拿不到。
5. Nginx 配置
Nginx 的主配置文件是:nginx.conf。

里面的配置主要是這樣:
#?全局區(qū)???有一個(gè)工作子進(jìn)程,一般設(shè)置為CPU數(shù)?*?核數(shù)
????????worker_processes??1;
????????events?{
????????????????#?一般是配置nginx進(jìn)程與連接的特性
????????????????#?如1個(gè)word能同時(shí)允許多少連接,一個(gè)子進(jìn)程最大允許連接1024個(gè)連接
????????????????worker_connections??1024;
????????}
????????#?配置HTTP服務(wù)器配置段
????????http?{
????????????????#?配置虛擬主機(jī)段
????????????????????server?{
????????????????????????#?定位,把特殊的路徑或文件再次定位。
????????????????location??{
????????????????}
????????????}
????????????server?{
???????????????????????...
????????????}
????????}
我們可以很明顯的將 nginx.conf 配置文件分為三部分:
全局塊:?從配置文件開始到 events 塊之間的內(nèi)容,主要會(huì)設(shè)置一些影響 nginx 服務(wù)器整體運(yùn)行的配置指令,主要包括配置運(yùn)行 Nginx 服務(wù)器的用戶(組)、允許生成的 worker process 數(shù),進(jìn)程 PID 存放路徑、日志存放路徑和類型以及配置文件的引入等。
比如上面第一行配置的:
worker_processes??1;
這是 Nginx 服務(wù)器并發(fā)處理服務(wù)的關(guān)鍵配置,worker_processes 值越大,可以支持的并發(fā)處理量也越多,但是會(huì)受到硬件、軟件等設(shè)備的制約。
events 塊: 涉及的指令主要影響 Nginx 服務(wù)器與用戶的網(wǎng)絡(luò)連接,常用的設(shè)置包括是否開啟對(duì)多 work process 下的網(wǎng)絡(luò)連接進(jìn)行序列化,是否允許同時(shí)接收多個(gè)網(wǎng)絡(luò)連接,選取哪種事件驅(qū)動(dòng)模型來處理連接請(qǐng)求,每個(gè) word process 可以同時(shí)支持的最大連接數(shù)等。
http 塊: Nginx 服務(wù)器配置中最頻繁的部分,代理、緩存和日志定義等絕大多數(shù)功能和第三方模塊的配置都在這里。
6. 反向代理
上面已經(jīng)解釋過反向代理了,我們現(xiàn)在來寫一個(gè)。當(dāng)我在公司配置反向代理的時(shí)候,我會(huì)在 http 中添加一個(gè) server:
??????server?{
????????listen????????????80;
????????server_name???????dev-customer.sdyxmall.com?;
????????gzip??????????????off;
????????gzip_buffers??????4?16k;
????????gzip_comp_level???5;
????????gzip_http_version?1.0;
????????gzip_min_length???1k;
????????gzip_types????????text/plain?text/css?application/javascript?application/x-javascript?text/xml?application/xml?application/xml+rss?text/javascript?image/x-icon?image/bmp;
????????gzip_vary?????????on;
????????location?/?{
???????????proxy_pass???http://127.0.0.1:5000;
???????????proxy_set_header?X-real-ip?$remote_addr;
???????????proxy_set_header??X-Forwarded-For?$proxy_add_x_forwarded_for;
???????????proxy_set_header?Host?$host;
????????}
????}
然后 hosts 中配置:

10.3.100.13?dev-customer.sdyxmall.com
接下來我們梳理一下語法:
1?listen?*:80?|?*:8080?#監(jiān)聽所有80端口和8080端口
2?listen??IP_address:port???#監(jiān)聽指定的地址和端口號(hào)
3?listen??IP_address?????#監(jiān)聽指定ip地址所有端口
4?listen?port?????#監(jiān)聽該端口的所有IP連接
server_name 指令主要用于配置基于名稱虛擬主機(jī)
gzip 的作用是是否需要開啟壓縮傳輸
location 指令用于匹配 URL
proxy_pass 指令用于設(shè)置被代理服務(wù)器的地址
proxy_set_header 用來設(shè)定被代理服務(wù)器接收到的 header 信息(請(qǐng)求頭)
基本上我們了解 server_name,location,proxy_pass 就可以配置反向代理
7.Nginx 管理虛擬主機(jī)
這部分我工作中沒有接觸過,但是查找資料的時(shí)候名字看起來很高大上,就特意研究了一下。當(dāng)我們想在一臺(tái)服務(wù)器虛擬出多個(gè)網(wǎng)站,我們就可以用虛擬主機(jī)來實(shí)現(xiàn)。
虛擬主機(jī)使用的是特殊的軟硬件技術(shù),它把一臺(tái)運(yùn)行在因特網(wǎng)上的服務(wù)器主機(jī)分成一臺(tái)臺(tái) “虛擬” 的主機(jī),每臺(tái)虛擬主機(jī)都可以是一個(gè)獨(dú)立的網(wǎng)站,可以具有獨(dú)立的域名,具有完整的 Intemet 服務(wù)器功能(WWW、FTP、Email 等),同一臺(tái)主機(jī)上的虛擬主機(jī)之間是完全獨(dú)立的。從網(wǎng)站訪問者來看,每一臺(tái)虛擬主機(jī)和一臺(tái)獨(dú)立的主機(jī)完全一樣。
7.1 基于域名的虛擬主機(jī)
1、在 http 大括號(hào)中添加如下代碼段:
server?{??
????????#監(jiān)聽端口?80??
????????listen?80;???
????????????????????????????????
????????#監(jiān)聽域名feng.com;??
????????server_name?feng.com;
??????????
????????location?/?{??????????????
????????????????#?相對(duì)路徑,相對(duì)nginx根目錄。也可寫成絕對(duì)路徑??
????????????root????feng;??
????????????
????????????#?默認(rèn)跳轉(zhuǎn)到index.html頁面??
????????????index?index.html;?????????????????
????????}??
????}
2、切換安裝目錄:cd/usr/local/software/nginx
3、創(chuàng)建目錄:mkdir feng
4、新建 index.html 文件:vi /usr/local/software/nginx/feng/index.html,文件內(nèi)容:
????????
????????????"Content-Type"?content="text/html;?charset=UTF-8"?/>
????????
????????
????????????楓
????????
????
5、重新讀取配置文件:
/usr/local/software/nginx/sbin/nginx-s reload
kill -HUP 進(jìn)程號(hào)
6、配置 windows 本機(jī) host:
192.168.197.142 feng.com #Linux[1] 服務(wù)器 IP 地址
7、訪問:http://feng.com:80/
7.2 基于端口的虛擬主機(jī)配置
server?{
????????listen??2022;
????????server_name?????feng.com;
????????location?/?{
???????????root????/home;
???????????index?index.html;
????????}
????}
7.3 基于 IP 地址虛擬主機(jī)配置
????server?{
??????listen??80;
??????server_name??192.168.197.142;
??????location?/?{
??????????????root????ip;
??????????????index?index.html;
??????}
????}
8. 負(fù)載均衡
我們使用 Nginx 聽到的最多的就是負(fù)載均衡,那么什么是負(fù)載均衡呢?
** 負(fù)載均衡:** 由于目前現(xiàn)有網(wǎng)絡(luò)的各個(gè)核心部分隨著業(yè)務(wù)量的提高,訪問量和數(shù)據(jù)流量的快速增長,其處理能力和計(jì)算強(qiáng)度也相應(yīng)地增大,使得單一的服務(wù)器設(shè)備根本無法承擔(dān)。
針對(duì)此情況而衍生出來的一種廉價(jià)有效透明的方法以擴(kuò)展現(xiàn)有網(wǎng)絡(luò)設(shè)備和服務(wù)器的帶寬、增加吞吐量、加強(qiáng)網(wǎng)絡(luò)數(shù)據(jù)處理能力、提高網(wǎng)絡(luò)的靈活性和可用性的技術(shù)就是負(fù)載均衡(Load Balance)。
Nginx 實(shí)現(xiàn)負(fù)載均衡有幾種方案。
8.1 輪詢
輪詢即 Round Robin,根據(jù) Nginx 配置文件中的順序,依次把客戶端的 Web 請(qǐng)求分發(fā)到不同的后端服務(wù)器。
upstream?backserver?{
????server?192.168.0.14;
????server?192.168.0.15;
}
8.2 weight
基于權(quán)重的負(fù)載均衡即 Weighted Load Balancing,這種方式下,我們可以配置 Nginx 把請(qǐng)求更多地分發(fā)到高配置的后端服務(wù)器上,把相對(duì)較少的請(qǐng)求分發(fā)到低配服務(wù)器。
upstream?backserver?{
????server?192.168.0.14?weight=3;
????server?192.168.0.15?weight=7;
}
權(quán)重越高,在被訪問的概率越大,如上例,分別是 30%,70%。
8.3 ip_hash
前述的兩種負(fù)載均衡方案中,同一客戶端連續(xù)的 Web 請(qǐng)求可能會(huì)被分發(fā)到不同的后端服務(wù)器進(jìn)行處理,因此如果涉及到會(huì)話 Session,那么會(huì)話會(huì)比較復(fù)雜。常見的是基于數(shù)據(jù)庫的會(huì)話持久化。要克服上面的難題,可以使用基于 IP 地址哈希的負(fù)載均衡方案。這樣的話,同一客戶端連續(xù)的 Web 請(qǐng)求都會(huì)被分發(fā)到同一服務(wù)器進(jìn)行處理。
upstream?backserver?{
????ip_hash;
????server?192.168.0.14:88;
????server?192.168.0.15:80;
}
8.4 fair
按后端服務(wù)器的響應(yīng)時(shí)間來分配請(qǐng)求,響應(yīng)時(shí)間短的優(yōu)先分配。
upstream?backserver?{
????server?server1;
????server?server2;
????fair;
}
8.5 url_hash
按訪問 url 的 hash 結(jié)果來分配請(qǐng)求,使每個(gè) url 定向到同一個(gè)(對(duì)應(yīng)的)后端服務(wù)器,后端服務(wù)器為緩存時(shí)比較有效。
upstream?backserver?{
????server?squid1:3128;
????server?squid2:3128;
????hash?$request_uri;
????hash_method?crc32;
}
在需要使用負(fù)載均衡的 server 中增加
proxy_pass?http://backserver/;?
upstream?backserver{?
????ip_hash;?
????server?127.0.0.1:9090?down;?(down?表示單前的server暫時(shí)不參與負(fù)載)?
????server?127.0.0.1:8080?weight=2;?(weight?默認(rèn)為1.weight越大,負(fù)載的權(quán)重就越大)?
????server?127.0.0.1:6060;?
????server?127.0.0.1:7070?backup;?(其它所有的非backup機(jī)器down或者忙的時(shí)候,請(qǐng)求backup機(jī)器)?
}?
max_fails :允許請(qǐng)求失敗的次數(shù)默認(rèn)為 1. 當(dāng)超過最大次數(shù)時(shí),返回 proxy_next_upstream 模塊定義的錯(cuò)誤。
fail_timeout:max_fails 次失敗后,暫停的時(shí)間。
配置實(shí)例:
#user??nobody;
worker_processes??4;
events?{
#?最大并發(fā)數(shù)
worker_connections??1024;
}
http{
????#?待選服務(wù)器列表
????upstream?myproject{
????????# ip_hash指令,將同一用戶引入同一服務(wù)器。
????????ip_hash;
????????server?125.219.42.4?fail_timeout=60s;
????????server?172.31.2.183;
????}
????server{
????????#?監(jiān)聽端口
????????listen?80;
????????#?根目錄下
????????location?/?{
????????#?選擇哪個(gè)服務(wù)器列表
????????????proxy_pass?http://myproject;
????????}
????}
}
8.6 深入實(shí)踐
上面寫的都是負(fù)載均衡的方案,具體實(shí)現(xiàn)我看到知乎大佬寫的很不錯(cuò),而且看起來帥的起飛。
地址:zhuanlan.zhihu.com/p/32122459
9. 總結(jié)
Nginx 真的很強(qiáng)大,而且使用的越來越廣泛,雖然我目前在公司使用的不多,但是學(xué)到了 Nginx 很多知識(shí),對(duì)項(xiàng)目的構(gòu)建,優(yōu)化,心里有了更多的想法?;蛟S不一定要了解的很深入,滿足我們的日常需要就可以了,了解它,當(dāng)我們?cè)谧鲰?xiàng)目或者解決問題,能夠作為我們的一種解決方案,就很 Nice 了。
參考資料
Linux知識(shí)庫: http://lib.csdn.net/base/linux
