32-高性能WEB服務NGINX(一)

本章內(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模型

image.png
  • 阻塞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模型

image.png
  • 用戶線程發(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多路復用模型

image.png
  • 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模型

image.png
  • 信號驅(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模型

image.png
  • 異步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

image.png
image.png
  • 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_Types

  • tcp_nodelay on | off;
    在keepalived模式下的連接是否啟用TCP_NODELAY選項,即Nagle算法
    當為off時,延遲發(fā)送,每發(fā)送一個包就需要確認ACK,才發(fā)送下一個包
    默認On時,不延遲發(fā)送,多個包才確認一次
    可用于:http, server, location

  • tcp_nopush on | off ;
    在開啟sendfile,on時合并響應頭和數(shù)據(jù)體在一個包中一起發(fā)送

  • sendfile on | off;
    是否啟用sendfile功能,在內(nèi)核中封裝報文直接發(fā)送,默認Off

  • charset 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說明: \d 表示 [0-9] ● 匹配優(yōu)先級機制從高到低 (1) 首先是字符串精確匹配 如:www.magedu.com (2) 左側(cè)*通配符 如:*.magedu.com (3) 右側(cè)*通配符 如:www.magedu.* (4) 正則表達式 如: ~^.*\.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ù)量,默認為100

  • keepalive_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ā)生錯誤的文件一類的信息,默認值為off

  • open_file_cache_min_uses number;
    open_file_cache指令的inactive參數(shù)指定的時長內(nèi),至少被命中此處指定的次數(shù)方可被歸類為活動項,默認值為1

  • open_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

  • 格式如下:
    set variable value; 支持:server, location, if 示例: setname magedu;
    echo name; setmy_port server_port; echomy_port;
    echo "server_name: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;
    自動文件索引功能,默為off

  • autoindex_exact_size on | off;
    計算文件確切大小(單位bytes),off 顯示大概大小(單位K、 M),默認on

  • autoindex_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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379