
此文已同步到因卓誒博客:
Nginx:很正經(jīng)的學(xué)習(xí)筆記(一) - 因卓誒-愛(ài)分享愛(ài)原創(chuàng)的技術(shù)博客 ~ 個(gè)人博客www.yinzhuoei.comNginx是一款高性能服務(wù)器,最近這幾年非常火,以輕量且高并發(fā),高性能著稱,那么此筆記將不會(huì)從0開始講解API,而是會(huì)從各種問(wèn)題入手,通過(guò)問(wèn)題學(xué)習(xí)nginx。
特點(diǎn):
- IO多路復(fù)用
- 高性能
- 高并發(fā)
- 占用系統(tǒng)資源少

Nginx作為一個(gè)WEB服務(wù)器,有著大好的未來(lái),市場(chǎng)份額非常給力,同時(shí)也是份額上升速度最快的web服務(wù)器。

Nginx作為前端來(lái)說(shuō),需要學(xué)習(xí)什么?我們只需要學(xué)習(xí)Nginx在應(yīng)用部署,反向代理,處理資源的進(jìn)程,亦或者是搭建網(wǎng)站的基礎(chǔ)知識(shí),如果你還沒(méi)有一個(gè)blog,那么就從現(xiàn)在開始學(xué)習(xí)nginx并且搭建你的第一個(gè)網(wǎng)站吧。
反向代理與正向代理

我們?cè)谄綍r(shí)上外網(wǎng)的時(shí)候,比如谷歌,youtube,twitter,Ins等,如果使用我們內(nèi)地網(wǎng)絡(luò),是訪問(wèn)不成功的,只有在香港臺(tái)灣或者境外才能訪問(wèn)到類似的外網(wǎng)。那我們需要通過(guò)內(nèi)地網(wǎng)絡(luò)去訪問(wèn)外網(wǎng)只能通過(guò)一個(gè)proxy代理去做一個(gè)請(qǐng)求的轉(zhuǎn)發(fā),我們的內(nèi)地網(wǎng)絡(luò)請(qǐng)求在到達(dá)外網(wǎng)地址之前,會(huì)經(jīng)過(guò)一層代理,這個(gè)代理會(huì)去請(qǐng)求外網(wǎng),請(qǐng)求成功之后會(huì)把頁(yè)面呈現(xiàn)給我們的客戶端。
在這個(gè)過(guò)程中,外網(wǎng)服務(wù)器不知道我們的內(nèi)地網(wǎng)絡(luò)是誰(shuí),只知道代理地址,所以對(duì)于外網(wǎng)服務(wù)器來(lái)說(shuō),請(qǐng)求的真實(shí)客戶端是看不到的。那么這個(gè)過(guò)程就叫做 正向代理,proxy代理的是客戶端。

