本章內(nèi)容
◆ I/O模型
◆ nginx介紹
◆ nginx安裝
◆ nginx各種模塊實現(xiàn)web服務
◆ nginx實現(xiàn)fastcgi反代代理
◆ nginx實現(xiàn)http負載均衡
◆ nginx實現(xiàn)tcp反向代理
◆ tengine實現(xiàn)
◆ nginx高并發(fā)Linux內(nèi)核優(yōu)化
性能影響
- 有很多研究都表明,性能對用戶的行為有很大的影響:
● 79%的用戶表示不太可能再次打開一個緩慢的網(wǎng)站
● 47%的用戶期望網(wǎng)頁能在2秒鐘以內(nèi)加載
● 40%的用戶表示如果加載時間超過三秒鐘,就會放棄這個網(wǎng)站
● 頁面加載時間延遲一秒可能導致轉(zhuǎn)換損失7%,頁面瀏覽量減少11%
● 8秒定律:用戶訪問一個網(wǎng)站時,如果等待網(wǎng)頁打開的時間超過8秒,會有超過30%的用戶放棄等待
影響用戶體驗的幾個因素
● 客戶端硬件配置
● 客戶端網(wǎng)絡速率
● 客戶端與服務端距離
● 服務端網(wǎng)絡速率
● 服務端硬件配置
● 服務端架構(gòu)設(shè)計
● 服務端應用程序工作模式
● 服務端并發(fā)數(shù)量
● 服務端響應文件大小及數(shù)量
● 服務端I/O壓力
Httpd MPM
- prefork:進程模型,兩級結(jié)構(gòu),主進程master負責生成子進程,每個子進程負責響應一個請求
- worker:線程模型,三級結(jié)構(gòu),主進程master負責生成子進程,每個子進程負責生成多個線程,每個線程響應一個請求
- event:線程模型,三級結(jié)構(gòu),主進程master負責生成子進程,每個子進程響應多個請求
I/O介紹
- I/O:
網(wǎng)絡IO:本質(zhì)是socket文件讀取
磁盤IO: - 每次IO,都要經(jīng)由兩個階段:
第一步:將數(shù)據(jù)從文件先加載至內(nèi)核內(nèi)存空間(緩沖區(qū)),等待數(shù)據(jù)準備完成,時間較長
第二步:將數(shù)據(jù)從內(nèi)核緩沖區(qū)復制到用戶空間的進程的內(nèi)存中,時間較短
I/O模型
- 同步/異步:關(guān)注的是消息通信機制
同步:synchronous,調(diào)用者等待被調(diào)用者返回消息,才能繼續(xù)執(zhí)行
異步:asynchronous,被調(diào)用者通過狀態(tài)、通知或回調(diào)機制主動通知調(diào)用者被調(diào)用者的運行狀態(tài) - 阻塞/非阻塞:關(guān)注調(diào)用者在等待結(jié)果返回之前所處的狀態(tài)
阻塞:blocking,指IO操作需要徹底完成后才返回到用戶空間,調(diào)用結(jié)果返回之前,調(diào)用者被掛起
非阻塞:nonblocking,指IO操作被調(diào)用后立即返回給用戶一個狀態(tài)值,無需等到IO操作徹底完成,最終的調(diào)用結(jié)果返回之前,調(diào)用者不會被掛起 - I/O模型:
阻塞型、非阻塞型、復用型、信號驅(qū)動型、異步
阻塞IO模型
阻塞IO模型是最簡單的IO模型,用戶線程在內(nèi)核進行IO操作時被阻塞
用戶線程通過系統(tǒng)調(diào)用read發(fā)起IO讀操作,由用戶空間轉(zhuǎn)到內(nèi)核空間。內(nèi)核等到數(shù)據(jù)包到達后,然后將接收的數(shù)據(jù)拷貝到用戶空間,完成read操作
用戶需要等待read將數(shù)據(jù)讀取到buffer后,才繼續(xù)處理接收的數(shù)據(jù)。整個IO請求的過程中,用戶線程是被阻塞的,這導致用戶在發(fā)起IO請求時,不能做任何事情,對CPU的資源利用率不夠
優(yōu)點:程序簡單,在阻塞等待數(shù)據(jù)期間進程/線程掛起,基本不會占用 CPU 資源
缺點:每個連接需要獨立的進程/線程單獨處理,當并發(fā)請求量大時為了維護程序,內(nèi)存、線程切換開銷較大,這種模型在實際生產(chǎn)中很少使用
對于單線程的網(wǎng)絡服務,這樣做就會有卡死的問題。因為當?shù)却龝r,整個線程會被掛起,無法執(zhí)行,也無法做其他的工作。這種Block是不會影響同時運行的其他程序(進程)的,因為現(xiàn)代操作系統(tǒng)都是多任務的,任務之間的切換是搶占式的。這里Block只是指Block當前的進程
網(wǎng)絡服務為了同時響應多個并發(fā)的網(wǎng)絡請求,必須實現(xiàn)為多線程,每個線程處理一個網(wǎng)絡請求。線程數(shù)隨著并發(fā)連接數(shù)線性增長。 2000年之前很多網(wǎng)絡服務器就是這么實現(xiàn)的。 但有兩個問題:線程越多,Context Switch就越多,而Context Switch是一個比較重的操作,會無謂浪費大量的CPU。每個線程同時也會占用一定的內(nèi)存作為線程的棧
雖可通過線程池技術(shù)既能并發(fā)的處理請求,又不會產(chǎn)生大量線程。但這樣會限制最大并發(fā)的連接數(shù)。
-
當調(diào)用read接受網(wǎng)絡請求時,有數(shù)據(jù)到了就處理,沒數(shù)據(jù)到時,實際上是可以干別的。之所以使用大量線程,僅僅是因為Block發(fā)生
總結(jié):
應用程序接收到用戶一個請求,應用程序發(fā)起系統(tǒng)調(diào)用內(nèi)核完成工作,內(nèi)核從網(wǎng)絡或者硬盤上得到數(shù)據(jù),發(fā)往應用程序的用戶空間中,此時應用程序一直處于等待狀態(tài),不能做任何事
同步非阻塞IO模型
用戶線程發(fā)起IO請求時立即返回。但并未讀取到任何數(shù)據(jù),用戶線程需要不斷地發(fā)起IO請求,直到數(shù)據(jù)到達后,才真正讀取到數(shù)據(jù),繼續(xù)執(zhí)行。即 “輪詢”機制
存在兩個問題:如果有大量文件描述符都要等,那么就得一個一個的read。這會帶來大量的Context Switch(read是系統(tǒng)調(diào)用,每調(diào)用一次就得在用戶態(tài)和核心態(tài)切換一次)。輪詢的時間不好把握。這里是要猜多久之后數(shù)據(jù)才能到。等待時間設(shè)的太長,程序響應延遲就過大;設(shè)的太短,就會造成過于頻繁的重試,干耗CPU而已
-
是比較浪費CPU的方式,一般很少直接使用這種模型,而是在其他IO模型中使用非阻塞IO這一特性
總結(jié):
應用程序接收到用戶一個請求,應用程序發(fā)起系統(tǒng)調(diào)用內(nèi)核完成工作,應用程序發(fā)起調(diào)用后處于空閑狀態(tài),不用等待系統(tǒng)回應,所以應用程序會不斷詢問系統(tǒng)處理結(jié)果。當系統(tǒng)處理完畢后就會回應并發(fā)往應用程序的用戶空間
I/O多路復用模型
IO多路復用(IO Multiplexing) :是一種機制,程序注冊一組socket文件描述符給操作系統(tǒng),表示“我要監(jiān)視這些fd是否有IO事件發(fā)生,有了就告訴程序處理”
IO多路復用是要和NIO一起使用的。 NIO和IO多路復用是相對獨立的。 NIO僅僅是指IO API總是能立刻返回,不會被Blocking;而IO多路復用僅僅是操作系統(tǒng)提供的一種便利的通知機制。操作系統(tǒng)并不會強制這倆必須得一起用,可以只用IO多路復用 + BIO,這時還是當前線程被卡住。 IO多路復用和NIO是要配合一起使用才有實際意義
IO多路復用是指內(nèi)核一旦發(fā)現(xiàn)進程指定的一個或者多個IO條件準備讀取,就通知該進程
多個連接共用一個等待機制,本模型會阻塞進程,但是進程是阻塞在select或者poll這兩個系統(tǒng)調(diào)用上,而不是阻塞在真正的IO操作上
用戶首先將需要進行IO操作添加到select中,同時等待select系統(tǒng)調(diào)用返回。當數(shù)據(jù)到達時,IO被激活,select函數(shù)返回。用戶線程正式發(fā)起read請求,讀取數(shù)據(jù)并繼續(xù)執(zhí)行
從流程上來看,使用select函數(shù)進行IO請求和同步阻塞模型沒有太大的區(qū)別,甚至還多了添加監(jiān)視IO,以及調(diào)用select函數(shù)的額外操作,效率更差。并且阻塞了兩次,但是第一次阻塞在select上時,select可以監(jiān)控多個IO上是否已有IO操作準備就緒,即可達到在同一個線程內(nèi)同時處理多個IO請求的目的。而不像阻塞IO那種,一次只能監(jiān)控一個IO
雖然上述方式允許單線程內(nèi)處理多個IO請求,但是每個IO請求的過程還是阻塞的(在select函數(shù)上阻塞),平均時間甚至比同步阻塞IO模型還要長。如果用戶線程只是注冊自己需要的IO請求,然后去做自己的事情,等到數(shù)據(jù)到來時再進行處理,則可以提高CPU的利用率
-
IO多路復用是最常使用的IO模型,但是其異步程度還不夠“徹底”,因它使用了會阻塞線程的select系統(tǒng)調(diào)用。因此IO多路復用只能稱為異步阻塞IO模型,而非真正的異步IO
總結(jié):
多個app發(fā)起請求,select進程接受請求,select進程發(fā)往內(nèi)核處理,如果內(nèi)核已把數(shù)據(jù)準備好了,發(fā)信息給app(在此之前app處于阻塞狀態(tài)),此時app參與了復制過程,內(nèi)核把數(shù)據(jù)復制到用戶空間并返回了成功結(jié)果,app就可以進行通訊了
信號驅(qū)動IO模型
信號驅(qū)動IO:signal-driven I/O
用戶進程可以通過sigaction系統(tǒng)調(diào)用注冊一個信號處理程序,然后主程序可以繼續(xù)向下執(zhí)行,當有IO操作準備就緒時,由內(nèi)核通知觸發(fā)一個SIGIO信號處理程序執(zhí)行,然后將用戶進程所需要的數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間
此模型的優(yōu)勢在于等待數(shù)據(jù)報到達期間進程不被阻塞。用戶主程序可以繼續(xù)執(zhí)行,只要等待來自信號處理函數(shù)的通知
對于 TCP 而言,信號驅(qū)動的 I/O 方式近乎無用,因為導致這種通知的條件為數(shù)眾多,每一個來進行判別會消耗很大資源,與前幾種方式相比優(yōu)勢盡失
優(yōu)點:線程并沒有在等待數(shù)據(jù)時被阻塞,可以提高資源的利用率
-
缺點:信號 I/O 在大量 IO 操作時可能會因為信號隊列溢出導致沒法通知
總結(jié):
app進程發(fā)起系統(tǒng)調(diào)用后,有異步行為,內(nèi)核準備數(shù)據(jù)發(fā)到內(nèi)核發(fā)送數(shù)據(jù)到用戶空間期間不阻塞(app可以做其他事)
異步IO模型
異步IO與信號驅(qū)動IO最主要的區(qū)別是信號驅(qū)動IO是由內(nèi)核通知應用程序何時可以進行IO操作,而異步IO則是由內(nèi)核告訴用戶線程IO操作何時完成。信號驅(qū)動IO當內(nèi)核通知觸發(fā)信號處理程序時,信號處理程序還需要阻塞在從內(nèi)核空間緩沖區(qū)拷貝數(shù)據(jù)到用戶空間緩沖區(qū)這個階段,而異步IO直接是在第二個階段完成后,內(nèi)核直接通知用戶線程可以進行后續(xù)操作了
由 POSIX 規(guī)范定義,應用程序告知內(nèi)核啟動某個操作,并讓內(nèi)核在整個操作(包括將數(shù)據(jù)從內(nèi)核拷貝到應用程序的緩沖區(qū))完成后通知應用程序
優(yōu)點:異步 I/O 能夠充分利用 DMA 特性,讓 I/O 操作與計算重疊
-
缺點:要實現(xiàn)真正的異步 I/O,操作系統(tǒng)需要做大量的工作。目前 Windows 下通過 IOCP 實現(xiàn)了真正的異步 I/O,在 Linux 系統(tǒng)下,Linux 2.6才引入,目前AIO 并不完善,因此在 Linux 下實現(xiàn)高并發(fā)網(wǎng)絡編程時以 IO 復用模型模式+多線程任務的架構(gòu)基本可以滿足需求
總結(jié):
app進程發(fā)起系統(tǒng)調(diào)用后,由內(nèi)核完成,內(nèi)核在處理過程中app全都不阻塞
I/O模型的具體實現(xiàn)
- 這五種 I/O 模型中,越往后,阻塞越少,理論上效率也是最優(yōu)前四種屬于同步I/O,因為其中真正的 I/O 操作(recvfrom)將阻塞進程/線程,只有異步 I/O 模型才與 POSIX 定義的異步 I/O 相匹配
- 主要實現(xiàn)方式有以下幾種:
Select:Linux實現(xiàn)對應,I/O復用模型,BSD4.2最早實現(xiàn),POSIX標準,一般操作系統(tǒng)均有實現(xiàn)
Poll:Linux實現(xiàn),對應I/O復用模型,System V unix最早實現(xiàn)
Epoll:Linux特有,對應I/O復用模型,具有信號驅(qū)動I/O模型的某些特性
Kqueue:FreeBSD實現(xiàn),對應I/O復用模型,具有信號驅(qū)動I/O模型某些特性
/dev/poll:SUN的Solaris實現(xiàn),對應I/O復用模型,具有信號驅(qū)動I/O模型的某些特性
Iocp Windows實現(xiàn),對應第5種(異步I/O)模型
select/poll/epoll
- Select:POSIX所規(guī)定,目前幾乎在所有的平臺上支持,其良好跨平臺支持也是它的一個優(yōu)點,本質(zhì)上是通過設(shè)置或者檢查存放fd標志位的數(shù)據(jù)結(jié)構(gòu)來進行下一步處理
- 缺點
● 單個進程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制,在Linux上一般為1024,可以通過修改宏定義FD_SETSIZE,再重新編譯內(nèi)核實現(xiàn),但是這樣也會造成效率的降低
● 單個進程可監(jiān)視的fd數(shù)量被限制,默認是1024,修改此值需要重新編譯內(nèi)核
● 對socket是線性掃描,即采用輪詢的方法,效率較低
● select 采取了內(nèi)存拷貝方法來實現(xiàn)內(nèi)核將 FD 消息通知給用戶空間,這樣一個用來存放大量fd的數(shù)據(jù)結(jié)構(gòu),這樣會使得用戶空間和內(nèi)核空間在傳遞該結(jié)構(gòu)時復制開銷大
#查看源碼內(nèi)核FD_SETSIZE的值
find linux-5.1.4/ -type f | xargs grep "FD_SETSIZE"
poll
● 本質(zhì)上和select沒有區(qū)別,它將用戶傳入的數(shù)組拷貝到內(nèi)核空間,然后查詢每個fd對應的設(shè)備狀態(tài)
● 其沒有最大連接數(shù)的限制,原因是它是基于鏈表來存儲的
● 大量的fd的數(shù)組被整體復制于用戶態(tài)和內(nèi)核地址空間之間,而不管這樣的復制是不是有意義
● poll特點是“水平觸發(fā)”,如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd
● 邊緣觸發(fā):只通知一次epoll:在Linux 2.6內(nèi)核中提出的select和poll的增強版本
● 支持水平觸發(fā)LT和邊緣觸發(fā)ET,最大的特點在于邊緣觸發(fā),它只告訴進程哪些fd剛剛變?yōu)榫托钁B(tài),并且只會通知一次
● 使用“事件”的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內(nèi)核就會采用類似callback的回調(diào)機制來激活該fd,epoll_wait便可以收到通知優(yōu)點:
● 沒有最大并發(fā)連接的限制:能打開的FD的上限遠大于1024(1G的內(nèi)存能監(jiān)聽約10萬個端口),具體查看/proc/sys/fs/file-max,此值和系統(tǒng)內(nèi)存大小相關(guān)
● 效率提升:非輪詢的方式,不會隨著FD數(shù)目的增加而效率下降;只有活躍可用的FD才會調(diào)用callback函數(shù),即epoll最大的優(yōu)點就在于它只管理“活躍”的連接,而跟連接總數(shù)無關(guān)
● 內(nèi)存拷貝,利用mmap(Memory Mapping)加速與內(nèi)核空間的消息傳遞;即epoll使用mmap減少復制開銷
零拷貝
- 傳統(tǒng)Linux中 I/O 的問題
- 傳統(tǒng)的 Linux 系統(tǒng)的標準 I/O 接口(read、 write)是基于數(shù)據(jù)拷貝的,也就是 數(shù)據(jù)都是 copy_to_user 或者 copy_from_user,這樣做的好處是,通過中間緩存的機制,減少磁盤 I/O 的操作,但是壞處也很明顯,大量數(shù)據(jù)的拷貝,用戶態(tài)和內(nèi)核態(tài)的頻繁切換,會消耗大量的 CPU 資源,嚴重影響數(shù)據(jù)傳輸?shù)男阅埽?統(tǒng)計表明,在Linux協(xié)議棧中,數(shù)據(jù)包在內(nèi)核態(tài)和用戶態(tài)之間的拷貝所用的時間,甚至占到了數(shù)據(jù)包整個處理流程時間的57.1%
- 什么是零拷貝
- 零拷貝就是上述問題的一個解決方案,通過盡量避免拷貝操作來緩解 CPU 的壓 力。零拷貝并沒有真正做到“0” 拷貝,它更多是一種思想,很多的零拷貝技術(shù) 都是基于這個思想去做的優(yōu)化
nginx介紹
nginx: engine X,是由1994年畢業(yè)于俄羅斯國立莫斯科鮑曼科技大學的同學為俄羅斯rambler.ru公司開發(fā)的,開發(fā)工作最早從2002年開始,第一次公開發(fā)布時間是2004年10月4日,版本號是0.1.0
nginx有商業(yè)版和社區(qū)版,2019年3月11日F5 Networks 6.7億美元的價格收購
nginx 是免費,開源,高性能的HTTP和反向代理服務器,郵件代理服務器,通用TCP/UDP代理服務器
解決C10K問題(10K Connections)
官網(wǎng):http://nginx.org
nginx的其它的二次發(fā)行版:
Tengine:由淘寶網(wǎng)發(fā)起的Web服務器項目。它在Nginx的基礎(chǔ)上,針對大訪問量網(wǎng)站的需求,添加了很多高級功能和特性。 Tengine的性能和穩(wěn)定性已經(jīng)在大型的網(wǎng)站如淘寶網(wǎng),天貓商城等得到了很好的檢驗。從2011年12月開始,Tengine成為一個開源項目,官網(wǎng) http://tengine.taobao.org/
OpenResty:基于 Nginx 與 Lua 語言的高性能 Web 平臺, 章亦春
官網(wǎng):http://openresty.org/cn/特性:
模塊化設(shè)計,較好的擴展性
高可靠性
支持熱部署:不停機更新配置文件,升級版本,更換日志文件
低內(nèi)存消耗:10000個keep-alive連接模式下的非活動連接,僅需2.5M內(nèi)存
event-driven,aio,mmap,sendfile基本功能:
靜態(tài)資源的web服務器
http協(xié)議反向代理服務器
pop3/imap4協(xié)議反向代理服務器
FastCGI(LNMP),uWSGI(python)等協(xié)議
模塊化(非DSO),如zip,SSL模塊
nginx的程序架構(gòu)
web服務相關(guān)的功能:
虛擬主機(server)
支持 keep-alive 和管道連接( 共享TCP連接發(fā)起并發(fā)的HTTP請求)
訪問日志(支持基于日志緩沖提高其性能)
url rewrite
路徑別名
基于IP及用戶的訪問控制
支持速率限制及并發(fā)數(shù)限制
重新配置和在線升級而無須中斷客戶的工作進程
Memcached 的 GET 接口nginx的程序架構(gòu):
master/worker結(jié)構(gòu)
● 一個master進程:
負載加載和分析配置文件、管理worker進程、平滑升級
● 一個或多個worker進程
處理并響應用戶請求
● 緩存相關(guān)的進程:
cache loader:載入緩存對象
cache manager:管理緩存對象
nginx模塊
- nginx高度模塊化,但其模塊早期不支持DSO機制;1.9.11版本支持動態(tài)裝載和卸載
- 模塊分類:
核心模塊:core module
標準模塊:
● HTTP 模塊: ngx_http_*
HTTP Core modules 默認功能
HTTP Optional modules 需編譯時指定
● Mail 模塊 ngx_mail_*
● Stream 模塊 ngx_stream_*
第三方模塊 - 核心模塊:是 Nginx 服務器正常運行 必不可少 的模塊,提供 錯誤日志記錄 、配置文件解析 、 事件驅(qū)動機制 、 進程管理 等核心功能
- 標準HTTP模塊:提供 HTTP 協(xié)議解析相關(guān)的功能,比如: 端口配置 、 網(wǎng)頁編碼設(shè)置 、 HTTP響應頭設(shè)置 等等
- 可選HTTP模塊:主要用于擴展標準的 HTTP 功能,讓 Nginx 能處理一些特殊的服務,比如: Flash 多媒體傳輸 、解析 GeoIP 請求、 網(wǎng)絡傳輸壓縮 、 安全協(xié)議 SSL 支持等
- 郵件服務模塊:主要用于支持 Nginx 的 郵件服務 ,包括對 POP3 協(xié)議、IMAP 協(xié)議和 SMTP協(xié)議的支持
- 第三方模塊:是為了擴展 Nginx 服務器應用,完成開發(fā)者自定義功能,比如:Json 支持、 Lua 支持等
nginx的功用
- 靜態(tài)的web資源服務器
html,圖片,js,css,txt等靜態(tài)資源 - 結(jié)合FastCGI/uWSGI/SCGI等協(xié)議反向代理動態(tài)資源請求
- http/https協(xié)議的反向代理
- imap4/pop3協(xié)議的反向代理
- tcp/udp協(xié)議的請求轉(zhuǎn)發(fā)(反向代理)
nginx的安裝
官方y(tǒng)um源:
http://nginx.org/packages/centos/7/x86_64/Fedora-EPEL源:
https://mirrors.aliyun.com/epel/7/x86_64/-
編譯安裝:
yum install gcc pcre-devel openssl-devel zlib-devel useradd -r -s /sbin/nologin nginx ./configure --prefix=/apps/nginx --conf-path=/etc/nginx/nginx.conf --errorlog-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --withhttp_dav_module --with-http_stub_status_module --with-threads --with-file-aio make && make install
vim /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
yum install nginx
編譯安裝示例
useradd -r -s /sbin/nologin nginx
./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
make && make install
小筆記:nginx
yum install nginx
systemctl start nginx
echo "welcome" > /usr/share/nginx/html/index.html
nginx #啟動服務
nginx -s reload|stop|restart
nginx -t #檢查配置文件
nginx -T #查看配置文件內(nèi)容
nginx -V #查看編譯的參數(shù)
小筆記:源碼編譯nginx
wget http://nginx.org/download/nginx-1.16.1.tar.gz
tar xf nginx-1.16.1.tar.gz
yum install gcc pcre-devel openssl-devel zlib-devel
useradd -r -s /sbin/nologin nginx
cd nginx-1.16.1
./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
make && make install
ln -s /apps/nginx/sbin/nginx /usr/sbin/
/apps/nginx/html #主頁文件目錄
nginx目錄結(jié)構(gòu)和命令
- ls /apps/nginx/
html是測試頁,sbin是主程序 - ls /apps/nginx/sbin/
nginx 只有一個程序文件 - ls /apps/nginx/html/
50x.html index.html 測試網(wǎng)頁 - nginx:默認為啟動nginx
-h 查看幫助選項
-V 查看版本和配置選項
-t 測試nginx語法錯誤
-c filename 指定配置文件(default: /etc/nginx/nginx.conf)
-s signal 發(fā)送信號給master進程,signal:stop, quit, reopen, reload
● 示例: nginx -s stop 停止nginx
nginx -s reload 加載配置文件
-g directives 在命令行中指明全局指令
nginx配置
- 配置文件的組成部分:
● 主配置文件:nginx.conf
子配置文件 include conf.d/*.conf
● fastcgi, uwsgi,scgi等協(xié)議相關(guān)的配置文件
● mime.types:支持的mime類型 - 主配置文件的配置指令:
directive value [value2 ...]; - 注意:
(1) 指令必須以分號結(jié)尾
(2) 支持使用配置變量
內(nèi)建變量:由Nginx模塊引入,可直接引用
自定義變量:由用戶使用set命令定義
set variable_name value;
引用變量:$variable_name
nginx配置文件
主配置文件結(jié)構(gòu):四部
main block:主配置段,即全局配置段,對http,mail都有效
event {
...
} 事件驅(qū)動相關(guān)的配置
http {
...
} http/https 協(xié)議相關(guān)配置段
mail {
...
} mail 協(xié)議相關(guān)配置段
stream {
...
} stream 服務器相關(guān)配置段
http協(xié)議相關(guān)的配置結(jié)構(gòu)
http {
...
... 各server的公共配置
server { 每個server用于定義一個虛擬主機
...
}
server {
...
server_name 虛擬主機名
root 主目錄
alias 路徑別名
location [OPERATOR] URL { 指定URL的特性
...
if CONDITION {
...
}
}
}
}
nginx配置
Main 全局配置段常見的配置指令分類
正常運行必備的配置
優(yōu)化性能相關(guān)的配置
用于調(diào)試及定位問題相關(guān)的配置
事件驅(qū)動相關(guān)的配置幫助文檔
http://nginx.org/en/docs/
http://tengine.taobao.org/nginx_docs/cn/docs/正常運行必備的配置:
● user
指定worker進程的運行身份,如組不指定,默認和用戶名同名
Syntax: user user [group];
Default: user nobody nobody;
Context: main
● pid /PATH/TO/PID_FILE;
指定存儲nginx主進程PID的文件路徑
● include file | mask;
指明包含進來的其它配置文件片斷
● load_module file ;
模塊加載配置文件: /usr/share/nginx/modules/*.conf
指明要裝載的動態(tài)模塊路徑:/usr/lib64/nginx/modules性能優(yōu)化相關(guān)的配置:
● worker_processes number | auto;
worker進程的數(shù)量;通常應該為當前主機的cpu的物理核心數(shù)
● worker_cpu_affinity cpumask ...;
worker_cpu_affinity auto [cpumask] 提高緩存命中率
CPU MASK: 00000001:0號CPU
00000010:1號CPU
10000000:7號CPU
worker_cpu_affinity 0001 0010 0100 1000;
worker_cpu_affinity 0101 1010;
● worker_priority number;
指定worker進程的nice值,設(shè)定worker進程優(yōu)先級:[-20,20]
● worker_rlimit_nofile number;
所有worker進程能打開的文件數(shù)量上限,最好與ulimit -n 的值保持一致,如65535事件驅(qū)動相關(guān)的配置:
events {
...
}
● worker_connections #;
每個worker進程所能夠打開的最大并發(fā)連接數(shù),如10240
總最大并發(fā)數(shù):worker_processes * worker_connections
● use method;
指明并發(fā)連接請求的處理方法,默認自動選擇最優(yōu)方法
示例:use epoll;事件驅(qū)動相關(guān)的配置:
● accept_mutex on | off;
處理新的連接請求的方法;on指由各個worker輪流處理新請求,Off指每個新請求的到達都會通知(喚醒)所有的worker進程,但只有一個進程可獲得連接,造成“驚群”,影響性能,默認值為off,可優(yōu)化為on
● multi_accept on|off;
此指令默認為off,即默認為一個worker進程只能一次接受一個新的網(wǎng)絡連 接, on表示每個woker進程可以同時接受所有新的網(wǎng)絡連接調(diào)試和定位問題:
1、 daemon on|off;
是否以守護進程方式運行,默認是on,即守護進程方式,off 用于調(diào)試或docker環(huán)境
2、 master_process on|off;
是否以master/worker模型運行nginx,默認為on,當指定off 將不啟動worker
3、 error_log file [level] ;
錯誤日志文件及其級別;出于調(diào)試需要,可設(shè)定為debug;但debug僅在編譯時使用了“--with-debug” 選項時才有效
/path/logfile: 記錄到文件中
stderr: 發(fā)送到標準錯誤
syslog:server-address[,parameter=values] 發(fā)送到syslog
memory:size 內(nèi)存
level:debug|info|notice|warn|error|crit|alter|emerg 日志級別-
http協(xié)議的相關(guān)配置:
http { ... ... server { ... server_name root location [OPERATOR] /uri/ { ... } } server { ... } }
ngx_http_core_module
-
在響應報文中將指定的文件擴展名映射至MIME對應的類型
include /etc/nginx/mime.types; default_type application/octet-stream; #除上面指定的類型外,就為默認的MIME類型,瀏覽器一般會提示下載 types { text/html html; image/gif gif; image/jpeg jpg; }
MIME參考文檔:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_Typestcp_nodelay on | off;
在keepalived模式下的連接是否啟用TCP_NODELAY選項,即Nagle算法
當為off時,延遲發(fā)送,每發(fā)送一個包就需要確認ACK,才發(fā)送下一個包
默認On時,不延遲發(fā)送,多個包才確認一次
可用于:http, server, locationtcp_nopush on | off ;
在開啟sendfile,on時合并響應頭和數(shù)據(jù)體在一個包中一起發(fā)送sendfile on | off;
是否啟用sendfile功能,在內(nèi)核中封裝報文直接發(fā)送,默認Offcharset charset | off;
是否在響應報文中的Content-Type顯示指定的字符集,默認off不顯示server_tokens on | off | build | string;
是否在響應報文的Server首部顯示nginx版本如果想自定義響應報文的nginx版本信息,需要修改源碼文件,重新編譯
-
如果server_tokens on,修改 src/core/nginx.h 修改第13-14行,如下示例
define NGINX_VERSION "1.68.9"
define NGINX_VER "wanginx/" NGINX_VERSION
如果server_tokens off,修改 src/http/ngx_http_header_filter_module.c
第49行,如下示例:
static char ngx_http_server_string[] = "Server: nginx" CRLF;
把其中的nginx改為自己想要的文字即可,如:wanginx
-
ngx_http_core_module
與套接字相關(guān)的配置:server { ... } #配置一個虛擬主機 server { listen address[:PORT]|PORT; server_name SERVER_NAME; root /PATH/TO/DOCUMENT_ROOT; }
listen PORT|address[:port]|unix:/PATH/TO/SOCKET_FILE
listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size];
default_server 設(shè)定為默認虛擬主機,無法匹配虛擬主機時使用
ssl 限制僅能夠通過ssl連接提供服務
backlog=number 超過并發(fā)連接數(shù)后,新請求進入后援隊列的長度
rcvbuf=size 接收緩沖區(qū)大小
sndbuf=size 發(fā)送緩沖區(qū)大小
注意:
(1) 基于port;
listen PORT; 指令監(jiān)聽在不同的端口
(2) 基于ip的虛擬主機
listen IP:PORT; IP 地址不同
(3) 基于hostname
server_name fqdn; 指令指向不同的主機名server_name name ...;
● 虛擬主機的主機名稱后可跟多個由空白字符分隔的字符串
● 支持*通配任意長度的任意字符
server_name .magedu.com www.magedu.
● 支持~起始的字符做正則表達式模式匹配,性能原因慎用
server_name ~^www\d+.magedu.com
(5) default_server定義路徑相關(guān)的配置
root
設(shè)置web資源的路徑映射;用于指明請求的URL所對應的文檔的目錄路徑,可用于http, server, location, if in location
server {
...
root /data/www/vhost1;
}
示例
http://www.magedu.com/images/logo.jpg
--> /data/www/vhosts/images/logo.jpg
- location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
在一個server中l(wèi)ocation配置段可存在多個,用于實現(xiàn)從uri到文件系統(tǒng)的路徑映射;ngnix會根據(jù)用戶請求的URI來檢查定義的所有l(wèi)ocation,并找出一個最佳匹配,而后應用其配置
示例:
server {...
server_name www.magedu.com;
location /images/ {
root /data/imgs/;
}
}
http://www.magedu.com/images/logo.jpg
--> /data/imgs/images/logo.jpg
- = 對URI做精確匹配;
location = / {
...
}
http://www.magedu.com/ 匹配
http://www.magedu.com/index.html 不匹配
^~ | 對URI的最左邊部分做匹配檢查,不區(qū)分字符大小寫 |
---|---|
~ | 對URI做正則表達式模式匹配,區(qū)分字符大小寫 |
~* | 對URI做正則表達式模式匹配,不區(qū)分字符大小寫 |
不帶符號 | 匹配起始于此uri的所有的uri |
\ | 轉(zhuǎn)義符,可將 . * ?等轉(zhuǎn)義為普通符號 |
匹配優(yōu)先級從高到低:=, ^~, ~/~*, 不帶符號
- 示例:
root /vhosts/www/htdocs/;
http://www.magedu.com/index.html
--> /vhosts/www/htdocs/index.html
server {
root /vhosts/www/htdocs/ ;
location /admin/ {
root /webapps/app1/data/;
}
}
http://www.magedu.com/admin/index.html
--> /webapps/app1/data/admin/index.html
- location示例
location = / { http://www.magedu.com/
[ configuration A ]
}
location / { http://www.magedu.com/index.html
[ configuration B ]
}
location /documents/ { http://www.magedu.com/documents/logo.jpg
[ configuration C ]
}
location ^~ /images/ { http://www.magedu.com/documents/linux.txt
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ { http://www.magedu.com/images/logo.jpeg
[ configuration E ]
}
- root 指定虛擬主機根目錄,在定義location時,文件的絕對路徑等于 root+location,
示例:
server {
listen 80;
server_name www.magedu.net;
location / {
root /data/nginx/html/pc;
}
location /about {
root /opt/nginx/html/pc;
#必須要在html目錄中創(chuàng)建一個about目錄才可以訪問,否則報錯
index index.html;
}
}
#mkdir /opt/nginx/html/pc/about
#echo about > /opt/nginx/html/pc/about/index.html
- 生產(chǎn)案例:靜態(tài)資源配置
location ^~ /static/ {
root /data/nginx/static;
}
# 或者
location ~* \.(gif|jpg|jpeg|png|bmp|tiff|tif|css|js|ico)$ {
root /data/nginx/static;
}
-
alias path;
路徑別名,文檔映射的另一種機制;僅能用于location上下文示例:
http://www.magedu.com/bbs/index.html location /bbs { #注意: /bbs 后建議不要加 / alias /web/forum/; #--> /web/forum/index.html } location /bbs/ { root /web/forum/; #--> /web/forum/bbs/index.html } #注意:location中使用root指令和alias指令的意義不同 (a) root,給定的路徑對應于location中的/uri 左側(cè)的/ (b) alias,給定的路徑對應于location中的/uri 的完整路徑
alias定義路徑別名,會把訪問的路徑重新定義到其指定的路徑,如下示例:
server {
listen 80;
server_name www.magedu.net;
location / {
root /data/nginx/html/pc;
}
#使用alias的時候uri后面如果加了斜杠則下面的路徑配置必須加斜杠,否則403
location /about { #當訪問about時,訪問alias定義的/opt/nginx/html/pc內(nèi)容
alias /opt/nginx/html/pc;
index index.html;
}
}
index file ...;
指定默認網(wǎng)頁文件,此指令由ngx_http_index_module模塊提供-
error_page code ... [=[response]] uri;
定義錯誤頁,以指定的響應狀態(tài)碼進行響應
可用位置:http, server, location, if in location
示例:error_page 404 /404.html; location = /40x.html { } error_page 404 =200 /404.html error_page 500 502 503 504 /50x.html; location = /50x.html { }
#生產(chǎn)案例:
listen 80;
server_name www.magedu.net;
error_page 500 502 503 504 404 /error.html;
location = /error.html {
root /data/nginx/html;
}
-
try_files file ... uri;
try_files file ... =code;
按順序檢查文件是否存在,返回第一個找到的文件或文件夾(結(jié)尾加斜線表示為
文件夾),如果所有文件或文件夾都找不到,會進行一個內(nèi)部重定向到最后一個
參數(shù)。只有最后一個參數(shù)可以引起一個內(nèi)部重定向,之前的參數(shù)只設(shè)置內(nèi)部URI的
指向location /images/ { try_files $uri /images/default.jpg; } #說明:/images/default.jpg 為 URI location / { try_files $uri $uri/index.html $uri.html =404; }
定義客戶端請求的相關(guān)配置
keepalive_timeout timeout [header_timeout];
設(shè)定保持連接超時時長,0表示禁止長連接,默認為75s
示例:在響應頭顯示此首部字段
keepalive_timeout 60 60;keepalive_requests number;
在一次長連接上所允許請求的資源的最大數(shù)量,默認為100keepalive_disable none | browser ...;
對哪種瀏覽器禁用長連接send_timeout time;
向客戶端發(fā)送響應報文的超時時長,此處是指兩次寫操作之間的間隔時長,而非整個響應過程的傳輸時長
client_max_body_size size;
指定請求報文中實體的最大值,設(shè)為0,則不限制,默認1m,超過報413錯誤client_body_buffer_size size;
用于接收每個客戶端請求報文的body部分的緩沖區(qū)大小;默認為16k;超出此大小時,其將被暫存到磁盤上的由下面client_body_temp_path指令所定義的位置client_body_temp_path path [level1 [level2 [level3]]];
設(shè)定存儲客戶端請求報文的body部分的臨時存儲路徑及子目錄結(jié)構(gòu)和數(shù)量目錄名為16進制的數(shù)字;用hash之后的值從后往前截取第1、 2、 3級作為文件名
client_body_temp_path /var/tmp/client_body 1 2 2
1 1級目錄占1位16進制,即2^4=16個目錄 0-f
2 2級目錄占2位16進制,即2^8=256個目錄 00-ff
2 3級目錄占2位16進制,即2^8=256個目錄 00-ff-
上傳服務器配置生產(chǎn)案例:
location /upload { client_max_body_size 100m; client_body_buffer_size 2048k; client_body_temp_path /apps/nginx/temp 1 2 2; … }
對客戶端進行限制的相關(guān)配置
limit_rate rate;
限制響應給客戶端的傳輸速率,單位是bytes/second
默認值0表示無限制limit_except method ... { ... },僅用于location
限制客戶端使用除了指定的請求方法之外的其它方法
method:GET, HEAD, POST, PUT, DELETE,MKCOL, COPY, MOVE,OPTIONS, PROPFIND, PROPPATCH, LOCK, UNLOCK, PATCH
limit_except GET {
allow 192.168.1.0/24;
deny all;
}
除了GET和HEAD 之外其它方法僅允許192.168.1.0/24網(wǎng)段主機使用
文件操作優(yōu)化的配置
aio on | off | threads[=pool];
是否啟用aio功能,默認off-
directio size | off;
當文件大于等于給定大小時,同步(直接)寫磁盤,而非寫緩存,默認off
示例:location /video/ { sendfile on; aio on; directio 8m; }
open_file_cache off;
open_file_cache max=N [inactive=time];
nginx可以緩存以下三種信息:
(1) 文件元數(shù)據(jù):文件的描述符、文件大小和最近一次的修改時間
(2) 打開的目錄結(jié)構(gòu)
(3) 沒有找到的或者沒有權(quán)限訪問的文件的相關(guān)信息
max=N:可緩存的緩存項上限;達到上限后會使用LRU算法實現(xiàn)管理
inactive=time:緩存項的非活動時長,在此處指定的時長內(nèi)未被命中的或
命中的次數(shù)少于open_file_cache_min_uses指令所指定的次數(shù)的緩存項即為非活動項,將被刪除open_file_cache_errors on | off;
是否緩存查找時發(fā)生錯誤的文件一類的信息,默認值為offopen_file_cache_min_uses number;
open_file_cache指令的inactive參數(shù)指定的時長內(nèi),至少被命中此處指定的次數(shù)方可被歸類為活動項,默認值為1open_file_cache_valid time;
緩存項有效性的檢查頻率,默認值為60s
小筆記:nginx配置文件
cd /etc/nginx/
grep -Ev "^#|^$" nginx.conf
mkdir conf.d/test
vim nginx.conf
user nginx; #指定用戶名
worker_processes 4; #進程數(shù),跟CPU核心有關(guān)
#worker_cpu_affinity 00000001 00000010 00000100 00001000 ; #進程跟CPU綁定
#worker_priority -20 #優(yōu)先級-20到20,越小越大
#worker_rlimit_nofile 65535 #與ulimit -n的值保持一致,配置文件/etc/security/limits.conf
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024; #每個worker進程所能夠打開的最大并發(fā)連接數(shù)
#master_process on|off; #默認為on,當指定off 將不啟動worker
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on; #開啟后nopush才有效
tcp_nopush on; #性能優(yōu)化
tcp_nodelay on; #性能優(yōu)化
keepalive_timeout 65; #保持連接超時時長
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
vim conf.d/test.conf
charset utf-8
server_tokens nginx
小筆記:配置虛擬主機
#server
mkdir /data/site1
mkdir /data/site2
echo /data/site1/index.html > /data/site1/index.html
echo /data/site2/index.html > /data/site2/index.html
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
}
server {
server_name www.magedu.tech;
root /data/site2/;
}
#client
echo "192.168.37.7 www.magedu.net www.magedu.tech" > /etc/hosts
curl http://www.magedu.net
curl http://www.magedu.tech
小筆記:location
#server
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location /test {
root /opt/testdir;
}
}
mkdir /opt/testdir -p
echo "/opt/testdir/index.html" > /opt/testdir/index.html
#client
curl http://www.magedu.net/test
#--------------分割線---------------#
#靜態(tài)資源
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location ~* \.(jpg|gif|html|txt)$ {
root /opt/static;
}
location ~* \.(php|jsp) {
root /opt/dynamic;
}
}
mkdir /opt/static
echo a.jsp > /opt/static/a.jsp
echo aaa.html > /opt/static/a.html
#client
curl http://www.magedu.net/a.jsp
#--------------分割線---------------#
#別名
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location /about { #about后面不要加"/"
alias /opt/testdir;
index test.html
}
error_page 404 /40x.html
#error_page 404 =200 /404.html #錯誤重定向
location = /40x.html {}
}
#client
curl http://www.magedu.net/about
#--------------分割線---------------#
#錯誤
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
error_page 404 /40x.html;
#error_page 404 =200 /404.html; #錯誤重定向
location = /40x.html {}
}
#--------------分割線---------------#
#try_files
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location /images {
alias /data/images
try_files $uri $uri.jpg =404; #先找uri(uri=/images/{這個值}),再找$uri/defalut.jpg,都找不到就404
}
}
#--------------分割線---------------#
#單線程限速
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
limit_rate 10k;
}
#--------------分割線---------------#
#limit_except
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location / {
limit_except GET { #除了get外所有指令都支持
allow 192.168.37.6;
deny all;
}
}
}
#client
curl -I -X OPTIONS www.magedu.net
curl -I -X GET www.magedu.net
#--------------分割線---------------#
#緩存
ngx_http_access_module
ngx_http_access_module模塊
可實現(xiàn)基于ip的訪問控制功能allow address | CIDR | unix: | all;
-
deny address | CIDR | unix: | all;
http, server, location, limit_except
自上而下檢查,一旦匹配,將生效,條件嚴格的置前
示例:location /about { root /data/nginx/html/pc; index index.html; deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; allow 2001:0db8::/32; deny all; #先允許小部分,再拒絕大部分 }
ngx_http_auth_basic_module
ngx_http_auth_basic_module模塊
實現(xiàn)基于用戶的訪問控制,使用basic機制進行用戶認證auth_basic string | off;
-
auth_basic_user_file file;
location /admin/ { auth_basic "Admin Area"; auth_basic_user_file /etc/nginx/.ngxpasswd; }
用戶口令文件:
1、明文文本:格式name:password:comment
2、加密文本:由htpasswd命令實現(xiàn)
httpd-tools所提供
ngx_http_stub_status_module
ngx_http_stub_status_module模塊
用于輸出nginx的基本狀態(tài)信息, 輸出信息示例:
Active connections: 291
server accepts handled requests #下面三個數(shù)分別對應accepts,handled,requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
Active connections:當前狀態(tài),活動狀態(tài)的連接數(shù)
accepts:統(tǒng)計總值,已經(jīng)接受的客戶端請求的總數(shù)
handled:統(tǒng)計總值,已處理完成的客戶端請求總數(shù),一般和accepts相同,除非拒絕
requests:統(tǒng)計總值,客戶端發(fā)來的總的請求數(shù)
Reading:當前狀態(tài),正在讀取客戶端請求報文首部的連接的連接數(shù)
Writing:當前狀態(tài),正在向客戶端發(fā)送響應報文過程中的連接數(shù)
Waiting:當前狀態(tài),正在等待客戶端發(fā)出請求的空閑連接數(shù)-
stub_status示例:
location /nginx_status { stub_status; allow 127.0.0.1; allow 172.16.0.0/16; deny all; }
小筆記:模塊
#訪問控制
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location / {
allow 192.168.37.6;
deny all;
}
}
#用戶的訪問控制
htpasswd -b -c /etc/nginx/conf.d/.nginx_passwd alice centos
htpasswd -b /etc/nginx/conf.d/.nginx_passwd bob centos
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location /admin {
root /data/;
allow 192.168.37.0/24;
deny all;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/conf.d/.nginx_passwd;
}
}
mkdir /data/admin/
echo /data/admin/index.html > /data/admin/index.html
#client
http://www.magedu.net/admin
curl -u bob:centos http://www.magedu.net/admin
#狀態(tài)頁
vim /etc/nginx/conf.d/test.conf
server_tokens off;
server {
server_name www.magedu.net;
root /data/site1/;
location /admin {
root /data/;
allow 192.168.37.0/24;
deny all;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/conf.d/.nginx_passwd;
}
location /nginx_status {
stub_status;
allow 127.0.0.1;
allow 172.16.0.0/16;
allow 192.168.37.0/24;
deny all;
}
}
#client
ab -c1000 -n 2000 www.magedu.net/m.html
http://www.magedu.net/nginx_status
nginx 第三方模塊
- 第三模塊是對nginx 的功能擴展,第三方模塊需要在編譯安裝nginx 的時候使用參數(shù)-- add-module=PATH指定路徑添加,有的模塊是由公司的開發(fā)人員針對業(yè)務需求定制 開發(fā)的,有的模塊是開源愛好者開發(fā)好之后上傳到github進行開源的模塊,nginx支持第三方模塊,需要重新編譯源碼才能支持
- 開源的echo模塊,實現(xiàn)輸出變量等信息
https://github.com/openresty/echo-nginx-module
示例:
yum install git –y
yum install gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
cd /usr/local/src
git clone https://github.com/openresty/echo-nginx-module.git
cd nginx-1.16.0/
useradd –r –s /sbin/nologin nginx
./configure \
--prefix=/apps/nginx \
--user=nginx --group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_perl_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--add-module=/usr/local/src/echo-nginx-module
make && make install
vim /apps/nginx/conf/conf.d/pc.conf
location /test {
index index.html;
default_type text/html;
echo "hello world,main-->";
echo_reset_timer;
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 1;
echo sub1;
}
location /sub2 {
echo_sleep 1;
echo sub2;
}
小筆記:第三方模塊
#按上面步驟先重新編譯nginx
#1.16 版本不兼容,改用1.14
vim /apps/nginx/conf/nginx.conf
http{
include /apps/nginx/conf.d/*.conf;
...
}
vim /apps/nginx/conf.d/test.conf
server_token off;
server {
server_name www.test.com;
root /data/test;
location /echo {
index index.html;
default_type text/html;
echo "hello world";
}
}
mkdir -p /data/test/echo
echo /data/test/index.html > /data/test/index.html
echo /data/test/echo/index.html > /data/test/echo/index.html
nginx -t
nginx
nginx 變量使用
nginx的變量可以在配置文件中引用,作為功能判斷或者日志等場景使用,變量可以分為內(nèi)置變量和自定義變量,內(nèi)置變量是由nginx模塊自帶,通過變量可以獲取到眾多的與客戶端訪問相關(guān)的值
-
常見內(nèi)置變量
$remote_addr;#存放了客戶端的地址,注意是客戶端的公網(wǎng)IP
$args;#變量中存放了URL中的指令
http://www.magedu.net/main/index.do?id=090&partner=search
以上:id=090&partner=search 即為 $args
$document_root;#保存了針對當前資源的請求的系統(tǒng)根目錄,如:/apps/nginx/html
$cookie_name; #表示key為 name 的cookie值
$document_uri;#保存了當前請求中不包含指令的URI,注意是不包含請求的指令,如http://www.magedu.net/main/index.do?id=090&partner=search會被定義為/main/index.do
$host;#存放了請求的host名稱
$http_user_agent;#客戶端瀏覽器的詳細信息
$http_cookie;#客戶端的cookie信息
$limit_rate;#如果nginx服務器使用limit_rate配置了顯示網(wǎng)絡速率,則會顯示,如果沒有設(shè)置, 則顯示0
$remote_port;#客戶端請求Nginx服務器時客戶端隨機打開的端口
$remote_user;#已經(jīng)經(jīng)過Auth Basic Module驗證的用戶名
$request_body_file;#做反向代理時發(fā)給后端服務器的本地資源的名稱
$request_method;#請求資源的方式,GET/PUT/DELETE等
$request_filename;#當前請求的資源文件的路徑名稱,由root或alias指令與
URI請求生成的文件絕對路徑,如/apps/nginx/html/main/index.html$request_uri;#包含請求參數(shù)的原始URI,不包含主機名
如:main/index.do?id=090&partner=search。
$scheme;#請求的協(xié)議,如ftp,https,http等
$server_protocol;#請求資源的協(xié)議版本,如HTTP/.0,HTTP/.,HTTP/.0等
$server_addr;#保存了服務器的IP地址
$server_name;#請求的服務器的主機名
$server_port;#請求的服務器的端口
自定義變量:
自定義變量名稱和值,使用指令set $variable value格式如下:
setname magedu;
echomy_port
my_port;
echo "server_port";
小筆記:變量
vim /apps/nginx/conf.d/test.conf
server_token off;
server {
server_name www.test.com;
root /data/test;
location /echo {
index index.html;
default_type text/html;
echo "hello world";
echo $remote_addr;
}
location /test {
index index.html;
default_type text/html;
echo "hello world,main-->";
echo_reset_timer;
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 1;
echo sub1;
}
location /sub2 {
echo_sleep 1;
echo sub2;
}
}
ngx_http_log_module
- ngx_http_log_module模塊
指定日志格式記錄請求 - log_format name string ...;
string可以使用nginx核心模塊及其它模塊內(nèi)嵌的變量 - access_log path [format [buffer=size] [gzip[=level]] [flush=time]
[if=condition]];
access_log off; #禁用訪問日志
訪問日志文件路徑,格式及相關(guān)的緩沖的配置
buffer=size
flush=time
示例
log_format compression '$remote_addr-$remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
access_log /spool/logs/nginx-access.log compression buffer=32k;
小筆記:nginx日志
#日志位置
/var/log/nginx/access.log
#自定義訪問日志
vim /etc/nginx/nginx.conf
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format testlog '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" ';
access_log /var/log/nginx/access.log main;
......
}
vim /etc/nginx/conf.d/test.conf
server_token off;
server {
server_name www.test.com;
root /data/test;
location / {}
access_log /var/log/nginx/magedu_net.access.log testlog;
}
自定義json日志格式
- nginx 的默認訪問日志記錄內(nèi)容相對比較單一,默認的格式也不方便后期做日志
統(tǒng)計分析,生產(chǎn)環(huán)境中通常將nginx日志轉(zhuǎn)換為json日志,然后配合使用ELK做日
志收集-統(tǒng)計-分析 - json格式的訪問日志示例:
{"@timestamp":"2019-02-
22T08:55:32+08:00","host":"192.168.7.102","clientip":"192.168.0.1","size":162,"resp
onsetime":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"www.magedu.net","uri":"/favicon.ico","domain":"www.magedu.net","xff"
:"-","referer":"-","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 6.1;
Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0","status":"404"}
log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
access_log /apps/nginx/logs/access_json.log access_json;
json格式的日志訪問統(tǒng)計
#cat nginx_json.py
#!/usr/bin/env python
#coding:utf-8
status_200= []
status_404= []
with open("access_json.log") as f:
for line in f.readlines():
line = eval(line)
if line.get("status") == "200":
status_200.append(line.get)
elif line.get("status") == "404":
status_404.append(line.get)
else:
print("狀態(tài)碼 ERROR")
f.close()
print "狀態(tài)碼200的有--:",len(status_200)
print "狀態(tài)碼404的有--:",len(status_404)
# python nginx_json.py
狀態(tài)碼200的有--: 1910
狀態(tài)碼404的有--: 13
關(guān)于favicon.ico
- favicon.ico 文件是瀏覽器收藏網(wǎng)址時顯示的圖標,當使用瀏覽器訪問頁面時,瀏覽器
會自己主動發(fā)起請求獲取頁面的favicon.ico文件,但是當瀏覽器請求的favicon.ico文
件不存在時,服務器會記錄404日志,而且瀏覽器也會顯示404報錯 - 解決方案:
- 服務器不記錄訪問日志:
location = /favicon.ico {
log_not_found off; #文件沒發(fā)現(xiàn)事件不記錄error_log
access_log off; #不記錄access_log
}
- 將圖標保存到指定目錄訪問:
#location ~ ^/favicon\.ico$ {
location = /favicon.ico {
root /data/nginx/html/pc/images;
}
ngx_http_log_module
- open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
緩存各日志文件相關(guān)的元數(shù)據(jù)信息
max:緩存的最大文件描述符數(shù)量
min_uses:在inactive指定的時長內(nèi)訪問大于等于此值方可被當作活動項
inactive:非活動時長
valid:驗證緩存中各緩存項是否為活動項的時間間隔
小筆記:自定義日志格式
#自定義日志格式
vim /etc/nginx/nginx.conf
http {
log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
access_log /var/log/nginx/access.log main;
......
}
vim /etc/nginx/conf.d/test.conf
server_token off;
server {
server_name www.test.com;
root /data/test;
location / {}
access_log /var/log/nginx/magedu_net.access.log access_json;
}
ngx_http_autoindex_module
配置文件下載服務
autoindex on | off;
自動文件索引功能,默為offautoindex_exact_size on | off;
計算文件確切大小(單位bytes),off 顯示大概大小(單位K、 M),默認onautoindex_localtime on | off ;
顯示本機時間而非GMT(格林威治)時間,默認off-
autoindex_format html | xml | json | jsonp;
顯示索引的頁面文件風格,默認html配置文件下載服務生產(chǎn)案例
location /download {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
autoindex_format json;
limit_rate 100k;
root /data/nginx/html/pc;
index index.html;
}
mkdir /data/nginx/html/pc/download/
ngx_http_gzip_module
- ngx_http_gzip_module
用gzip方法壓縮響應數(shù)據(jù),節(jié)約帶寬 - gzip on | off;
啟用或禁用gzip壓縮 - gzip_comp_level level;
壓縮比由低到高:1 到 9, 默認:1 - gzip_disable regex ...;
匹配到客戶端瀏覽器不執(zhí)行壓縮
示例:gzip_disable "MSIE[1-6]."; - gzip_min_length length;
啟用壓縮功能的響應報文大小閾值 - gzip_http_version 1.0 | 1.1;
設(shè)定啟用壓縮功能時,協(xié)議的最小版本,默認:1.1 - gzip_buffers number size;
支持實現(xiàn)壓縮功能時緩沖區(qū)數(shù)量及每個緩存區(qū)的大小
默認:32 4k 或 16 8k - gzip_types mime-type ...;
指明僅對哪些類型的資源執(zhí)行壓縮操作;即壓縮過濾器
默認包含有text/html,不用顯示指定,否則出錯 - gzip_vary on | off;
如果啟用壓縮,是否在響應報文首部插入“Vary: Accept-Encoding” - gzip_proxied off | expired | no-cache | no-store | private |
no_last_modified | no_etag | auth | any ...;
nginx充當代理服務器時,對于后端服務器的響應報文,在何種條件下啟
用壓縮功能
off:不啟用壓縮
expired,no-cache, no-store,private:對后端服務器的響應報文首部
Cache-Control值任何一個,啟用壓縮功能
示例:
gzip on;
gzip_comp_level 6;
gzip_min_length 64;
gzip_vary on;
gzip_types text/xml text/css application/javascript;
小筆記:充當文件下載服務
vim /etc/nginx/conf.d/test.conf
server {
server_name www.test.com;
root /data/test;
location / {}
access_log /var/log/nginx/test.com.access.log access_json;
location /download {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
#autoindex_format json; #html|xml|json|jsonp
limit_rate 100k;
index index.html;
}
}
mkdir /data/test/download
mount /dev/sr0 /data/test/download
小筆記:壓縮
vim /etc/nginx/conf.d/test.conf
server {
server_name www.test.com;
root /data/test;
location / {}
access_log /var/log/nginx/magedu_net.access.log access_json;
gzip on; #啟用壓縮
gzip_comp_level 6; #壓縮等級
gzip_min_length 64; #響應報文閾值
gzip_vary on; #響應報文首部插入“Vary: Accept-Encoding”
gzip_types text/xml text/css application/javascript; #壓縮類型
}
#client
curl --compressed http://www.magedu.net/m.html