nginx基本原理介绍
目錄
代理與反向代理
代理服務(wù)器的作用
反向代理服務(wù)器的作用
nginx的作用
nginx的工作過(guò)程
nginx的事件驅(qū)動(dòng)機(jī)制
epoll庫(kù)
nginx的詳細(xì)配置
代理與反向代理
代理服務(wù)器是位于客戶端和原始服務(wù)器的一臺(tái)中間服務(wù)器,為了從原始服務(wù)器獲取到內(nèi)容,客戶端向代理服務(wù)器發(fā)送一個(gè)請(qǐng)求并帶上目標(biāo)服務(wù)器(原始服務(wù)器),代理服務(wù)器在接收到請(qǐng)求后就會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給原始服務(wù)器,并將從原始服務(wù)器上獲取到的數(shù)據(jù)返回給客戶端,代理服務(wù)器是代理的客戶端,所以一般客戶端是知道代理服務(wù)器的存在的,比如翻墻就用了代理服務(wù)器。
反向代理服務(wù)器是位于原始服務(wù)器端的服務(wù)器,反向代理服務(wù)器接受來(lái)自互聯(lián)網(wǎng)的請(qǐng)求,然后將這些請(qǐng)求發(fā)送給內(nèi)網(wǎng)的服務(wù)器,并將從內(nèi)網(wǎng)的服務(wù)器獲取結(jié)果返回給互聯(lián)網(wǎng)上的客戶端,反向代理服務(wù)器是代理的服務(wù)端,所以客戶端是不知道反向代理服務(wù)器的存在的,服務(wù)端是知道反向代理服務(wù)器的。
代理服務(wù)器的作用
1. 訪問(wèn)原來(lái)無(wú)法訪問(wèn)的資源?
2. 用作緩存,加速訪問(wèn)速度?
3. 對(duì)客戶端訪問(wèn)授權(quán),上網(wǎng)進(jìn)行認(rèn)證?
4. 代理可以記錄用戶訪問(wèn)記錄(上網(wǎng)行為管理),對(duì)外隱藏用戶信息
反向代理服務(wù)器的作用
1. 保護(hù)內(nèi)網(wǎng)安全?
2. 負(fù)載均衡?
3. 緩存,減少服務(wù)器的壓力?
nginx的作用
1.反向代理,將多臺(tái)服務(wù)器代理成一臺(tái)服務(wù)器
2.負(fù)載均衡,將多個(gè)請(qǐng)求均勻的分配到多臺(tái)服務(wù)器上,減輕每臺(tái)服務(wù)器的壓力,提高服務(wù)的吞吐量
3.動(dòng)靜分離,nginx可以用作靜態(tài)文件的緩存服務(wù)器,提高訪問(wèn)速度
nginx的工作過(guò)程
1.在nginx啟動(dòng)后,會(huì)有一個(gè)master進(jìn)程和多個(gè)worker進(jìn)程,master進(jìn)程主要用來(lái)管理worker進(jìn)程,包括:接受信號(hào),將信號(hào)分發(fā)給worker進(jìn)程,監(jiān)聽(tīng)worker進(jìn)程工作狀態(tài),當(dāng)worker進(jìn)程退出時(shí)(非正常),啟動(dòng)新的worker進(jìn)程?;镜木W(wǎng)絡(luò)事件會(huì)交給worker進(jìn)程處理。多個(gè)worker進(jìn)程之間是對(duì)等的,他們同等競(jìng)爭(zhēng)來(lái)自客戶端的請(qǐng)求,各進(jìn)程互相之間是獨(dú)立的?。一個(gè)請(qǐng)求,只可能在一個(gè)worker進(jìn)程中處理,一個(gè)worker進(jìn)程,不可能處理其它進(jìn)程的請(qǐng)求。?worker進(jìn)程的個(gè)數(shù)是可以設(shè)置的,一般我們會(huì)設(shè)置與機(jī)器cpu核數(shù)一致,這里面的原因與nginx的進(jìn)程模型以及事件處理模型是分不開(kāi)的?。
2.當(dāng)master接收到重新加載的信號(hào)會(huì)怎么處理(./nginx -s reload)?,master會(huì)重新加載配置文件,然后啟動(dòng)新的進(jìn)程,使用的新的worker進(jìn)程來(lái)接受請(qǐng)求,并告訴老的worker進(jìn)程他們可以退休了,老的worker進(jìn)程將不會(huì)接受新的,老的worker進(jìn)程處理完手中正在處理的請(qǐng)求就會(huì)退出。
3.worker進(jìn)程是如何處理用戶的請(qǐng)求呢?首先master會(huì)根據(jù)配置文件生成一個(gè)監(jiān)聽(tīng)相應(yīng)端口的socket,然后再faster出多個(gè)worker進(jìn)程,這樣每個(gè)worker就可以接受從socket過(guò)來(lái)的消息(其實(shí)這個(gè)時(shí)候應(yīng)該是每一個(gè)worker都有一個(gè)socket,只是這些socket監(jiān)聽(tīng)的地址是一樣的)。當(dāng)一個(gè)連接過(guò)來(lái)的時(shí)候,每一個(gè)worker都能接收到通知,但是只有一個(gè)worker能和這個(gè)連接建立關(guān)系,其他的worker都會(huì)連接失敗,這就是所謂的驚群現(xiàn)在,為了解決這個(gè)問(wèn)題,nginx提供一個(gè)共享鎖accept_mutex,有了這個(gè)共享鎖后,就會(huì)只有一個(gè)worker去接收這個(gè)連接。當(dāng)一個(gè)worker進(jìn)程在accept這個(gè)連接之后,就開(kāi)始讀取請(qǐng)求,解析請(qǐng)求,處理請(qǐng)求,產(chǎn)生數(shù)據(jù)后,再返回給客戶端,最后才斷開(kāi)連接,這樣一個(gè)完整的請(qǐng)求就是這樣的了。
nginx的事件驅(qū)動(dòng)機(jī)制
為什么幾個(gè)worker進(jìn)程(每一個(gè)worker進(jìn)程里面其實(shí)只有一個(gè)主線程)能同時(shí)接收上萬(wàn)的請(qǐng)求呢?這是因?yàn)閚ginx事件處理機(jī)制是異步非阻塞的。nginx將一個(gè)請(qǐng)求劃分為多個(gè)階段來(lái)異步處理模塊,每個(gè)階段只是處理請(qǐng)求的一部分,如果請(qǐng)求的這一部分發(fā)生阻塞,nginx不會(huì)等待,它會(huì)處理其他的請(qǐng)求的某一部分。傳統(tǒng)web服務(wù)器的每個(gè)事件消費(fèi)者獨(dú)占一個(gè)進(jìn)程(線程)資源,這種情況對(duì)于用戶規(guī)模較小的情況來(lái)說(shuō),用戶響應(yīng)速度快,但是當(dāng)并發(fā)規(guī)模達(dá)到數(shù)十萬(wàn)上百萬(wàn)的時(shí)候,由于線程(進(jìn)程)數(shù)目過(guò)多,會(huì)頻繁的切換,而且當(dāng)線程阻塞的時(shí)候會(huì)進(jìn)行睡眠,也會(huì)造成資源的浪費(fèi),這樣服務(wù)器就會(huì)產(chǎn)生瓶頸.
? ? nginx服務(wù)器采用的事件驅(qū)動(dòng)機(jī)制不同,他不會(huì)為每個(gè)消費(fèi)事件創(chuàng)建一個(gè)進(jìn)程或線程,這樣就不會(huì)產(chǎn)生由于進(jìn)程間頻繁切換占用cpu而產(chǎn)生的瓶頸,而且nginx不會(huì)讓事件阻塞,即采用無(wú)阻塞事件驅(qū)動(dòng)模型,這樣就不會(huì)因?yàn)槭录枞惯M(jìn)程睡眠而造成的資源浪費(fèi).
? ? ?nginx將一個(gè)請(qǐng)求劃分成多個(gè)階段異步處理,每個(gè)階段僅僅完成一個(gè)請(qǐng)求中的一部分,當(dāng)本階段任務(wù)完成后進(jìn)入下一階段.等待事件發(fā)生不是阻塞的等待,等待事件發(fā)生時(shí)候內(nèi)。
事件發(fā)生源產(chǎn)生事件->事件收集器來(lái)收集分發(fā)事件(選擇自己感興趣的)->消費(fèi)事件.
epoll庫(kù)
? ? epoll庫(kù)是Nginx服務(wù)器支持的高性能事件驅(qū)動(dòng)庫(kù)之一。它是公認(rèn)的最好的事件驅(qū)動(dòng)模型。和poll庫(kù)及select庫(kù)有很大的區(qū)別。
? ? poll和select都是創(chuàng)建一個(gè)待處理事件列表,然后把這個(gè)列表發(fā)給內(nèi)核,返回的時(shí)候,再去輪詢檢查這個(gè)列表。以判斷這個(gè)事件是否發(fā)生。在描述符太多的情況下,就會(huì)明顯效率低下了。
? ? epoll是這么做的,它把事件描述符列表的管理交給內(nèi)核復(fù)制。一旦有某個(gè)事件發(fā)生,內(nèi)核將發(fā)生事件的事件描述符交給Nginx的進(jìn)程,而不是將整個(gè)事件描述符列表交給進(jìn)程,讓進(jìn)程去輪詢具體是哪個(gè)描述符。epoll()避免了輪詢整個(gè)事件描述符列表。所以顯得更高效。
? ? epoll庫(kù)的基本步驟:
? ? 首先:epoll庫(kù)通過(guò)相關(guān)調(diào)用通知內(nèi)核創(chuàng)建一個(gè)有N個(gè)描述符的事件列表。然后給這個(gè)事件列表設(shè)置自己關(guān)心的事件。并把它添加到內(nèi)核中。在具體的代碼中還可以實(shí)現(xiàn)對(duì)相關(guān)調(diào)用的事件描述符列表進(jìn)行修改和刪除。
? ? 之后,一旦設(shè)置完成就一直等待內(nèi)核通知事件發(fā)生了,某一事件發(fā)生后,內(nèi)核就將發(fā)生事件的描述符給epoll庫(kù),epoll庫(kù)去處理事件。
nginx的詳細(xì)配置
1、全局塊:配置影響nginx全局的指令。一般有運(yùn)行nginx服務(wù)器的用戶組,nginx進(jìn)程pid存放路徑,日志存放路徑,配置文件引入,允許生成worker process數(shù)等。
2、events塊:配置影響nginx服務(wù)器或與用戶的網(wǎng)絡(luò)連接。有每個(gè)進(jìn)程的最大連接數(shù),選取哪種事件驅(qū)動(dòng)模型處理連接請(qǐng)求,是否允許同時(shí)接受多個(gè)網(wǎng)路連接,開(kāi)啟多個(gè)網(wǎng)絡(luò)連接序列化等。
3、http塊:可以嵌套多個(gè)server,配置代理,緩存,日志定義等絕大多數(shù)功能和第三方模塊的配置。如文件引入,mime-type定義,日志自定義,是否使用sendfile傳輸文件,連接超時(shí)時(shí)間,單連接請(qǐng)求數(shù)等。
4、server塊:配置虛擬主機(jī)的相關(guān)參數(shù),一個(gè)http中可以有多個(gè)server。
5、location塊:配置請(qǐng)求的路由,以及各種頁(yè)面的處理情況
########### 每個(gè)指令必須有分號(hào)結(jié)束。################# #user administrator administrators; #配置用戶或者組,默認(rèn)為nobody nobody。 #worker_processes 2; #允許生成的進(jìn)程數(shù),默認(rèn)為1 #pid /nginx/pid/nginx.pid; #指定nginx進(jìn)程運(yùn)行文件存放地址 error_log log/error.log debug; #制定日志路徑,級(jí)別。這個(gè)設(shè)置可以放入全局塊,http塊,server塊,級(jí)別以此為:debug|info|notice|warn|error|crit|alert|emerg events {accept_mutex on; #設(shè)置網(wǎng)路連接序列化,防止驚群現(xiàn)象發(fā)生,默認(rèn)為onmulti_accept on; #設(shè)置一個(gè)進(jìn)程是否同時(shí)接受多個(gè)網(wǎng)絡(luò)連接,默認(rèn)為off#use epoll; #事件驅(qū)動(dòng)模型,select|poll|kqueue|epoll|resig|/dev/poll|eventportworker_connections 1024; #最大連接數(shù),默認(rèn)為512 } http {include mime.types; #文件擴(kuò)展名與文件類型映射表default_type application/octet-stream; #默認(rèn)文件類型,默認(rèn)為text/plain#access_log off; #取消服務(wù)日志 log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定義格式access_log log/access.log myFormat; #combined為日志格式的默認(rèn)值sendfile on; #允許sendfile方式傳輸文件,默認(rèn)為off,可以在http塊,server塊,location塊。sendfile_max_chunk 100k; #每個(gè)進(jìn)程每次調(diào)用傳輸數(shù)量不能大于設(shè)定的值,默認(rèn)為0,即不設(shè)上限。keepalive_timeout 65; #連接超時(shí)時(shí)間,默認(rèn)為75s,可以在http,server,location塊。upstream mysvr { server 127.0.0.1:7878;server 192.168.10.121:3333 backup; #熱備}error_page 404 https://www.baidu.com; #錯(cuò)誤頁(yè)server {keepalive_requests 120; #單連接請(qǐng)求上限次數(shù)。listen 4545; #監(jiān)聽(tīng)端口server_name 127.0.0.1; #監(jiān)聽(tīng)地址 location ~*^.+$ { #請(qǐng)求的url過(guò)濾,正則匹配,~為區(qū)分大小寫(xiě),~*為不區(qū)分大小寫(xiě)。#root path; #根目錄#index vv.txt; #設(shè)置默認(rèn)頁(yè)proxy_pass http://mysvr; #請(qǐng)求轉(zhuǎn)向mysvr 定義的服務(wù)器列表deny 127.0.0.1; #拒絕的ipallow 172.18.5.54; #允許的ip } } }上面是nginx的基本配置,需要注意的有以下幾點(diǎn):
1、1.$remote_addr 與$http_x_forwarded_for 用以記錄客戶端的ip地址;?2.$remote_user :用來(lái)記錄客戶端用戶名稱;?3.$time_local : 用來(lái)記錄訪問(wèn)時(shí)間與時(shí)區(qū);4.$request : 用來(lái)記錄請(qǐng)求的url與http協(xié)議;
? 5.$status : 用來(lái)記錄請(qǐng)求狀態(tài);成功是200,?6.$body_bytes_s ent :記錄發(fā)送給客戶端文件主體內(nèi)容大小;7.$http_referer :用來(lái)記錄從那個(gè)頁(yè)面鏈接訪問(wèn)過(guò)來(lái)的;?8.$http_user_agent :記錄客戶端瀏覽器的相關(guān)信息;
2、驚群現(xiàn)象:一個(gè)網(wǎng)路連接到來(lái),多個(gè)睡眠的進(jìn)程被同事叫醒,但只有一個(gè)進(jìn)程能獲得鏈接,這樣會(huì)影響系統(tǒng)性能。
3、每個(gè)指令必須有分號(hào)結(jié)束。
nginx的介紹基本到這就結(jié)束了,這篇博文呢基本不是自己寫(xiě)的,我只是將一些好的博客里面的重點(diǎn)部分給組織了一下,后面會(huì)開(kāi)始學(xué)習(xí)分布式dubbo和zookerper。下面的幾個(gè)幾個(gè)鏈接都是我參考的博客
1.最好的nginx介紹文章:https://www.cnblogs.com/mfc-itblog/p/5176792.html
2.最好的nginx配置文件介紹文章:https://www.cnblogs.com/knowledgesea/p/5175711.html? ?
總結(jié)
以上是生活随笔為你收集整理的nginx基本原理介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Servlet JSP系列文章总结
- 下一篇: HDU-Yuna's confusion