反向代理是相反的,代理的是服務(wù)端,對(duì)于客戶端而言,訪問(wèn)的服務(wù)器僅僅是多個(gè)真實(shí)服務(wù)器的一個(gè)代理而已,所以對(duì)于客戶端用戶而言,真實(shí)服務(wù)器的信息是不可見(jiàn)的。這樣的過(guò)程也就是反向代理,proxy代理的是服務(wù)端。
Nginx如何去做反向代理?
server{ listen 80; server_name nginx.yinzhuoei.com; location / { proxy_pass http://yinzhuoei.com; }}其他的proxy配置:
proxy_set_header :在將客戶端請(qǐng)求發(fā)送給后端服務(wù)器之前,更改來(lái)自客戶端的請(qǐng)求頭信息。proxy_connect_timeout:配置Nginx與后端代理服務(wù)器嘗試建立連接的超時(shí)時(shí)間。proxy_read_timeout : 配置Nginx向后端服務(wù)器組發(fā)出read請(qǐng)求后,等待相應(yīng)的超時(shí)時(shí)間。proxy_send_timeout:配置Nginx向后端服務(wù)器組發(fā)出write請(qǐng)求后,等待相應(yīng)的超時(shí)時(shí)間。proxy_redirect :用于修改后端服務(wù)器返回的響應(yīng)頭中的Location和Refresh。解決跨域
通過(guò)反向代理解決跨域:
server{ listen 3003; server_name localhost; ## = /表示精確匹配路徑為/的url location = / { proxy_pass http://localhost:5500; } ## 若 proxy_pass最后為/ 如http://localhost:3000/;匹配/no/son,則真實(shí)匹配為http://localhost:3000/son location /no { proxy_pass http://localhost:3000; } ## /ok/表示精確匹配以ok開頭的url,/ok2是匹配不到的,/ok/son則可以 location /ok/ { proxy_pass http://localhost:3000; }}加header頭允許跨域:
server{ listen 3002; server_name localhost; location /ok { proxy_pass http://localhost:3000; # 指定允許跨域的方法,*代表所有 add_header Access-Control-Allow-Methods *; # 預(yù)檢命令的緩存,如果不緩存每次會(huì)發(fā)送兩次請(qǐng)求 add_header Access-Control-Max-Age 3600; # 帶cookie請(qǐng)求需要加上這個(gè)字段,并設(shè)置為true add_header Access-Control-Allow-Credentials true; # 表示允許這個(gè)域跨域調(diào)用(客戶端發(fā)送請(qǐng)求的域名和端口) # $http_origin動(dòng)態(tài)獲取請(qǐng)求客戶端請(qǐng)求的域 不用*的原因是帶cookie的請(qǐng)求不支持*號(hào) add_header Access-Control-Allow-Origin $http_origin; # 表示請(qǐng)求頭的字段 動(dòng)態(tài)獲取 add_header Access-Control-Allow-Headers $http_access_control_request_headers; # OPTIONS預(yù)檢命令,預(yù)檢命令通過(guò)時(shí)才發(fā)送請(qǐng)求 # 檢查請(qǐng)求的類型是不是預(yù)檢命令 if ($request_method = OPTIONS){ return 200; } }}Master&Woker模式
Nginx啟動(dòng)之后,啟動(dòng)了80端口進(jìn)行服務(wù)監(jiān)聽(tīng),那么進(jìn)程中就存在一個(gè)Mater主進(jìn)程和多個(gè)Woker進(jìn)程;

Master進(jìn)程的作用就是:讀取&驗(yàn)證nginx.conf配置文件并且管理多個(gè)woker進(jìn)程;接受外部信號(hào);監(jiān)控Woker,如果Woker掛掉,將自動(dòng)重啟Woker;
Woker進(jìn)程的作用就是:多個(gè)Woker會(huì)攔截所有的請(qǐng)求并做出處理;每一個(gè)woker進(jìn)程維護(hù)一個(gè)線程;woker的個(gè)數(shù)和CPU有關(guān),從nginx.conf配置woker個(gè)數(shù),配置幾個(gè)就是幾個(gè),但是要避免配置過(guò)多,要充分利用CPU;
一個(gè)請(qǐng)求到響應(yīng)的流程:
- Nginx啟動(dòng),Matster進(jìn)程根據(jù)nginx.conf初始化;初始化監(jiān)聽(tīng)socket;fork出多個(gè)woker進(jìn)程;
- 發(fā)起請(qǐng)求
- woker進(jìn)程們一起競(jìng)爭(zhēng),勝出者通過(guò)三次握手,建立socket連接,處理請(qǐng)求。
如何做熱部署呢?
熱部署就和前端熱部署一樣的性質(zhì),即修改配置文件,不需要重啟服務(wù)器就可以使用最新的配置。
通過(guò)這樣的一個(gè)命令即可熱部署,無(wú)需重啟,隨時(shí)改隨時(shí)用。
一般情況下,我們做熱部署可以有幾個(gè)方案,比如前端,webpack的本地開發(fā)工具,webpack-dev-server,即本地啟動(dòng)一個(gè)服務(wù),開啟一個(gè)websocket,當(dāng)我們的文件改動(dòng),就重新加載這個(gè)css/js。
而nginx也是同樣的方式么?我們的主進(jìn)程master去發(fā)布一個(gè)修改請(qǐng)求,然后woker去訂閱這個(gè)消息,實(shí)現(xiàn)類似這樣的熱部署?
其實(shí)不然,nginx使用的是如下的方案,當(dāng)master監(jiān)聽(tīng)到配置文件的更改,會(huì)創(chuàng)建一批新的woker去執(zhí)行新的請(qǐng)求,老的woker進(jìn)程會(huì)在任務(wù)處理完畢之后,再由master殺掉進(jìn)程。
如何做到高并發(fā)?
Nginx采用多進(jìn)程+異步非阻塞方式(IO多路復(fù)用):
關(guān)于異步和同步,我需要做一些概念上的整理;
同步和異步指的是消息的通信機(jī)制,我們做web開發(fā)是最能理解同步異步的區(qū)別的,因?yàn)槲覀兲焯旌徒涌诖蚪坏溃?/p>
1)所謂同步指的就是發(fā)起一個(gè)請(qǐng)求/調(diào)用,在沒(méi)有得到結(jié)果之前就不會(huì)返回,一旦得到結(jié)果就立即返回;
2)所謂異步指的就是發(fā)起一個(gè)請(qǐng)求/調(diào)用,調(diào)用者不會(huì)主動(dòng)去care被調(diào)用者,而被調(diào)用者拿到結(jié)果之后會(huì)通知調(diào)用者
而阻塞非阻塞指的是程序在等待調(diào)用結(jié)果時(shí)的狀態(tài);
1)阻塞調(diào)用指的就是,結(jié)果返回之前當(dāng)前線程被掛起,調(diào)用線程在返回之后才返回;那么掛起的這個(gè)線程是會(huì)被阻塞的;
2)非阻塞調(diào)用指的就是,不能立刻得到結(jié)果之前,線程是不會(huì)被掛起的,仍然可以做其他事情;那么非阻塞調(diào)用如何知道得到結(jié)果了呢,需要定時(shí)去check的;
關(guān)于阻塞IO和非阻塞IO等我總結(jié)完了再說(shuō)哈,還有關(guān)于Nginx的IO多路復(fù)用Epoll模型,這個(gè)是延申知識(shí)了,我也需要學(xué)習(xí)整理哈,現(xiàn)在還不清楚這一塊的東西。
Nginx后續(xù)章節(jié)過(guò)段時(shí)間發(fā),中間要發(fā)幾篇shadowDom和劍指題解的文章,大家耐心等待...
學(xué)習(xí)資料如下: