1 web服務基礎
1.1 正常情況的單次web服務訪問流程:
正常情況下,單次 Web 服務訪問流程從用戶在客戶端發起請求開始,到最終在客戶端展示內容結束,涉及客戶端、網絡傳輸、服務器端等多個環節,以下是詳細過程:
1.1.1 客戶端發起請求
1.用戶操作與URL解析:
用戶在瀏覽器地址欄輸入網址(如https://www.example.com
),或點擊網頁上的鏈接、提交表單等操作,觸發 Web 服務訪問。瀏覽器對輸入的 URL 進行解析,識別出協議(常見的有 HTTP、HTTPS)、域名(www.example.com
)、端口號(HTTP 默認 80,HTTPS 默認 443,若 URL 中未明確指定端口,瀏覽器會使用默認端口 )以及資源路徑(如/index.html
)。
2.DNS解析:
瀏覽器首先檢查本地的 DNS 緩存,如果緩存中有對應的域名 - IP 地址映射,則直接獲取 IP 地址;若沒有,就向本地 DNS 服務器發送查詢請求。本地 DNS 服務器會先查詢自身緩存,若未找到結果,它會向根 DNS 服務器、頂級 DNS 服務器、權威 DNS 服務器等依次進行遞歸或迭代查詢,最終將域名解析為對應的 IP 地址(例如192.168.1.100
),并將結果返回給瀏覽器。
1.1.2 建立連接
1.TCP三次握手(以HTTP協議基于tcp傳輸為例):
- 第一次握手:客戶端向服務器發送一個帶有 SYN(同步序列號)標志的 TCP 報文段,該報文段中包含客戶端隨機生成的初始序列號(假設為 x),表示客戶端請求與服務器建立連接。
- 第二次握手:服務器接收到客戶端的 SYN 報文后,返回一個帶有 SYN 和 ACK(確認應答)標志的 TCP 報文段。其中,ACK 標志表示對客戶端 SYN 的確認,確認號為客戶端初始序列號 x 加 1(即 x + 1);同時,服務器也生成自己的初始序列號(假設為 y),并將其放入 SYN 標志位中發送給客戶端。
- 第三次握手:客戶端收到服務器的 SYN + ACK 報文后,向服務器發送一個帶有 ACK 標志的 TCP 報文段,確認號為服務器的初始序列號 y 加 1(即 y + 1),序列號為客戶端的初始序列號 x 加 1(即 x + 1),表示客戶端確認收到服務器的響應并完成連接建立。至此,TCP 連接成功建立。
2.TLS/SSL握手(若使用HTTPS協議):
在 TCP 連接建立后,客戶端和服務器之間會進行 TLS/SSL 握手,以協商加密算法、交換公鑰證書等,確保數據傳輸的安全性。具體步驟如下:
- 客戶端發送ClientHello消息:包含客戶端支持的 SSL/TLS 版本、加密算法列表、隨機數等信息。
- 服務器響應ServerHello消息:服務器從客戶端提供的選項中選擇合適的 SSL/TLS 版本和加密算法,并返回自己的證書(包含公鑰)、隨機數等信息。
- 客戶端驗證服務器證書:客戶端檢查服務器證書的有效性(如證書是否過期、頒發機構是否可信等),并從中提取服務器的公鑰。
- 客戶端生成預主密鑰:客戶端使用服務器的公鑰加密一個隨機生成的預主密鑰,并發送給服務器。
- 服務器解密預主密鑰:服務器使用自己的私鑰解密收到的預主密鑰,然后客戶端和服務器雙方使用預主密鑰、之前交換的隨機數等信息,生成會話密鑰,用于后續的數據加密傳輸。
具體加密原理請參考:加密(一)- 阮一峰:RSA算法原理_rsa 阮一峰-CSDN博客https://blog.csdn.net/yiguang_820/article/details/108842637
1.1.3 發送http請求
TCP 連接建立后,客戶端通過該連接向服務器發送 HTTP 請求報文,請求報文主要包括:
- 請求行:包含請求方法(常見的有 GET、POST、PUT、DELETE 等,例如 GET 方法用于獲取資源,POST 方法用于提交數據 )、請求的資源路徑(如
/index.html
)以及 HTTP 協議版本(如 HTTP/1.1 )。 - 請求頭:包含一系列鍵值對,提供了關于客戶端、請求內容等的元信息。
- 請求體:當請求方法為 POST、PUT 等需要提交數據的方法時,請求體中包含了要發送的數據,例如表單數據(格式如
name=John&age=30
)或 JSON 格式的數據(如{"username": "John", "password": "123456"}
)。
1.1.4 服務器處理請求
- Web服務器接收與解析:Web 服務器(如 Apache、Nginx 等)在指定端口(如 80 或 443 )監聽并接收客戶端發送的 HTTP 請求報文,然后對請求報文進行解析,提取請求方法、資源路徑等關鍵信息。
- 請求分發與處理:
- 靜態資源請求:如果請求的是靜態資源(如 HTML 文件、CSS 樣式表、圖片、JavaScript 腳本等),Web 服務器會根據資源路徑在本地文件系統中查找對應的文件,并直接將其讀取出來,準備返回給客戶端。
- 動態資源請求:對于動態資源請求(例如請求一個 PHP 腳本、Python Flask 應用的接口等),Web 服務器會將請求轉發給相應的應用服務器(如 PHP-FPM、Gunicorn、Tomcat 等 )。應用服務器根據請求內容執行相應的業務邏輯,這可能涉及與數據庫進行交互(例如查詢用戶信息、獲取商品列表等 )。應用服務器通過數據庫驅動程序(如 MySQL Connector/Python )連接到數據庫(如 MySQL、PostgreSQL 等 ),執行 SQL 查詢或操作,獲取或更新數據,然后將處理結果返回給 Web 服務器。
1.1.5 服務器返回響應
- 構建響應報文:Web 服務器接收到應用服務器返回的處理結果(如果是動態請求)或獲取到靜態資源后,構建 HTTP 響應報文。響應報文主要包括:
- 狀態行:包含 HTTP 協議版本、狀態碼(如 200 表示請求成功,404 表示資源未找到,500 表示服務器內部錯誤等 )以及狀態描述(如
OK
)。 - 響應頭:包含一系列鍵值對,提供關于響應的元信息。
- 響應體:包含了實際要返回給客戶端的內容,對于靜態資源請求,可能是 HTML 頁面、CSS 文件、圖片等的二進制數據;對于動態請求,可能是 JSON 格式的數據、渲染后的 HTML 頁面等。
- 發送響應:Web 服務器通過已建立的 TCP 連接,將構建好的 HTTP 響應報文發送回客戶端。
1.1.6 客戶端接收與渲染
- 接收響應:客戶端通過 TCP 連接接收服務器發送的 HTTP 響應報文,根據響應頭中的
Content-Length
等信息,確定接收數據的大小,并將數據完整地接收下來。 - 解析與渲染:
- 響應狀態檢測:客戶端首先檢查響應的狀態碼,如果是 200 - 299 范圍內的狀態碼,表示請求成功;如果是其他范圍的狀態碼,可能意味著請求失敗,客戶端會根據狀態碼的含義進行相應的處理,例如顯示錯誤頁面。
- 響應頭處理:客戶端解析響應頭中的信息,如
Content-Type
,根據內容類型調用相應的渲染引擎。例如,如果是text/html
,則調用 HTML 渲染引擎;如果是image/jpeg
,則調用圖片解碼和顯示模塊。 - 響應體渲染:對于 HTML 頁面,瀏覽器會構建 DOM 樹,解析 CSS 樣式表并應用樣式,執行 JavaScript 腳本,最終在瀏覽器窗口中呈現出完整的網頁內容;對于 JSON 數據等,客戶端可能會根據業務邏輯進行數據處理和展示。
1.1.7 關閉連接
TCP四次揮手(默認情況下):
當數據傳輸完成后,客戶端和服務器之間會進行 TCP 四次揮手來關閉連接:
- 第一次揮手:客戶端發送一個帶有 FIN(結束標志)的 TCP 報文段,表示客戶端不再發送數據,但還可以接收數據。
- 第二次揮手:服務器接收到客戶端的 FIN 報文后,返回一個帶有 ACK 標志的 TCP 報文段,確認收到客戶端的 FIN 請求。
- 第三次揮手:服務器發送一個帶有 FIN 標志的 TCP 報文段,表示服務器也不再發送數據。
- 第四次揮手:客戶端接收到服務器的 FIN 報文后,返回一個帶有 ACK 標志的 TCP 報文段,確認收到服務器的 FIN 請求,至此,TCP 連接完全關閉。
HTTP長連接(若啟用):在 HTTP/1.1 協議中,默認啟用了 HTTP 長連接(通過Connection: keep-alive
頭字段標識 ),這意味著在一次請求 - 響應完成后,TCP 連接不會立即關閉,而是可以被復用,用于后續的 HTTP 請求,這樣可以減少建立和關閉連接的開銷,提高性能。
1.2 web服務介紹
1.2.1 Apache經典的web服務端
1.2.1.1 Apache prefork模型
- 預派生模式,有一個主控制進程,然后生成多個子進程,使用select模型,最大并發1024
- 每個子進程有一個獨立的線程響應用戶請求
- 相對比較占用內存,但是比較穩定,可以設置最大和最小進程數

1.2.1.2 Apache worker模型
- 一種多進程和多線程混合的模型
- 有一個控制進程,啟動多個子進程
- 每個子進程里面包含固定的線程
- 使用線程來處理請求
- 當線程不夠使用的時候會再啟動一個新的子進程,然后在進程里面再啟動線程處理請求
- 由于其使用了線程處理請求,因此可以承受更高的并發

1.2.1.3 Apache event模型
- Apache中最新的模式,2012年發布的apache 2.4.X系列正式支持event 模型,屬于事件驅動模型(epoll) 每個進程響應多個請求,在現在版本里的已經是穩定可用的模式
- 它和worker模式很像,最大的區別在于,它解決了keepalive場景下長期被占用的線程的資源浪費問題(某些線程因為被keepalive,空掛在哪里等待,中間幾乎沒有請求過來,甚至等到超時)
- event MPM中,會有一個專門的線程來管理這些keepalive類型的線程
- 當有真實請求過來的時候,將請求傳遞給服務線程,執行完畢后,又允許它釋放。這樣增強了高并發場景下的請求處理能力

1.2.2 nginx-高性能的web服務端
1.2.3 用戶訪問體驗和性能
1.2.3.1 影響用戶體驗的因素
1.客戶端:
- 客戶端硬件配置
- 客戶端網絡速率
- 客戶端與服務端距離
2.服務器:
- 服務端網絡速率
- 服務端硬件配置
- 服務端架構設計
- 服務端應用程序工作模式
- 服務端并發數量,服務端響應文件大小及數量
- 服務端I/O壓力
1.2.4 服務端I/O流程
- 磁盤I/O
- 網絡I/O:一切皆文件,本質是對socket文件的讀寫
1.2.4.1 磁盤I/O
機械磁盤的尋道時間、旋轉延遲和數據傳輸時間:尋道時間:是指磁頭移動到正確的磁道上所花費的時間,尋道時間越短則I/O處理就越快,目前磁盤的尋道時間一般在3-15毫秒左右。旋轉延遲:是指將磁盤片旋轉到數據所在的扇區到磁頭下面所花費的時間,旋轉延遲取決于磁盤的轉速,通常使用磁盤旋轉一周所需要時間的1/2之一表示,比如7200轉的磁盤平均訓傳延遲大約為60*1000/7200/2=4.17毫秒,公式的意思為 (每分鐘60秒*1000毫秒每秒/7200轉每分/2),如果是15000轉的則為60*1000/15000/2=2毫秒。數據傳輸時間:指的是讀取到數據后傳輸數據的時間,主要取決于傳輸速率,這個值等于數據大小除以傳輸速率,目前的磁盤接口每秒的傳輸速度可以達到600MB,因此可以忽略不計。常見的機械磁盤平均尋道時間值:7200轉/分的磁盤平均物理尋道時間:9毫秒10000轉/分的磁盤平均物理尋道時間:6毫秒15000轉/分的磁盤平均物理尋道時間:4毫秒常見磁盤的平均延遲時間:7200轉的機械盤平均延遲:60*1000/7200/2 = 4.17ms10000轉的機械盤平均延遲:60*1000/10000/2 = 3ms15000轉的機械盤平均延遲:60*1000/15000/2 = 2ms每秒最大IOPS的計算方法:7200轉的磁盤IOPS計算方式:1000毫秒/(9毫秒的尋道時間+4.17毫秒的平均旋轉延遲時間)=1000/13.13=75.9 IOPS10000轉的磁盤的IOPS計算方式:1000毫秒/(6毫秒的尋道時間+3毫秒的平均旋轉延遲時間)=1000/9=111IOPS15000轉的磁盤的IOPS計算方式:15000毫秒/(4毫秒的尋道時間+2毫秒的平均旋轉延遲時間)=1000/6=166.6 IOPS
1.2.4.2 網絡I/O

網絡I/O處理過程
- 獲取請求數據,客戶端與服務器建立連接發出請求,服務器接受請求
- 構建響應,當服務器接收完請求,并在用戶空間處理客戶端的請求,直到構建響應完成
- 返回數據,服務器將已構建好的響應再通過內核空間的網絡I/O發還給客戶端
不論磁盤和網絡I/O
每次I/O,都要經過兩個階段:
- 將數據從文件先加載到內核內存空間(緩沖區),等待數據準備完成,時間較長
- 將數據從內核緩沖區復制到用戶空間的進程內存中,時間較短
1.3 I/O模型
1.3.1 I/O模型概念
同步/異步:關注的是消息通信機制,即調用者在等待一件事情的處理結果時,被調用者是否提供完成狀態的通知。
- 同步:synchronous,被調用者并不提供事件的處理結果相關的通知消息,需要調用者主動詢問事情是否處理完成
- 異步:asynchronous,被調用者通過狀態、通知或回調機制主動通知調用者被調用者的運行狀態
阻塞/非阻塞:關注調用者在等待結果返回之前的狀態
- 阻塞:blocking,指IO操作需要徹底完成后才返回到用戶空間,調用結果返回之前,調用者被掛起,干不了別的事情。
- 非阻塞:nonblocking,指IO操作被調用后立即返回給用戶一個狀態值,而無需等到IO操作徹底完成,在最終的調用結果返回之前,調用者不會被掛起,可以去做別的事情
1.3.2 網絡I/O模型
1.3.2.1 阻塞型I/O模型(blocking IO)
- 用戶線程在內核進行IO操作時被阻塞
- 用戶線程通過系統調用read發起I/O讀操作,由用戶空間轉到內核空間。內核等到數據包到達后,然后將接收的數據拷貝到用戶空間,完成read操作
- 用戶需要等待read將數據讀取到buffer后,才繼續處理接收的數據。整個I/O請求的過程中,用戶線程是被阻塞的,這導致用戶在發起IO請求時,不能做任何事情,對CPU的資源利用率不夠
1.3.2.2 非阻塞型I/O模型(nonblocking IO)

1.3.2.3 多路復用I/O型(I/O multiplexing)
- 上面的模型中,每一個文件描述符對應的IO是由一個線程監控和處理
- 多路復用IO指一個線程可以同時(實際是交替實現,即并發完成)監控和處理多個文件描述符對應各自的IO,即復用同一個線程
- 一個線程之所以能實現同時處理多個IO,是因為這個線程調用了內核中的SELECT,POLL或EPOLL等系統調用,從而實現多路復用IO

- 優點:可以基于一個阻塞對象,同時在多個描述符上等待就緒,而不是使用多個線程(每個文件描述符一個線程),這樣可以大大節省系統資源
- 缺點:當連接數較少時效率相比多線程+阻塞 I/O 模型效率較低,可能延遲更大,因為單個連接處理需要 2 次系統調用,占用時間會有增加
- 當客戶端處理多個描述符時(一般是交互式輸入和網絡套接口),必須使用I/O復用
- 當一個客戶端同時處理多個套接字時,此情況可能的但很少出現
- 當一個服務器既要處理監聽套接字,又要處理已連接套接字,一般也要用到I/O復用
- 當一個服務器即要處理TCP,又要處理UDP,一般要使用I/O復用
- 當一個服務器要處理多個服務或多個協議,一般要使用I/O復用
1.3.2.4 信號驅動式I/O模型(signal-drven IO)
1.3.2.5 異步I/O模型(asynchronous IO)
1.3.3 五種IO對比
1.3.4 I/O的具體實現方式
1.3.4.1 I/O常見實現
- select:select庫是在linux和windows平臺都基本支持的 事件驅動模型庫,并且在接口的定義也基本相同,只是部分參數的含義略有差異,最大并發限制1024,是最早期的事件驅動模型。
- poll:在Linux 的基本驅動模型,windows不支持此驅動模型,是select的升級版,取消了最大的并發限制,在編譯nginx的時候可以使用--with-poll_module和--without-poll_module這兩個指定是否編譯select庫。
- epoll:epoll是庫是Nginx服務器支持的最高性能的事件驅動庫之一,是公認的非常優秀的事件驅動模型,它和select和poll有很大的區別,epoll是poll的升級版,但是與poll有很大的區別.epoll的處理方式是創建一個待處理的事件列表,然后把這個列表發給內核,返回的時候在去輪詢檢查這個表,以判斷事件是否發生,epoll支持一個進程打開的最大事件描述符的上限是系統可以打開的文件的最大數,同時epoll庫的I/O效率不隨描述符數目增加而線性下降,因為它只會對內核上報的“活躍”的描述符進行操作。
- kqueue:用于支持BSD系列平臺的高校事件驅動模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0級以上版本NetBSD級以上版本及Mac OS X 平臺上,該模型也是poll庫的變種,因此和epoll沒有本質上的區別,都是通過避免輪詢操作提供效率。
- Iocp:Windows系統上的實現方式,對應第5種(異步I/O)模型。
- rtsig:不是一個常用事件驅動,最大隊列1024,不是很常用
- /dev/poll:用于支持unix衍生平臺的高效事件驅動模型,主要在Solaris 平臺、HP/UX,該模型是sun公司在開發Solaris系列平臺的時候提出的用于完成事件驅動機制的方案,它使用了虛擬的/dev/poll設備,開發人員將要見識的文件描述符加入這個設備,然后通過ioctl()調用來獲取事件通知,因此運行在以上系列平臺的時候請使用/dev/poll事件驅動機制。
- eventport:該方案也是sun公司在開發Solaris的時候提出的事件驅動庫,只是Solaris 10以上的版本,該驅動庫看防止內核崩潰等情況的發生。
1.3.4.2 常用I/O模型比較
select | poll | epoll | |
操作方式 | 遍歷 | 遍歷 | 回調 |
底層實現 | 數組 | 鏈表 | 哈希表 |
IO效率 | 每次調回都進行線性遍歷,時間復雜度為O(n) | 同左 | 事件通知方式,每當fd就緒,系統注冊的回調函數就會被調用,將就緒的fd放到rdlist里,時間復雜度O(1) |
最大連接數 | 1024(x86) 2048(x64) | 無上限 | 無上限 |
fd拷貝 | 每次調用select都需要把fd集合從用戶拷貝到內核態 | 每次調用poll,都需要把fd集合從用戶態拷貝到內核態 | 調用epoll_ct時拷貝進內核并保存,之后每次epoll_wait不拷貝 |
1.4 零拷貝
1.4.1 零拷貝介紹
1.4.1.1 傳統Linux中I/O的問題
1.4.1.2 什么是零拷貝
1.4.2 零拷貝相關技術
1.4.2.1 MMAP(Memory Mapping)
1.4.2.2 SENDFILE
1.4.2.3 DMA輔助的SENDFILE
2 Nginx架構和安裝
2.1 Nginx概述
2.1.1 nginx介紹
- Tengine:由淘寶網發起的Web服務器項目。它在Nginx的基礎上,針對大訪問量網站的需求,添加了很多高級功能和特性。Tengine的性能和穩定性已經在大型的網站如淘寶網,天貓商城等得到了很好的檢驗。它的最終目標是打造一個高效、穩定、安全、易用的Web平臺。從2011年12月開始,Tengine成為一個開源項目官網: http://tengine.taobao.org/
- OpenResty:基于 Nginx 與 Lua 語言的高性能 Web 平臺, 章亦春團隊開發,官網:http://openresty.org/cn/
2.1.2 nginx功能介紹
- 靜態web資源服務器html,圖片,js,css,txt等靜態資源
- http/https協議的反向代理
- 結合FastCGI/uWSGI/SCGI等協議反向代理動態資源請求
- tcp/udp協議的轉發請求轉發(反向代理)
- imap4/pop3協議的反向代理
2.2.3 基礎特性
- 模塊化設計,較好的擴展性
- 高可靠性
- 支持熱部署:不停機更新配置文件,升級版本,更換日志文件
- 低內存消耗:10000個keep-alive連接模式下的非活動連接,僅需2.5M內存
- event-driven,aio,mmap,sendfile
2.2.4 web服務相關的功能
2.2 nginx架構和進程
- 虛擬主機(server)
- 支持keep-alive和管道連接(利用一個連接做多次請求)
- 訪問日志(支持基于日志緩沖提高其性能)
- url rewirte
- 路徑別名
- 基于IP及用戶的訪問控制
- 支持速率限制及并發數限制
- 重新配置和在線升級而無需中斷客戶的工作進程
2.2.2 nginx進程結構
web請求處理機制:
- 多進程方式:服務器每接收到一個客戶端請求就有服務器的主進程生成一個子進程響應客戶端,直到用戶關閉連接,這樣的優勢是處理速度快,子進程之間相互獨立,但是如果訪問過大會導致服務器資源耗盡而無法提供請求
- 多線程方式:與多進程方式類似,但是每收到一個客戶端請求會有服務進程派生出一個線程和此客戶端進行交互,一個線程的開銷遠遠小于一個進程,因此多線程方式在很大程度減輕了web服務器對系統資源的要求,但是多線程也有自己的缺點,即當多個線程位于同一個進程內工作的時候,可以相互訪問同樣的內存地址空間,所以他們相互影響,一旦主進程掛掉則所有子線程都不能工作了,IIS服務器使用了多線程的方式,需要間隔一段時間就重啟一次才能穩定。

主進程(master)的功能:
- 對外接口:接收外部的操作(信號)
- 對內轉發:根據外部的操作的不同,通過信號管理worker
- 監控:監控worker進程的運行狀態,worker進程異常終止后,自動重啟worker進程
- 讀取nginx配置文件并驗證其有效性和正確性
- 建立、綁定和關閉socker連接
- 按照配置生成、管理和結束工作進程
- 接收外界指令,如重啟、升級及退出服務器等指令
- 不中斷服務,實現平滑升級,重啟服務并應用新的配置
- 開啟日志文件,獲取文件描述符
- 不中斷服務,實現平滑升級,升級失敗進行回滾處理
- 編譯和處理perl腳本
工作進程(worker)的功能:
- 所有worker進程都是平等的
- 實際處理:網絡請求,由worker進程處理
- worker進程數量:一般設置為核心數,充分利用CPU資源,同時避免進程數量過多,導致進程競爭CPU資源
- 增加上下文切換的損耗
- 接受處理客戶的請求
- 將請求依次送入各個功能模塊進行處理
- I/O調用,獲取響應數據
- 與后端服務器通信,接收后端服務器的處理結果
- 緩存數據,訪問緩存索引,查詢和調用緩存數據
- 發送請求結果,響應客戶的請求
- 接收主程序指令,比如重啟、升級和退出等
2.2.3 nginx進程間通信
worker進程之間的通信原理基本上和主進程與worker進程之間的通信是一樣的,只要worker進程之間能夠取得彼此的信息,建立管道即可通信,但是由于worker進程之間是完全隔離的,因此一個進程想要知道另外一個進程的狀態信息,就只能通過主進程來實現。為了實現worker進程之間的交互,master進程在生成worker進程之后,在worker進程表中進行遍歷,將該新進程的PID以及針對該進程建立的管道句柄傳遞給worker進程中的其他進程,為worker進程之間的通信做準備,當worker進程1向worker進程2發送指令的時候,首先在master進程給它的其他worker進程工作信息中找到2的進程PID,然后將正確的指令寫入指向進程2的管道,worker進程2捕獲到管道中的事件后,解析指令并進行相關操作,這樣就完成了worker進程之間的通信。另worker進程可以通過共享內存來通訊的,比如upstream中的zone,或者limit_req、limit_conn中的zone等。操作系統提供了共享內存機制。
2.2.4 nginx啟動和HTTP連接建立
2.3 nginx模塊介紹
nginx有多種模塊:
- nginx啟動時,master進程加載配置文件
- master進程,初始化監聽的socket
- master進程,fork出多個worker進程
- worker進程,競爭新的連接,獲勝方通過三次握手,建立socket連接,并處理請求
- 核心模塊:是 Nginx 服務器正常運行必不可少的模塊,提供錯誤日志記錄 、配置文件解析 、事件驅動機制 、進程管理等核心功能
- 標準HTTP模塊:提供 HTTP 協議解析相關的功能,比如: 端口配置 、 網頁編碼設置 、 HTTP響應頭設置等
- 可選HTTP模塊:主要用于擴展標準的 HTTP 功能,讓 Nginx 能處理一些特殊的服務,比如: Flash多媒體傳輸 、解析 GeoIP 請求、 網絡傳輸壓縮 、 安全協議 SSL 支持等
- 郵件服務模塊:主要用于支持 Nginx 的 郵件服務 ,包括對 POP3 協議、 IMAP 協議和 SMTP協議的支持
- Stream服務模塊: 實現反向代理功能,包括TCP協議代理
- 第三方模塊:是為了擴展 Nginx 服務器應用,完成開發者自定義功能,比如: Json 支持、 Lua 支持等
核心模塊:core module
標準模塊:HTTP模塊:ngx_http_*HTTP Core modulesHTTP Optional modules # 需編譯時指定Mail模塊:ngx_mail_*Stream模塊:ngx_stream_*
參考:勿忘初心,進無止盡!https://www.cnblogs.com/Soy-technology/p/11355597.html
2.4 nginx安裝
2.4.1 nginx版本和安裝方式
nginx版本:
- Mainline version 主要開發版本,一般為奇數版本號,如1.19
- Stable version 當前最穩定版本,一般為偶數版本,如1.20
- Legacy version 舊的穩定版,一般為偶數版本,如1.18
nginx安裝可以使用yum或源碼安裝,但是推薦使用源碼編譯安裝
2.4.2 nginx編譯安裝
編譯器介紹:
- yum的版本比較舊
- 編譯安裝可以更方便自定義相關路徑
- 使用源碼編譯可以自定義相關功能,更方便業務上的使用
2.4.2.1 編譯安裝nginx
官方源碼包下載地址:

編譯安裝示例:
注意:編譯安裝前請確保SELinux和防火墻為關閉狀態,本地yum或網絡yum配置正常,網絡通暢
[root@Nginx ~]# yum install gcc pcre-devel zlib-devel openssl-devel -y
[root@Nginx ~]# tar zxf nginx-1.24.0.tar.gz
[root@Nginx ~]# cd nginx-1.24.0
[root@Nginx nginx-1.24.0]# useradd -s /sbin/nologin -M nginx
[root@Nginx nginx-1.24.0]# ls # 查看是否有下面類似的文件
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README[root@Nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \ # 指定 Nginx 的安裝目錄為 /usr/local/nginx
--user=nginx \ # 指定nginx運行用戶
--group=nginx \ # 指定nginx運行組
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透傳
--with-http_stub_status_module \ # 支持狀態頁面
--with-http_gzip_static_module \ # 支持壓縮
--with-pcre \ # 支持正則
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透傳ip[root@Nginx nginx-1.24.0]# make && make install
nginx完成安裝后有四個主要目錄
[root@Nginx nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbinconf:保存nginx所有的配置文件,其中nginx.conf是nginx服務器的最核心最主要的配置文件,其他
的.conf則是用來配置nginx相關的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params
兩個文件,配置文件一般都有一個樣板配置文件,是以.default為后綴,使用時可將其復制并將default后綴
去掉即可。html目錄中保存了nginx服務器的web文件,但是可以更改為其他目錄保存web文件,另外還有一個50x的web
文件是默認的錯誤頁面提示頁面。logs:用來保存nginx服務器的訪問日志錯誤日志等日志,logs目錄可以放在其他路徑,比
如/var/logs/nginx里面。sbin:保存nginx二進制啟動腳本,可以接受不同的參數以實現不同的功能。
2.4.2.2 驗證版本及編譯參數
# 將 Nginx 的可執行程序目錄(/usr/local/nginx/sbin)添加到系統環境變量 PATH 中
[root@Nginx ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@Nginx ~]# source ~/.bash_profile # 使剛修改的環境變量配置立即生效[root@Nginx ~]# nginx -V # 查看 Nginx 的版本信息和編譯配置參數
nginx version: nginx/1.24.0
built by gcc 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --group=nginx --with-http_ssl_module --with-http_v2_module -
-with-http_realip_module --with-http_stub_status_module --withhttp_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --
with-stream_realip_module
2.4.2.3 使用安裝完成的二進制文件nginx
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf # 編輯 Nginx 的主配置文件
[root@Nginx ~]# nginx -g "worker_processes 4;" # 啟動 Nginx 服務并臨時指定工作進程數為4
[root@Nginx ~]# ps aux | grep nginx # 查看當前系統中與 nginx 相關的進程狀態
2.4.2.4 nginx啟動文件
為 Nginx 創建一個 systemd 服務配置文件,以便通過系統服務管理器來管理 Nginx(啟動、停止、開機自啟等)
[root@Nginx ~]# vim /lib/systemd/system/nginx.service
[Unit]
# 服務描述信息,說明這是 Nginx HTTP 服務器和反向代理服務
Description=The NGINX HTTP and reverse proxy server
# 指定 Nginx 啟動的依賴順序,需在這些服務(系統日志、網絡、遠程文件系統、DNS 解析)啟動之后再啟動 Nginx
After=syslog.target network-online.target remote-fs.target nss-lookup.target
# 期望網絡就緒后再啟動nginx
Wants=network-online.target
[Service]
Type=forking # Nginx 是fork模式啟動(主進程會創建子進程,主進程退出后子進程繼續運行)
PIDFile=/usr/local/nginx/logs/nginx.pid # 指定Nginx主進程PID文件路徑(與nginx.conf中pid配置一致)
ExecStartPre=/usr/local/nginx/sbin/nginx -t # 啟動前執行的命令,nginx -t用于檢查配置文件語法是否正確,確保配置無誤后才啟動
ExecStart=/usr/local/nginx/sbin/nginx # 啟動Nginx的命令(執行 Nginx 二進制文件)
ExecReload=/usr/local/nginx/sbin/nginx -s reload # 重載配置的命令(nginx -s reload 平滑重啟,不中斷服務)
ExecStop=/bin/kill -s QUIT $MAINPID # 停止服務的命令
PrivateTmp=true # 為Nginx分配獨立的臨時目錄
[Install]
WantedBy=multi-user.target
[root@Nginx ~]# systemctl daemon-reload # 重新加載systemd服務配置,使新創建的nginx.service生效
[root@Nginx ~]# systemctl start nginx # 啟動Nginx服務
2.6 平滑升級和回滾
2.6.1 平滑升級流程
- 將舊Nginx二進制文件換成新Nginx程序文件(注意先備份)
- 向master進程發送USR2信號
- master進程修改pid文件名加上后綴.oldbin,成為nginx.pid.oldbin
- master進程用新Nginx文件啟動新master進程成為舊master的子進程,系統中將有新舊兩個Nginx主進程共同提供Web服務,當前新的請求仍然由舊Nginx的worker進程進行處理,將新生成的master進程的PID存放至新生成的pid文件nginx.pid
- 向舊的Nginx服務進程發送WINCH信號,使舊的Nginx worker進程平滑停止
- 向舊master進程發送QUIT信號,關閉老master,并刪除Nginx.pid.oldbin文件
- 如果發現升級有問題,可以回滾∶向老master發送HUP,向新master發送QUIT
2.6.2 平滑升級和回滾案例
[root@Nginx nginx]# tar zxf nginx-1.26.1.tar.gz
[root@Nginx nginx]# cd nginx-1.26.1/
#開始編譯新版本
[root@Nginx nginx-1.26.1]# ./configure --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
[root@Nginx nginx-1.26.1]# make
#查看兩個版本
[root@Nginx nginx-1.26.1]# ll objs/nginx /usr/local/nginx/sbin/nginx
-rwxr-xr-x 1 root root 1239416 Jul 18 15:08 objs/nginx
-rwxr-xr-x 1 root root 5671488 Jul 18 11:41 /usr/local/nginx/sbin/nginx
#把之前的舊版的nginx命令備份
[root@Nginx ~]# cd /usr/local/nginx/sbin/
[root@Nginx sbin]# cp nginx nginx.24
#把新版本的nginx命令復制過去
[root@Nginx sbin]# cp -f /root/nginx/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin
#檢測一下有沒有問題
[root@Nginx sbin]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful[root@Nginx sbin]# ps aux | grep nginx # 查看進程ID
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 48733 0.0 0.2 14200 4868 ? S 14:17 0:00 nginx: worker
process
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52076 0.0 0.2 14208 4868 ? S 15:41 0:00 nginx: worker
process[root@Nginx sbin]# kill -USR2 48732 #nginx worker ID
#USR2 平滑升級可執行程序,將存儲有舊版本主進程PID的文件重命名為nginx.pid.oldbin,并啟動新的nginx
#此時兩個master的進程都在運行,只是舊的master不在監聽,由新的master監聽80
#此時Nginx開啟一個新的master進程,這個master進程會生成新的worker進程,這就是升級后的Nginx進
#程,此時老的進程不會自動退出,但是當接收到新的請求不作處理而是交給新的進程處理。[root@Nginx sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 # 此時依舊是舊版本生生效
Date: Thu, 18 Jul 2025 07:45:58 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2025 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes#回收舊版本
[root@Nginx sbin]# kill -WINCH 48732 # 減少工作進程數量,主進程保持運行,跟舊主進程ID
[root@Nginx sbin]# ps aux | grep nginx
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52076 0.0 0.2 14208 4868 ? S 15:41 0:00 nginx: worker
process
#檢測版本信息
[root@Nginx sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.26.1 #新版本生效
Date: Thu, 18 Jul 2025 07:59:45 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2025 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes#回滾
#如果升級的版本發現問題需要回滾,可以重新拉起舊版本的worker
[root@Nginx sbin]# cp nginx nginx.26
[root@Nginx sbin]# ls
nginx nginx.24 nginx.26
[root@Nginx sbin]# mv nginx.24 nginx
mv: overwrite 'nginx'? y# kill -HUP ID
# 檢查新配置文件的語法是否正確(若錯誤則不重載,保持舊配置運行)。
# 用新配置啟動新的工作進程。
# 逐步關閉舊工作進程(等待它們處理完當前請求)。
[root@Nginx sbin]# kill -HUP 48732
[root@Nginx sbin]# ps aux | grep nginx
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52076 0.0 0.2 14208 5124 ? S 15:41 0:00 nginx: worker
process
nobody 52130 0.0 0.2 14200 4868 ? S 16:30 0:00 nginx: worker
process
[root@Nginx sbin]# kill -WINCH 52075
[root@Nginx sbin]# ps aux | grep nginx
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52130 0.0 0.2 14200 4868 ? S 16:30 0:00 nginx: worker
process
root 52137 0.0 0.1 221664 2176 pts/0 S+ 16:31 0:00 grep --
color=auto nginx
[root@Nginx sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 ##版本回滾完成
Date: Thu, 18 Jul 2025 08:31:51 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2025 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes
3 nginx核心配置詳解
3.1 配置文件說明
nginx官方幫助文檔:nginx documentationhttp://nginx.org/en/docs/
nginx配置文件的組成部分:
- 主配置文件:nginx.conf
- 子配置文件:include conf.d/*.conf
- fastcgi,uwsgi,scgi等協議相關的配置文件
- mime.types:支持的mime類型,MIME(Multipurpose Internet Mail Extensions)多用途互聯網郵件擴展類型,MIME消息能包含文本、圖像、音頻、視頻以及其他應用程序專用的數據,是設定某種擴展名的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應用程序來打開。多用于指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
nginx配置文件格式說明:
- 配置文件由指令與指令塊構成
- 每條指令以;分號結尾,指令與值之間以空格符號分隔
- 可以將多條指令放在同一行,用分號分隔即可,但可讀性差,不推薦
- 指令塊以{ }大括號將多條指令組織在一起,且可以嵌套指令塊
- include語句允許組合多個配置文件以提升可維護性
- 使用#符號添加注釋,提高可讀性
- 使用$符號使用變量
- 部分指令的參數支持正則表達式
nginx主配置文件的配置指令方式:
main block:主配置段,即全局配置段,對http,mail都有效
#事件驅動相關的配置
event {
...
}#http/https 協議相關配置段
http {
默認的nginx.conf 配置文件格式說明
...
}#默認配置文件不包括下面兩個塊
#mail 協議相關配置段
mail {
...
}#stream 服務器相關配置段
stream {
...
}
默認的nginx.conf配置文件格式說明:
# 全局配置端,對全局生效,主要設置nginx的啟動用戶/組,啟動的工作進程數量,工作模式,Nginx的PID路
徑,日志路徑等。
user nobody; # 這里使用nginx
worker_processes 1; # 指定工作進程數量,一般設置為auto# error_log 文件路徑 日志級別;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;#pid logs/nginx.pid; # 指定主進程PID文件路徑# events塊專門用于設置Nginx與客戶端連接相關的底層參數,決定了Nginx如何處理網絡事件(如接收連接、處理請求等),這些配置直接影響 Nginx 的并發處理能力
events {worker_connections 1024; # 設置單個nginx工作進程可以接受的最大并發# 作為web服務器的時候最大并發數為# worker_processes * worker_connections# 作為反向代理的時候最大并發數為# (worker_connections * worker_processes)/2
}# http塊是Nginx服務器配置中的重要部分,緩存、代理和日志格式定義等絕大多數功能和第三方模塊都
# 可以在這設置,http塊可以包含多個server塊,而一個server塊中又可以包含多個location塊,
# server塊可以配置文件引入、MIME-Type定義、日志自定義、是否啟用sendfile、連接超時時間和
# 單個鏈接的請求上限等。
http {include mime.types;default_type application/octet-stream;#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 logs/access.log main;sendfile on; # 作為web服務器的時候打開sendfile加快靜態文件傳輸,# 數據傳輸路徑為:磁盤 → 內核緩存 → 網絡協議棧 → 網卡,# 省略了用戶態與內核態之間的拷貝,減少 CPU 占用,提升傳輸速度,# 被稱之為零拷貝。#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65; # 長連接超時時間,單位是秒# 當客戶端(如瀏覽器)發起請求時,若雙方支持長連接,# 連接不會在單次請求后立即關閉,而是保持一段時間,供后續請求復用。# 避免每次請求都重新進行 TCP 三次握手,降低網絡延遲和服務器資源消耗# 際配置時需根據業務場景(并發量、請求頻率)調整,# 靜態資源多的服務可適當延長,高并發動態服務可適當縮短。#gzip on;# server:設置一個虛擬機主機,可以包含自己的全局塊,同時也可以包含多個location模塊
# 比如本虛擬機監聽的端口、本虛擬機的名稱和IP配置,多個server可以使用一個端口
# 比如都使用80端口提供web服務server {listen 80; # 配置server監聽的端口server_name localhost; # 本server的名稱,當訪問此名稱的時候# nginx會調用當前serevr內部的配置進程匹配#charset koi8-r;#access_log logs/host.access.log main;# location是Nginx配置中用于匹配客戶端請求URL路徑的核心指令,
# 主要作用是根據請求的URL路徑,定義不同的處理規則(如返回靜態文件、反向代理到后端服務、
# 重定向等)。它必須嵌套在 server 塊或其他 location 塊中,是實現 URL 路由的關鍵。location / {root html; # 相當于默認頁面的目錄名稱,默認是安裝目錄的相對路徑,# 可以使用絕對路徑配置。index index.html index.htm; # 默認的頁面文件名稱}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html# 當服務器返回 500、502、503、504 這些服務器端錯誤狀態碼時,# Nginx 會自動將請求重定向到 /50x.html 頁面error_page 500 502 503 504 /50x.html; location = /50x.html { # location處理對應的不同錯誤碼的頁面定義到/50x.htmlroot html; # 定義默認頁面所在的目錄}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {# proxy_pass http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# include fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {# deny all;#}}# another virtual host using mix of IP-, name-, and port-based configuration##server {# listen 8000;# listen somename:8080;# server_name somename alias another.alias;# location / {# root html;# index index.html index.htm;# }#}# HTTPS server##server {# listen 443 ssl;# server_name localhost;# ssl_certificate cert.pem;# ssl_certificate_key cert.key;# ssl_session_cache shared:SSL:1m;# ssl_session_timeout 5m;# ssl_ciphers HIGH:!aNULL:!MD5;# ssl_prefer_server_ciphers on;# location / {# root html;# index index.html index.htm;# }#}
# include /usr/local/nginx/conf.d/*.conf # 導入其他路徑的配置文件
}
3.2 全局配置
- main全局配置段常見的配置指令分類:
- 正常運行必備的配置
- 優化性能相關的配置
- 用于調試及定位問題相關的配置
- 事件驅動相關的配置
全局配置說明:
user nginx nginx; # 啟動Nginx工作進程的用戶和組
worker_processes [number | auto]; # 啟動Nginx工作進程的數量,一般設為和CPU核心數相同
worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ;
# 將Nginx工作進程綁定到指定的CPU核心,默認Nginx是不進行進程綁定的,綁定并不是意味著當前nginx進
# 程獨占以一核心CPU,但是可以保證此進程不運行在其他核心上,這就極大減少了nginx的工作進程在不同的
# cpu核心上的來回跳轉,減少了CPU對進程的資源分配與回收以及內存管理等,因此可以有效的提升nginx服務
# 器的性能。
# CPU MASK:00000001:0號CPU
# 00000010:1號CPU
# 10000000:7號CUP
# 示例:
# worker_cpu_affinity 0001 0010 0100 1000;第0號至第3號CPU
# worker_cpu_affinity 01 10;第0號至第1號cpu
# 查看配置
[root@centos8 ~]# ps axo pid,cmd,psr | grep nginx
31093 nginx: master process /apps 1
34474 nginx: worker process 1
34475 nginx: worker process 3
34476 nginx: worker process 5
34477 nginx: worker process 7
# a:顯示所有用戶的進程
# x:顯示沒有控制終端的進程(如后臺服務進程)
# o pid,cmd,psr:自定義輸出格式,僅顯示三個字段
# pid:進程 ID。
# cmd:啟動進程的命令(包括參數)。
# psr:進程當前運行的 CPU 核心編號error_log /usr/local/nginx/logs/error.log error; # 指定錯誤日志路徑和錯誤級別pid /usr/local/nginx/logs/nginx.pid; # pid文件的保存路徑worker_priority 0; # 工作進程的優先級,進程優先級范圍通常為-20到19,通常保持默認0即可# 數值越小,優先級越高(如 -20 是最高優先級)# 數值越大,優先級越低(如 19 是最低優先級)# 默認值通常為 0(與系統中其他普通進程優先級相同)# 若服務器專門用于 Nginx 服務,且需要優先保障其響應速度,# 可適當降低數值(提高優先級),如 worker_priority -5;# 若 Nginx 并非服務器核心服務(如同時運行高優先級的計算任務),# 可提高數值(降低優先級),如 worker_priority 5;
worker_rlimit_nofile 65536; # 所有worker進程能打開的文件數量上限,# 包括:Nginx的所有連接(例如與代理服務器的連接等)# 而不僅僅是與客戶端的連接# 另一個考慮因素是實際的并發連接數不能超過# 系統級別的最大打開文件數的限制# 最好與ulimit -n 或者limits.conf的值保持一致
# 修改pam限制
[root@Nginx ~]# sudo -u nginx ulimit -n
1024
[root@Nginx ~]# vim /etc/security/limits.conf
* - nofile 100000
[root@Nginx ~]# sudo -u nginx ulimit -n
100000daemon off; #前臺運行Nginx服務用于測試、docker等環境
master_process off|on; # 是否開啟Nginx的master-worker工作模式,僅用于開發調試場景,默認為onevents {worker_connections 65535; # 設置單個工作進程的最大并發連接數use epoll; # 使用epoll事件驅動(Linux推薦epoll,性能最優),# Nginx支持眾多的事件驅動,# 比如:select、poll、epoll,只能設置在events模塊中accept_mutex on; # 驚群問題:當多個 Nginx 工作進程同時監聽同一端口時,新連接到達時,# 所有工作進程會被同時喚醒競爭連接,但最終只有一個進程能獲取連接,# 其余進程被喚醒后發現無連接可處理,造成 CPU 資源浪費# on時,同一時間只允許一個工作進程嘗試接收新連接,避免多進程同時競爭,# 減少 CPU 無效消耗,提高連接處理效率,建議設置為onmulti_accept on; # 允許單個工作進程(worker process)一次性接收多個新連接# 減少accept()調用次數和進程喚醒頻率,降低CPU上下文切換開銷# 建議開啟
}
3.2.1 實現nginx的高并發配置
注意:測試環境由于硬件問題,并發量寫小一點(對硬件要求較高)
1.修改nginx默認配置文檔
[root@server2 conf]# vim /usr/local/nginx/conf/nginx.conf
2.修改pam限制
[root@server2 conf]# vim /etc/security/limits.conf
3.查看pam是否生效
[root@server2 ~]# sudo -u nginx ulimit -n
50000
4.測試并發性能
[root@server2 ~]# ab -c 1500 -n 50000 http://192.168.36.136/index.html
?-n:請求總量
-c:并發量
總共50000個請求,每次發送1500個并發
3.3 http配置塊
# 在響應報文中將指定的文件擴展名映射至MIME對應的類型
include /etc/nginx/mime.types;
default_type application/octet-stream; # 除mime.types中的類型外# 指定其它文件的默認MIME類型,瀏覽器一般會提示下載
types {
text/html html;
image/gif gif;
image/jpeg jpg;
}
示例:
[root@Nginx ~]# vim /usr/local/nginx/html/lee.php
<?php
phpinfo();
?>
[root@Nginx ~]# curl -I 192.168.36.136/lee.php
HTTP/1.1 200 OK
Server: nginx/1.26.1
Content-Type: application/octet-stream
Content-Length: 24
Last-Modified: Fri, 19 Jul 2025 09:38:52 GMT
Connection: keep-alive
ETag: "669a342c-18"
Accept-Ranges: bytes
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
default_type text/html;
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# curl -I 192.168.36.136/lee.php
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Fri, 19 Jul 2025 09:49:49 GMT
Content-Type: text/html
Content-Length: 24
Last-Modified: Fri, 19 Jul 2025 09:38:52 GMT
Connection: keep-alive
ETag: "669a342c-18"
Accept-Ranges: bytes
3.4 核心配置示例
3.4.1?新建一個 PC web 站點
1.添加子配置文件路徑(在配置文件的最后面添加此行,不要放在最前面,會導致前面的命令無法
[root@server2 sbin]# vim /usr/local/nginx/conf/nginx.conf
2.創建虛擬主機網站配置
[root@server2 sbin]# mkdir -p /usr/local/nginx/conf.d/
[root@server2 sbin]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@server2 sbin]#
3.重新讀取配置文件
[root@server2 sbin]# nginx -s reload
3.添加域名映射
[root@server2 sbin]# vim /etc/hosts
4.測試域名訪問效果
[root@server2 ~]# mkdir -p /web/html
[root@server2 ~]# vim /web/html/index.html
web_html
[root@server2 ~]# curl www.timinglee.org
web_html
3.4.2 root與alias
location中使用root指令和alias指令的意義不同?
1.root查找路徑方式?
location /dirtest {root /mnt;}
?客戶實請求路徑:curl www.timinglee.org/dirtest/index.html
Nginx 實際查找的文件路徑:/nmt/dirtest/index.html(root路徑 + location路徑 + 請求資源
)
2.alias查找路徑方式
location /alias {alias /mnt/dirtest;}
客戶請求路徑:curl www.timinglee.org/dirtest/
nginx實際查找文件路徑:/nmt/dirtest/index.html(alias路徑 + 請求資源
,忽略location
路徑)
3.4.3 location的詳細使用
- 在一個server中location配置段可存在多個,用于實現從uri到文件系統的路徑映射;
- ngnix會根據用戶請求的URI來檢查定義的所有location,按一定的優先級找出一個最佳匹配, 而后應用其配置在沒有使用正則表達式的時候,nginx會先在server中的多個location選取匹配度最高的一個uri
- uri是用戶請求的字符串,即域名后面的web文件路徑
- 然后使用該location模塊中的正則url和字符串,如果匹配成功就結束搜索,并使用此location處理此請求。
#語法規則:
location [ = | ~ | ~* | ^~ ] uri { ... }= # 用于標準uri前,需要請求字串與uri精確匹配,大小敏感,如果匹配成功就停止向下匹配并立即處理請求
^~ # 用于標準uri前,表示包含正則表達式,并且匹配以指定的正則表達式開頭# 對uri的最左邊部分做匹配檢查,不區分字符大小寫
~ # 用于標準uri前,表示包含正則表達式,并且區分大小寫
~* # 用于標準uri前,表示包含正則表達式,并且不區分大寫
不帶符號 #匹配起始于此uri的所有的uri
\ # 用于標準uri前,表示包含正則表達式并且轉義字符。可以將 . * ?等轉義為普通符號#匹配優先級從高到低:
=, ^~, ~/~*, 不帶符號
3.4.3.1 匹配案例-精準匹配
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/images -p
[root@Nginx ~]# ls /webdata/nginx/timinglee.org/lee/images
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location = /logo.png {root /webdata/nginx/timinglee.org/lee/images;}
}
#上傳logo.jpg圖片到/webdata/nginx/timinglee.org/lee/images,重啟Nginx并訪問測試
#訪問測試:http://www.timinglee.org/logo.png
3.1.3.2 匹配案例-區分大小寫
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ~ /logo.PNG {root /webdata/nginx/timinglee.org/lee/images;}
}
#重啟Nginx并訪問測試
#http://www.timinglee.org/logo.PNG #訪問失敗,系統中沒有logo.PNG文件
3.4.3.3 匹配案例-不區分大小寫
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ~* /logo.PNG {root /webdata/nginx/timinglee.org/lee/images;}
}
#重啟Nginx并訪問測試
#http://www.timinglee.org/logo.png
3.4.3.4 匹配案例-URI開始
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/images/images{1,2}
[root@Nginx ~]# echo image1 > /webdata/nginx/timinglee.org/lee/images/images1/index.html
[root@Nginx ~]# echo image1 > /webdata/nginx/timinglee.org/lee/images/images2/index.html
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ^~ /images {root /webdata/nginx/timinglee.org/lee/images;index index.html;}location /images1 {root /webdata/nginx/timinglee.org/lee/images;}
}
#重啟Nginx并訪問測試,實現效果是訪問/images1和/images2返回內容一樣
[root@node100 ~]# curl 192.168.36.100/images1/
image1
[root@node100 ~]# curl 192.168.36.100/images2/
image1
3.4.3.5 匹配案例-文件名后綴
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/images
#上傳一個圖片到/webdata/nginx/timinglee.org/lee/images
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js|css)$ {root /webdata/nginx/timinglee.org/lee/images;index index.html;}
}
#重啟Nginx并訪問測試
192.168.36.200/logo.png
3.4.3.6 匹配案例-優先級
server {
listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ^~ /images {root /webdata/nginx/timinglee.org/lee/images;index index.html;}location /images1 {root /webdata/nginx/timinglee.org/lee/images;}location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js)$ {root /data/nginx/static3;index index.html;}
}
#匹配優先級:=, ^~, ~/~*,/
location優先級:(location =) > (location ^~ 路徑) > (location ~,~* 正則順序) >
(location 完整路徑) > (location 部分起始路徑) > (/)
3.4.3.7 生產使用案例
#直接匹配網站根會加速Nginx訪問處理
location = /index.html {......;
}
location / {......;
}#靜態資源配置方法1
location ^~ /static/ {......;
}#靜態資源配置方法2,應用較多
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {......;
}#多應用配置
location ~* /app1 {......;
}
location ~* /app2 {......;
}
3.4.4 Nginx 賬戶認證功能
[root@Nginx ~]# htpasswd -cmb /usr/local/nginx/conf/.htpasswd admin lee #-b 表
示非交互建立用戶認證
Adding password for user admin
[root@Nginx ~]# htpasswd -mb /usr/local/nginx/conf/.htpasswd lee lee
Adding password for user lee
[root@Nginx ~]# cat /usr/local/nginx/conf/.htpasswd
admin:$apr1$haGCKgCT$myogggALmqNecTyNupsWQ/
lee:$apr1$H97AyQPF$kGU.Tc4zn1E4Zkp/M4R6G.
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/login
[root@Nginx ~]# echo login > /webdata/nginx/timinglee.org/lee/login/index.html
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name lee.timinglee.org;
location /login {
root /webdata/nginx/timinglee.org/lee;
index index.html;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/conf/.htpasswd";
}
}
#重啟Nginx并訪問測試
[root@node100 ~]# curl lee.timinglee.org/login/ -u lee:lee
login
[root@node100 ~]# curl lee.timinglee.org/login/ -u admin:lee
login
實驗驗證:
基于用戶的訪問
[root@server2 ~]# mkdir -p /web/login/
[root@server2 ~]# touch index.html
[root@server2 ~]# echo "login" > /web/login/index.html
[root@server2 ~]# cat /web/login/index.html
login
[root@server2 ~]#
[root@server2 conf.d]# htpasswd -cm /usr/local/nginx/.htpasswd admin # 創建nginx所需認證文件和用戶
# -c創建新的文件會覆蓋舊文件
New password:
Re-type new password:
Adding password for user admin
[root@server2 conf.d]# htpasswd -m /usr/local/nginx/.htpasswd lee
New password:
Re-type new password:
Adding password for user lee
[root@server2 conf.d]# cat /usr/local/nginx/.htpasswd
admin:$apr1$.0fUA3Pl$e6CqYByBBLgDfrZAps32y/
lee:$apr1$pPwPp51g$/PBcT9Xl293rX5ciMdaE4.
[root@server2 conf.d]#
[root@server2 conf.d]# vim vhosts.conf
[root@server2 conf.d]# pwd
/usr/local/nginx/conf.d
驗證是否成功
[root@server2 ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server2 ~]# nginx -s reload
[root@server2 ~]# curl www.timinglee.org/login/
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.24.0</center>
</body>
</html>
[root@server2 ~]# curl -uadmin:lee www.timinglee.org/login/
login
[root@server2 ~]#
3.4.5 自定義錯誤頁面和錯誤日志
自定義錯誤和日志
[root@server2 web]# mkdir errorpage
[root@server2 web]# echo "錯誤" > error.html
[root@server2 web]# cat error.html
錯誤
[root@server2 logs]# touch timinglee.org.err
[root@server2 logs]# touch timinglee.org.acc
[root@server2 logs]# pwd
/usr/local/nginx/logs
[root@server2 logs]#
?驗證
3.4.7 檢測文件是否存在
[root@Nginx ~]# echo "index.html is not exist" >
/webdata/nginx/timinglee.org/lee/error/default.html
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;error_page 404 /40x.html;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;try_files $uri $uri.html $uri/index.html /error/default.html;location = /40x.html {root /webdata/nginx/timinglee/lee/errors;}
}
實驗驗證:
[root@server2 conf.d]# echo default > /web/errorpage/default.html
[root@server2 conf.d]# cat /web/errorpage/default.html
default
測試
3.4.8 長連接配置
keepalive_timeout timeout [header_timeout]; # 設定保持連接超時時長,0表示禁止長連接,默認為75s# 通常配置在http字段作為站點全局配置
keepalive_requests 數字; # 在一次長連接上所允許請求的資源的最大數量# 默認為100次,建議適當調大,比如:500
示例:
keepalive_requests 3;
keepalive_timeout 65 60;
#開啟長連接后,返回客戶端的會話保持時間為60s,單次長連接累計請求達到指定次數請求或65秒就會被斷
開,第二個數字60為發送給客戶端應答報文頭部中顯示的超時時間設置為60s:如不設置客戶端將不顯示超時時
間。
Keep-Alive:timeout=60 #瀏覽器收到的服務器返回的報文
#如果設置為0表示關閉會話保持功能,將如下顯示:
#Connection:close 瀏覽器收到的服務器返回的報文
#使用命令測試:
[root@node100 ~]# telnet lee.timinglee.org 80
Trying 172.25.254.200...
Connected to lee.timinglee.org.
Escape character is '^]'.
GET / HTTP/1.1 ##輸入動作
HOST: lee.timinglee.org ##輸入訪問HOST
##輸入回車
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sat, 20 Jul 2024 12:54:16 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Sat, 20 Jul 2024 08:49:12 GMT
Connection: keep-alive
ETag: "669b7a08-f"
Accept-Ranges: bytes
172.25.254.200
GET / HTTP/1.1 #第二次操作
HOST: lee.timinglee.org #第二次操作
#第二次操作
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sat, 20 Jul 2024 12:54:25 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Sat, 20 Jul 2024 08:49:12 GMT
Connection: close
ETag: "669b7a08-f"
Accept-Ranges: bytes
172.25.254.200
Connection closed by foreign host. #自動斷開鏈接
實驗驗證
[root@server2 conf]# vim nginx.conf # 長鏈接位于nginx主配置文件
[root@server2 conf]# pwd
/usr/local/nginx/conf
[root@server2 conf]#
[root@server2 ~]# yum install telnet -y
3.4.9 作為下載服務器配置
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
limit_rate rate; # 限制響應客戶端傳輸速率(除GET和HEAD以外的所有方法),單位B/s,bytes/second,# 默認值0,表示無限制,此指令由ngx_http_core_module提供
set $limit_rate 4k; # 也可以通變量限速,單位B/s,同時設置,此項優級高.
示例:實現下載站點
#注意:download不需要index.html文件
[root@Nginx ~]# mkdir -p /webdata/nginx/timinglee.org/lee/download
[root@Nginx ~]# cp /root/anaconda-ks.cfg /webdata/nginx/timinglee.org/lee/download
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;try_files $uri $uri.html $uri/index.html /error/default.html;location = /40x.html {root /webdata/nginx/timinglee/lee/errors;}location /download {autoindex on; #自動索引功能autoindex_exact_size on; #計算文件確切大小(單位bytes),此為默認值,off只顯示大概大小(單位kb、mb、gb)autoindex_localtime on; #on表示顯示本機時間而非GMT(格林威治)時間,默為為off顯示GMT時間limit_rate 1024k; #限速,默認不限速 }
}
#重啟Nginx并訪問測試下載頁面
實驗實現:
1.建立實驗素材?
2.下載服務器?
?3.測試
4 nginx高級配置
4.1 nginx狀態頁
- 基于nginx 模塊 ngx_http_stub_status_module 實現,
- 在編譯安裝nginx的時候需要添加編譯參數 --with-http_stub_status_module
- 否則配置完成之后監測會是提示法錯誤
#配置示例:
location /nginx_status {
stub_status;
auth_basic "auth login";
auth_basic_user_file /apps/nginx/conf/.htpasswd;
allow 192.168.0.0/16;
allow 127.0.0.1;
deny all;
}
# 狀態頁用于輸出nginx的基本狀態信息:
# 輸出信息示例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上面三個數字分別對應accepts,handled,requests三個值
Reading: 6 Writing: 179 Waiting: 106
Active connections: # 當前處于活動狀態的客戶端連接數# 包括連接等待空閑連接數=reading+writing+waiting
accepts: # 統計總值,Nginx自啟動后已經接受的客戶端請求連接的總數。
handled: # 統計總值,Nginx自啟動后已經處理完成的客戶端請求連接總數# 通常等于accepts,除非有因worker_connections限制等被拒絕的連接
requests: # 統計總值,Nginx自啟動后客戶端發來的總的請求數
Reading: # 當前狀態,正在讀取客戶端請求報文首部的連接的連接數# 數值越大,說明排隊現象嚴重,性能不足
Writing: # 當前狀態,正在向客戶端發送響應報文過程中的連接數,數值越大,說明訪問量很大
Waiting: # 當前狀態,正在等待客戶端發出請求的空閑連接數開啟 keep-alive的情況下,這個值 等于active –(reading+writing)
4.1 nginx壓縮功能
#啟用或禁用gzip壓縮,默認關閉
gzip on | off;#壓縮比由低到高從1到9,默認為1,值越高壓縮后文件越小,但是消耗cpu比較高。基本設定未4或者5
gzip_comp_level 4;#禁用IE6 gzip功能,早期的IE6之前的版本不支持壓縮
gzip_disable "MSIE [1-6]\.";#gzip壓縮的最小文件,小于設置值的文件將不會壓縮
gzip_min_length 1k;#啟用壓縮功能時,協議的最小版本,默認HTTP/1.1
gzip_http_version 1.0 | 1.1;#指定Nginx服務需要向服務器申請的緩存空間的個數和大小,平臺不同,默認:32 4k或者16 8k;
gzip_buffers number size;#指明僅對哪些類型的資源執行壓縮操作;默認為gzip_types text/html,不用顯示指定,否則出錯
gzip_types mime-type ...;#如果啟用壓縮,是否在響應報文首部插入“Vary: Accept-Encoding”,一般建議打開
gzip_vary on | off;#預壓縮,即直接從磁盤找到對應文件的gz后綴的式的壓縮文件返回給用戶,無需消耗服務器CPU
#注意: 來自于ngx_http_gzip_static_module模塊
gzip_static on | off;
示例:
#重啟nginx并進行訪問測試壓縮功能
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/data
[root@Nginx ~]# cp /usr/local/nginx/logs/access.log
/webdata/nginx/timinglee.org/lee/data/data.txt
[root@Nginx ~]# echo test > /webdata/nginx/timinglee.org/lee/data/test.html #
小于1k的文件測試是否會壓縮
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
@@@@省略內容@@@@
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/css
application/xml text/javascript application/x-httpd-php image/gif image/png;
gzip_vary on;
#重啟Nginx并訪問測試:
[root@client ~]# curl --head --compressed lee.timinglee.org/data/test.html
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 21 Jul 2024 15:42:46 GMT
Content-Type: text/html
Content-Length: 5
Last-Modified: Sun, 21 Jul 2024 15:40:35 GMT
Connection: keep-alive
ETag: "669d2bf3-5"
Accept-Ranges: bytes
[root@client ~]# curl --head --compressed lee.timinglee.org/data/data.txt
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 21 Jul 2024 15:43:17 GMT
Content-Type: text/plain
Last-Modified: Sun, 21 Jul 2024 15:40:13 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/"669d2bdd-3e25b5"
Content-Encoding: gzip
實驗驗證:
1.準備壓縮材料
[root@server2 conf.d]# cp /usr/local/nginx/logs/timinglee.org.acc /web/html/big.html
[root@server2 conf.d]# echo hello > /web/html/small.html
[root@server2 conf.d]# cat /web/html/small.html
hello
2.編輯配置文件
測試壓縮效果
[root@server2 conf.d]# cp /usr/local/nginx/logs/timinglee.org.acc /web/html/big.html
[root@server2 conf.d]# curl --head --compressed www.timinglee.org/small.html
4.3 nginx的版本隱藏
[root@Nginx nginx-1.26.1]# vim src/core/nginx.h
#define nginx_version 1026001
#define NGINX_VERSION "1.0"
#define NGINX_VER "HAHA/" NGINX_VERSION
4.4 nginx變量使用
- nginx的變量可以在配置文件中引用,作為功能判斷或者日志等場景使用
- 變量可以分為內置變量和自定義變量
- 內置變量是由nginx模塊自帶,通過變量可以獲取到眾多的與客戶端訪問相關的值。
4.4.1 內置變量
官方文檔:Alphabetical index of variableshttp://nginx.org/en/docs/varindex.html
常用內置變量:
$remote_addr;
#存放了客戶端的地址,注意是客戶端的公網IP$args;
#變量中存放了URL中的所有參數
#例如:https://search.jd.com/Search?keyword=手機&enc=utf-8
#返回結果為: keyword=手機&enc=utf-8$is_args
#如果有參數為? 否則為空$document_root;
#保存了針對當前資源的請求的系統根目錄,例如:/webdata/nginx/timinglee.org/lee。$document_uri;
#保存了當前請求中不包含參數的URI,注意是不包含請求的指令
#比如:http://lee.timinglee.org/var?\id=11111會被定義為/var
#返回結果為:/var$host;
#存放了請求的host名稱limit_rate 10240;
echo $limit_rate;
#如果nginx服務器使用limit_rate配置了顯示網絡速率,則會顯示,如果沒有設置, 則顯示0$remote_port;
#客戶端請求Nginx服務器時隨機打開的端口,這是每個客戶端自己的端口$remote_user;
#已經經過Auth Basic Module驗證的用戶名$request_body_file;
#做反向代理時發給后端服務器的本地資源的名稱$request_method;
#請求資源的方式,GET/PUT/DELETE等$request_filename;
#當前請求的資源文件的磁盤路徑,由root或alias指令與URI請求生成的文件絕對路徑,
#如:webdata/nginx/timinglee.org/lee/var/index.html$request_uri;
#包含請求參數的原始URI,不包含主機名,相當于:$document_uri?$args,
#例如:/main/index.do?id=20190221&partner=search$scheme;
#請求的協議,例如:http,https,ftp等$server_protocol;
#保存了客戶端請求資源使用的協議的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等$server_addr;
#保存了服務器的IP地址$server_name;
#虛擬主機的主機名$server_port;
#虛擬主機的端口號$http_user_agent;
#客戶端瀏覽器的詳細信息$http_cookie;
#客戶端的所有cookie信息$cookie_<name>
#name為任意請求報文首部字部cookie的key名
$http_<name>
#name為任意請求報文首部字段,表示記錄請求報文的首部字段,name的對應的首部字段名需要為小寫,如果有
橫線需要替換為下劃線
#示例:
echo $http_user_agent;
echo $http_host;$sent_http_<name>
#name為響應報文的首部字段,name的對應的首部字段名需要為小寫,如果有橫線需要替換為下劃線,此變量有
問題echo $sent_http_server;
$arg_<name>
#此變量存放了URL中的指定參數,name為請求url中指定的參數
echo $arg_id;
示例:
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;location /var {default_type text/html;echo $remote_addr;echo $args;echo $document_root;echo $document_uri;echo $host;echo $http_user_agent;echo $request_filename;echo $scheme;echo $scheme://$host$document_uri?$args;echo $http_cookie;echo $cookie_key2;echo $http_Accept;}
}[root@client ~]# curl -b "title=lee;key1=lee,key2=timinglee"
"lee.timinglee.org/var?search=lee&&id=666666"
172.25.254.20
search=lee&&id=666666
/webdata/nginx/timinglee.org/lee
/var
lee.timinglee.org
curl/7.29.0
/webdata/nginx/timinglee.org/lee/var
http
http://lee.timinglee.org/var?search=lee&&id=666666
title=lee;key1=lee,key2=timinglee
timinglee
*/*
[root@server2 ~]# rm -rf /usr/local/nginx/
[root@server2 ~]# cd /usr/local/
[root@server2 local]# rm -rf nginx-1.26.3/
[root@server2 ~]# cd /usr/local/
[root@server2 local]# tar zxf /root/nginx-1.26.3.tar.gz
[root@server2 local]# tar zxf /root/echo-nginx-module-0.63.tar.gz
[root@server2 nginx-1.26.3]# ./configure --prefix=/usr/local/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 --add-module=/usr/local/echo-nginx-module-0.63
[root@server2 nginx-1.26.3]# make && make install
?驗證
[root@server2 conf.d]# nginx -s reload
[root@server2 conf.d]# curl -A "timinglee" -b "lee=a,key1=2" -ulee:lee www.timinglee.org/vars?name=lee
4.4.2 自定義變量
set $name timinglee;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port";
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;location /var {default_type text/html;set $name timinglee;echo $name;set $web_port $server_port;echo $web_port;}
}
測試輸出
[root@client ~]# curl lee.timinglee.org/var
timinglee
80
5 Nginx Rewrite 相關功能
- Nginx服務器利用 ngx_http_rewrite_module 模塊解析和處理rewrite請求
- 此功能依靠 PCRE(perl compatible regular expression),因此編譯之前要安裝PCRE庫
- rewrite是nginx服務器的重要功能之一,用于實現URL的重寫,URL的重寫是非常有用的功能
- 比如它可以在我們改變網站結構之后,不需要客戶端修改原來的書簽,也無需其他網站修改我們的鏈接,就可以設置為訪問
- 另外還可以在一定程度上提高網站的安全性。
5.1?ngx_http_rewrite_module 模塊指令

5.2?rewrite 案例: break 與 last
?rewrite中break與last區別
[root@server2 ~]# mkdir /web/html/{test1,test2,break,last}
[root@server2 ~]# echo test1 > /web/html/test1/index.html
[root@server2 ~]# echo test2 > /web/html/test2/index.html
[root@server2 ~]# echo break > /web/html/break/index.html
[root@server2 ~]# echo last > /web/html/last/index.html
[root@server2 ~]#
?測試
5.2.1?rewrite案例: 自動跳轉 https
[root@server2 conf.d]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/timinglee.org.key -x509 -days 365 -out /usr/local/nginx/certs/timinglee.org.crt
?
測試
5.2.2?rewrite 案例: 判斷文件是否存在
案例:當用戶訪問到公司網站的時輸入了一個錯誤的URL,可以將用戶重定向至官網首頁
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
location / {root /data/nginx/html/pc;index index.html;if (!-e $request_filename) {rewrite .* http://www.timinglee.org/index.html; #實現客戶端瀏覽器的302跳轉#rewrite .* /index.html; #web服務器內部跳轉}
}
#重啟Nginx并訪問測試
?判斷文件是否存在
5.3 nginx防盜鏈
none: # 請求報文首部沒有referer首部,# 比如用戶直接在瀏覽器輸入域名訪問web網站,就沒有referer信息。
blocked: # 請求報文有referer首部,但無有效值,比如為空。
server_names: # referer首部中包含本主機名及即nginx 監聽的server_name。
arbitrary_string: # 自定義指定字符串,但可使用*作通配符。示例: *.timinglee.org
www.timinglee.*
regular expression: # 被指定的正則表達式模式匹配到的字符串,要使用~開頭,例如:
~.*\.timinglee\.com
5.3.1 實現盜鏈
#新建一個主機172.25.254.20,盜取另一臺主機lee.timinglee.org/images/lee.png的圖片
[root@client ~]# yum install httpd -y
[root@client html]# vim /var/www/html/index.html
#準備盜鏈web頁面:
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盜鏈</title>
</head>
<body>
<img src="http://www.timinglee.org/images/lee.png" >
<h1 style="color:red">歡迎大家</h1>
<p><a href=http://www.timinglee.org>狂點老李</a>出門見喜</p>
</body>
</html>
~
#重啟apache并訪問http://172.25.254.20 測試
#驗證兩個域名的日志,是否會在被盜連的web站點的日志中出現以下盜鏈日志信息:
[root@Nginx ~]# cat /usr/local/nginx/logs/access.log
172.25.254.1 - - [22/Jul/2024:09:50:01 +0800] "GET /images/logo.png HTTP/1.1" 304
0 "http://172.25.254.20/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Edg/126.0.0.0"
172.25.254.1 - - [22/Jul/2024:09:50:18 +0800] "GET / HTTP/1.1" 304 0
"http://172.25.254.20/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Edg/126.0.0.0"
5.3.2?實現防盜鏈

示例:定義防盜鏈
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /data/web/html;index index.html;location / {valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;if ($invalid_referer){return 404;}
}location /images {valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;if ($invalid_referer){rewrite ^/ http://www.timinglee.org/daolian.png permanent; #注意此圖片不能和正常圖片放在一個目錄中}}
}
#重啟Nginx并訪問測試
http://172.25.254.20
6 nginx反向代理功能
ngx_http_proxy_module: # 將客戶端的請求以http協議轉發至指定服務器進行處理
ngx_http_upstream_module # 用于定義為proxy_pass,fastcgi_pass,uwsgi_pass# 等指令引用的后端服務器分組
ngx_stream_proxy_module: # 將客戶端的請求以tcp協議轉發至指定服務器處理
ngx_http_fastcgi_module: # 將客戶端對php的請求以fastcgi協議轉發至指定服務器助理
ngx_http_uwsgi_module: # 將客戶端對Python的請求以uwsgi協議轉發至指定服務器處理


- 同構代理:用戶不需要其他程序的參與,直接通過http協議或者tcp協議訪問后端服務器
- 異構代理:用戶訪問的資源時需要經過處理后才能返回的,比如php,python,等等,這種訪問資源需要經過處理才能被訪問
6.1 實現http反向代理
官方文檔:Module ngx_http_proxy_modulehttps://nginx.org/en/docs/http/ngx_http_proxy_module.html
6.1.1 http 協議反向代理
6.1.1.1 反向代理配置參數
#官方文檔:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
proxy_pass; # 用來設置將客戶端請求轉發給的后端服務器的主機# 可以是主機名(將轉發至后端服務做為主機頭首部)、IP地址:端口的方式# 也可以代理到預先設置的主機群組,需要模塊ngx_http_upstream_module支持
#示例:
location /web {index index.html;proxy_pass http://172.25.254.30:8080; # 8080后面無uri,即無 / 符號,# 需要將location后面url 附加到proxy_pass指定的url后面# 此行為類似于root# proxy_pass指定的uri不帶斜線將訪問的/web# 等于訪問后端服務器
proxy_pass http://172.25.254.40:8080/; # 8080后面有uri,即有 / 符號# 相當于置換,即訪問/web時實際返回proxy_pass后面uri內容
# 此行為類似于alias
# proxy_pass指定的uri帶斜線
# 等于訪問后端服務器的
# http://172.25.254.40:8080/index.html
# 內容返回給客戶端
} # http://nginx/web/index.html ==> http://1:8080# 重啟Nginx測試訪問效果:
# curl -L http://www.timinglee.org/web
# 如果location定義其uri時使用了正則表達式模式(包括~,~*,但不包括^~),則proxy_pass之后必須不能使用uri
# 即不能有/ ,用戶請求時傳遞的uri將直接附加至后端服務器之后
server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy_pass http://host:port; #proxy_pass后面的url 不能加/
}
...
}
http://HOSTNAME/uri/ --> http://host/uri/
proxy_hide_header field; # 用于nginx作為反向代理的時候
# 在返回給客戶端http響應時
# 隱藏后端服務器相應頭部的信息
# 可以設置在http,server或location塊
# 示例: 隱藏后端服務器ETag首部字段
location /web {index index.html;proxy_pass http://10.0.0.18:8080/;proxy_hide_header ETag;
}
proxy_pass_header field; # 透傳
# 默認nginx在響應報文中不傳遞后端服務器的首部字段Date, Server, X-Pad, X-Accel等參數
# 如果要傳遞的話則要使用 proxy_pass_header field聲明將后端服務器返回的值傳遞給客戶端
# field 首部字段大小不敏感
# 示例:透傳后端服務器的Server和Date首部給客戶端,同時不再響應報中顯示前端服務器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
proxy_pass_request_body on | off;# 是否向后端服務器發送HTTP實體部分,可以設置在http,server或location塊,默認即為開啟
proxy_pass_request_headers on | off;
# 是否將客戶端的請求頭部轉發給后端服務器,可以設置在http,server或location塊,默認即為開啟
proxy_set_header;# 可更改或添加客戶端的請求頭部信息內容并轉發至后端服務器,比如在后端服務器想要獲取客戶端的真實IP的時候,就要更改每一個報文的頭部
#示例:
location ~ /web {proxy_pass http://172.25.254.20:80;proxy_hide_header ETag;proxy_pass_header Server;proxy_pass_request_body on;proxy_pass_request_headers on;proxy_set_header X-Forwarded-For $remote_addr;
}[root@apache20 ~]# vim /etc/httpd/conf/httpd.conf
LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%
{User-Agent}i\"" combined訪問后看后端服務器日志proxy_connect_timeout time;
# 配置nginx服務器與后端服務器嘗試建立連接的超時時間,默認為60秒用法如下:proxy_connect_timeout 6s;
# 60s為自定義nginx與后端服務器建立連接的超時時間,超時會返回客戶端504響應碼proxy_read_timeout time;
# 配置nginx服務器向后端服務器或服務器組發起read請求后,等待的超時時間,默認60sproxy_send_timeout time;
# 配置nginx項后端服務器或服務器組發起write請求后,等待的超時 時間,默認60sproxy_http_version 1.0;
# 用于設置nginx提供代理服務的HTTP協議的版本,默認http 1.0proxy_ignore_client_abort off;
# 當客戶端網絡中斷請求時,nginx服務器中斷其對后端服務器的請求。即如果此項設置為on開啟,則服務器、
會忽略客戶端中斷并一直等著代理服務執行返回,如果設置為off,則客戶端中斷后Nginx也會中斷客戶端請求
并立即記錄499日志,默認為off。
6.1.1.2 實戰案例: 反向代理單臺 web 服務器
[root@centos8 ~]# cat /apps/nginx/conf/conf.d/pc.conf
server {listen 80;server_name www.timinglee.org;location / {proxy_pass http://172.25.254.30;}
}
#重啟Nginx 并訪問測試
6.1.1.3 實戰案例: 指定 location 實現反向代理
6.1.1.3.1 針對指定的 location
server {
listen 80;server_name www.timinglee.org;location / {proxy_pass http://172.25.254.30;}location ~ /static {proxy_pass http://172.25.254.20:8080;}
}
# 后端web服務器必須要有相對于的訪問URL
[root@apache20 ~]# mkdir /var/www/html/static
[root@apache20 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html
[root@apache30 ~]# echo 172.25.254.30 > /var/www/html/index.html
# 重啟Nginx并訪問測試:
[2025-07-25 17:09.35] ~
[Administrator.DESKTOP-P19CNDN] ? curl www.timinglee.org/static/
static 172.25.254.20
[2025-07-25 17:09.39] ~
[Administrator.DESKTOP-P19CNDN] ? curl www.timinglee.org
172.25.254.30
6.1.1.3.2 針對特定的資源實現代理
[root@Nginx ~]# vim /apps/nginx/conf.d/vhost.conf
server {listen 80;server_name www.timinglee.org;location / {proxy_pass http://172.25.254.30;}location ~ \.(png|jpg|gif) {proxy_pass http://172.25.254.20:8080;}
}
6.1.1.4 反向代理示例: 緩存功能
proxy_cache zone_name | off; 默認off
# 指明調用的緩存,或關閉緩存機制;Context:http, server, location
# zone_name 表示緩存的名稱.需要由proxy_cache_path事先定義proxy_cache_key string;
# 緩存中用于“鍵”的內容,默認值:proxy_cache_key $scheme$proxy_host$request_uri;proxy_cache_valid [code ...] time;
# 定義對特定響應碼的響應內容的緩存時長,定義在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_path;
# 定義可用于proxy功能的緩存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off]
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number]
[manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off]
[purger_files=number] [purger_sleep=time] [purger_threshold=time];
# 示例:在http配置定義緩存信息
proxy_cache_path /var/cache/nginx/proxy_cache # 定義緩存保存路徑,proxy_cache會自動創建
levels=1:2:2 # 定義緩存目錄結構層次
# 1:2:2可以生成
2^4x2^8x2^8=2^20=1048576個目錄
keys_zone=proxycache:20m # 指內存中緩存的大小,主要用于存放key和metadata
(如:使用次數)
# 一般1M可存放8000個左右的key
inactive=120s # 緩存有效時間
max_size=10g; # 最大磁盤占用空間,磁盤存入文件內容的緩存空間最大值
# 調用緩存功能,需要定義在相應的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; # 對指定的數據進行MD5的運算做為緩存的key
proxy_cache_valid 200 302 301 10m; # 指定的狀態碼返回的數據緩存多長時間
proxy_cache_valid any 1m; # 除指定的狀態碼返回的數據以外的緩存多長時間,必須設置,否則不會緩存
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 |
http_502 | http_503 | http_504 | http_403 | http_404 | off ; #默認是off
# 在被代理的后端服務器出現哪種情況下,可直接使用過期的緩存響應客戶端
# 示例
proxy_cache_use_stale error http_502 http_503;
proxy_cache_methods GET | HEAD | POST ...;
# 對哪些客戶端請求方法對應的響應進行緩存,GET和HEAD方法總是被緩存
6.1.1.4.1 非緩存場景壓測
# 準備后端httpd服務器
[root@apache20 app1]# pwd
/var/www/html/static
[root@apache20 static]# cat /var/log/messages > ./log.html # 準備測試頁面
[root@apache30 ~]# ab -n1000 -c100 http://www.timinglee.org/static/index.html
Concurrency Level: 100
Time taken for tests: 23.238 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2011251000 bytes
HTML transferred: 2010991000 bytes
Requests per second: 43.03 [#/sec] (mean)
Time per request: 2323.789 [ms] (mean)
Time per request: 23.238 [ms] (mean, across all concurrent requests)
Transfer rate: 84521.97 [Kbytes/sec] received
6.1.1.4.2 準備緩存配置
[root@Nginx ~]# vim /apps/nginx/conf/nginx.conf
@@@@內容省略@@@@
# gzip on;
proxy_cache_path /apps/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m
inactive=120s max_size=1g; #配置在nginx.conf http配置段
[root@Nginx ~]# vim /apps/nginx/conf.d/vhost.conf
location ~ /static { # 要緩存的URL 或者放在server配置項對所有URL都進行緩存proxy_pass http://172.25.254.20:8080;proxy_cache proxycache;proxy_cache_key $request_uri;proxy_cache_valid 200 302 301 10m;proxy_cache_valid any 1m; # 必須指定哪些響應碼的緩存
}
# /data/nginx/proxycache/ 目錄會自動生成
[root@Nginx ~]# ll /apps/nginx/proxy_cache/ -d
drwx------ 3 nginx root 4096 7月 25 20:07 /apps/nginx/proxy_cache/
[root@Nginx ~]# tree /apps/nginx/proxy_cache/
/data/nginx/proxycache/
0 directories, 0 files
6.1.1.4.3 訪問并驗證緩存文件
#訪問web并驗證緩存目錄
[root@apache30 ~]# ab -n1000 -c100 http://www.timinglee.org/static/index.html
[root@centos8 ~]# ab -n 2000 -c200 http://www.timinglee.org/static/log.html
Concurrency Level: 100
Time taken for tests: 10.535 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2011251000 bytes
HTML transferred: 2010991000 bytes
Requests per second: 94.92 [#/sec] (mean)
Time per request: 1053.507 [ms] (mean)
Time per request: 10.535 [ms] (mean, across all concurrent requests)
Transfer rate: 186435.60 [Kbytes/sec] received# 驗證緩存目錄結構及文件大小
[root@Nginx ~]# tree /apps/nginx/proxy_cache/
/apps/nginx/proxy_cache/
└── e
└── 50
└── 99
└── 319432ef3663735a9d3cb4e0c1d9950e
3 directories, 0 files
6.1.2 http 反向代理負載均衡

6.1.2.1 http upstream配置參數
# 自定義一組服務器,配置在http塊內
upstream name {
server .....
......
}
# 示例
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
server address [parameters];
# 配置一個后端web服務器,配置在upstream內,至少要有一個server服務器配置。
# server支持的parameters如下:
weight=number # 設置權重,默認為1,實現類似于LVS中的WRR,WLC等
max_conns=number # 給當前后端server設置最大活動鏈接數,默認為0表示沒有限制
max_fails=number # 后端服務器的下線條件,當客戶端訪問時,對本次調度選中的后端服務器連續進 行檢測多少次,如果都失敗就標記為不可用,默認為1次,當客戶端訪問時,才會利用TCP觸發對探測后端服務器健康性檢查,而非周期性的探測fail_timeout=time # 后端服務器的上線條件,對已經檢測到處于不可用的后端服務器,每隔此時間間隔再次進行檢測是否恢復可用,如果發現可用,則將后端服務器參與調度,默認為10秒
backup # 設置為備份服務器,當所有后端服務器不可用時,才會啟用此備用服務器
down # 標記為down狀態,可以平滑下線后端服務器resolve # 當server定義的是主機名的時候,當A記錄發生變化會自動應用新IP而不用重啟Nginx
hash KEY [consistent];
# 基于指定請求報文中首部字段或者URI等key做hash計算,使用consistent參數,將使用ketama一致性
hash算法,適用于后端是Cache服務器(如varnish)時使用,consistent定義使用一致性hash運算,一致
性hash基于取模運算
hash $request_uri consistent; # 基于用戶請求的uri做hash
hash $cookie_sessionid # 基于cookie中的sessionid這個key進行hash調度,實現會話綁定
ip_hash;
# 源地址hash調度方法,基于的客戶端的remote_addr(源地址IPv4的前24位或整個IPv6地址)做hash計
算,以實現會話保持
least_conn;
# 最少連接調度算法,優先將客戶端請求調度到當前連接最少的后端服務器,相當于LVS中的WLC
6.1.2.2 反向代理示例: 后端多臺 web服務器
172.25.254.10 # Nginx 代理服務器
172.25.254.20 # 后端web A,Apache部署
172.25.254.30 # 后端web B,Apache部署
[root@apache20 ~]# yum install httpd -y
[root@apache20 ~]# echo "web1 172.25.254.20" > /var/www/html/index.html
[root@apache20 ~]# systemctl enable --now httpd
[root@apache30 ~]# yum install httpd -y
[root@apache30 ~]# echo "web2 172.25.254.30" >> /var/www/html/index.html
[root@apache30 ~]# systemctl enable --now httpd# 訪問測試
[root@centos8 ~]# curl http://172.25.254.20
web1 172.25.254.20
[root@centos8 ~]# curl http://172.25.254.30
web2 172.25.254.30
[root@centos8 ~]# cat /apps/nginx/conf/conf.d/pc.conf
upstream webserver {# ip_hash;# hash $request_uri consistent;# hash $cookie_lee# least_conn;server 172.25.254.20:8080 weight=1 fail_timeout=15s max_fails=3;server 172.25.254.30:80 weight=1 fail_timeout=15s max_fails=3;server 172.25.254.10:80 backup;
}
server {listen 80;server_name www.timinglee.org;location ~ / {proxy_pass http://webserver;}
}# 重啟Nginx 并訪問測試
[Administrator.DESKTOP-P19CNDN] ? curl www.timinglee.org
172.25.254.20 web
[Administrator.DESKTOP-P19CNDN] ? curl www.timinglee.org
172.25.254.30 web
#關閉172.25.254.20和172.25.254.30,測試nginx backup服務器可用性:
[Administrator.DESKTOP-P19CNDN] ? while true;do curl
http://www.timinglee.org;sleep 1;done
[root@Nginx ~]# vim /apps/nginx/conf.d/vhost.conf
http {upstream websrvs {hash $cookie_hello; # hello是cookie的key的名稱server 10.0.0.101:80 weight=2;server 10.0.0.102:80 weight-1;}
}[root@centos8 ~]# vim /apps/nginx/conf/conf.d/pc.conf
upstream webserver {# ip_hash;# hash $request_uri consistent;hash $cookie_lee;# least_conn;server 172.25.254.20:8080 weight=1 fail_timeout=15s max_fails=3;server 172.25.254.30:80 weight=1 fail_timeout=15s max_fails=3;# server 172.25.254.10:80 backup;
}
server {listen 80;server_name www.timinglee.org;location ~ / {proxy_pass http://webserver;}
}
#測試
[Administrator.DESKTOP-P19CNDN] ? curl -b lee=1 www.timinglee.org
6.2 實現 Nginx 四層負載均衡
6.2.1 tcp負載均衡配置參數
stream { # 定義stream相關的服務;
Context:mainupstream backend { # 定義后端服務器hash $remote_addr consistent; # 定義調度算法server backend1.example.com:12345 weight=5; # 定義具體serverserver 127.0.0.1:12345 max_fails=3 fail_timeout=30s;server unix:/tmp/backend3;}upstream dns { # 定義后端服務器server 10.0.0.1:53; #定義具體serverserver dns.example.com:53;}
server { # 定義serverlisten 12345; # 監聽IP:PORTproxy_connect_timeout 1s; # 連接超時時間proxy_timeout 3s; # 轉發超時時間proxy_pass backend; # 轉發到具體服務器組
}
server {listen 127.0.0.1:53 udp reuseport;proxy_timeout 20s;proxy_pass dns;
}
server {listen [::1]:12345;proxy_pass unix:/tmp/stream.socket;}
}
6.2.2 負載均衡實例: MySQL
#在apache20中安裝mysql
[root@apache20 ~]# yum install mariadb-server -y
[root@apache20 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=20
[root@apache20 ~]# systemctl start mariadb
[root@apache20 ~]# mysql -e "grant all on *.* to lee@'%' identified by 'lee';"
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.20 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
#在apache30重復以上步驟并在apache20上測試
[root@Nginx ~]# vim /apps/nginx/conf/tcp/tcp.conf
stream {
upstream mysql_server {
server 172.25.254.20:3306 max_fails=3 fail_timeout=30s;
server 172.25.254.30:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.10:3306;
proxy_pass mysql_server;
proxy_connect_timeout 30s;
proxy_timeout 300s;
}
}
# 重啟nginx并訪問測試:
[root@Nginx ~]# nginx -s reload
# 測試通過nginx負載連接MySQL:
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+
# 在10.0.0.28停止MySQL服務
[root@apache20 ~]# systemctl stop mariadb
# 再次測試訪問,只會看到mysql-server1.timinglee.org進行響應
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+
6.2.3 udp 負載均衡實例: DNS
stream {upstream dns_server{server 172.25.254.20:53 max_fails=3 fail_timeout=30s;server 172.25.254.30:53 max_fails=3 fail_timeout=30s;}server {listen 172.25.254.10:53 udp;proxy_pass dns_server;proxy_timeout 1s;proxy_responses 1; # 使用UDP協議時,設置代理服務器響應客戶端期望的數據報文數# 該值作為會話的終止條件error_log logs/dns.log;}
}測試:
[root@apache30 named]# dig www.timinglee.org @172.25.254.10
; <<>> DiG 9.16.23 <<>> www.timinglee.org @172.25.254.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33888
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 701447f1bdd8acea0100000066a27b465426b2b4bc7f1dc3 (good)
;; QUESTION SECTION:
;www.timinglee.org. IN A
;; ANSWER SECTION:
www.timinglee.org. 86400 IN A 172.25.254.20
;; Query time: 2 msec
;; SERVER: 172.25.254.10#53(172.25.254.10)
;; WHEN: Fri Jul 26 00:20:22 CST 2024
;; MSG SIZE rcvd: 90
[root@apache30 named]# dig www.timinglee.org @172.25.254.10
; <<>> DiG 9.16.23 <<>> www.timinglee.org @172.25.254.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8932
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 8ecb61bbfe2716df0100000066a27b47a3bb0c3d8e537858 (good)
;; QUESTION SECTION:
;www.timinglee.org. IN A
;; ANSWER SECTION:
www.timinglee.org. 86400 IN A 172.25.254.30
;; Query time: 1 msec
;; SERVER: 172.25.254.10#53(172.25.254.10)
;; WHEN: Fri Jul 26 00:20:23 CST 2024
;; MSG SIZE rcvd: 90
6.3 實現 FastCGI
為什么會有FastCGI?
- FastCGI進程管理器)是一個實現了Fastcgi的程序,并且提供進程管理的功能。
- 進程包括master進程和worker進程。master進程只有一個,負責監聽端口,接受來自web server
- 的請求worker進程一般會有多個,每個進程中會嵌入一個PHP解析器,進行PHP代碼的處理。
6.3.1 FastCGI配置指令
fastcgi_pass address:port;
# 轉發請求到后端服務器,address為后端的fastcgi server的地址,可用位置:location, if in
location
fastcgi_index name;
# fastcgi默認的主頁資源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
# 設置傳遞給FastCGI服務器的參數值,可以是文本,變量或組合,可用于將Nginx的內置變量賦值給自定義key
fastcgi_param REMOTE_ADDR $remote_addr; # 客戶端源IP
fastcgi_param REMOTE_PORT $remote_port; # 客戶端源端口
fastcgi_param SERVER_ADDR $server_addr; # 請求的服務器IP地址
fastcgi_param SERVER_PORT $server_port; # 請求的服務器端口
fastcgi_param SERVER_NAME $server_name; # 請求的server nameNginx默認配置示例:
location ~ \.php$ {root /scripts;fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # 默認腳本路徑# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;include fastcgi_params; # 此文件默認系統已提供,存放的相對路徑為prefix/conf
}
6.3.2 FastCGI實戰案例 : Nginx與php-fpm在同一服務器
# 利用yum解決php依賴
[root@Nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel oniguruma-devel
# 解壓源碼并安裝
[root@Nginx ~]# ./configure \
--prefix=/usr/local/php \ # 安裝路徑
--with-config-file-path=/usr/local/php/etc \ # 指定配置路徑
--enable-fpm \ # 用cgi方式啟動程序
--with-fpm-user=nginx \ # 指定運行用戶身份
--with-fpm-group=nginx \
--with-curl \ # 打開curl瀏覽器支持
--with-iconv \ # 啟用iconv函數,轉換字符編碼
--with-mhash \ # mhash加密方式擴展庫
--with-zlib \ # 支持zlib庫,用于壓縮http壓縮傳輸
--with-openssl \ # 支持ssl加密
--enable-mysqlnd \ # mysql數據庫
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ # 關閉debug功能
--enable-sockets \ # 支持套接字訪問
--enable-soap \ # 支持soap擴展協議
--enable-xml \ # 支持xml
--enable-ftp \ # 支持ftp
--enable-gd \ # 支持gd庫
--enable-exif \ # 支持圖片元數據
--enable-mbstring \ # 支持多字節字符串
--enable-bcmath \ # 打開圖片大小調整,用到zabbix監控的時候用到了這個模塊
--with-fpm-systemd # 支持systemctl 管理cgi
[root@Nginx ~]# cd /usr/local/php/etc
[root@Nginx etc]# cp php-fpm.conf.default php-fpm.conf
[root@Nginx etc]# vim php-fpm.conf
去掉注釋
pid = run/php-fpm.pid # 指定pid文件存放位置
[root@Nginx etc]# cd php-fpm.d/
[root@Nginx php-fpm.d]# cp www.conf.default www.conf
# 生成主配置文件
[root@Nginx php-fpm.d]# cd /root/php-8.3.9/
[root@Nginx php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@Nginx ~]# vim /usr/local/php/etc/php.ini
[Date]
; Defines the default timezone used by the date functions
; https://php.net/date.timezone
date.timezone = Asia/Shanghai # 修改時區
# 生成啟動文件
[root@Nginx ~]# cd /root/php-8.3.9/
[root@Nginx php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by
this unit.
# ProtectSystem=full # 注釋該內容
[root@Nginx php-8.3.9]# systemctl start php-fpm.service
[root@Nginx php-8.3.9]# netstat -antlupe | grep php
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 0
820758 176202/php-fpm: mas
[root@Nginx ~]# mkdir /data/php -p
[root@centos8 ~]# cat /data/php/index.php # php測試頁面
<?php
phpinfo();
?>
[root@Nginx ~]# vim /apps/nginx/conf.d/php.conf
server {listen 80;server_name php.timinglee.org;root /data/php;location ~ \.php$ {fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;include fastcgi.conf;}
}
# 重啟Nginx并訪問web測試
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# vim .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin:/apps/nginx/sbin:/usr/local/php/bin
export PATH
[root@Nginx ~]# source .bash_profile
6.3.3 php的動態擴展模塊(php的緩存模塊)

[root@Nginx ~]# tar zxf memcache-8.2.tgz
[root@Nginx ~]# cd memcache-8.2/
[root@Nginx memcache-8.2]# yum install autoconf
[root@Nginx memcache-8.2]# phpize
[root@Nginx memcache-8.2]# ./configure && make && make install
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-nonzts-20230831/
[root@Nginx memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-
20230831/
memcache.so opcache.so
[root@Nginx ~]# cd memcache-8.2/
[root@Nginx memcache-8.2]# ls
autom4te.cache config.log configure.ac example.php Makefile.fragments
README
build config.m4 config.w32 include Makefile.objects runtests.php
config9.m4 config.nice CREDITS libtool memcache.la src
config.h config.status docker LICENSE memcache.php
tests
config.h.in configure Dockerfile Makefile modules
[root@Nginx memcache-8.2]# cp example.php memcache.php /data/php/
[root@Nginx ~]# vim /data/php/memcache.php
define('ADMIN_USERNAME','admin'); // Admin Username
define('ADMIN_PASSWORD','lee'); // Admin Password
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
$MEMCACHE_SERVERS[] = 'localhost:11211'; // add more as an array
#$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
[root@Nginx ~]# vim /usr/local/php/etc/php.ini
;extension=zip
extension=memcache
;zend_extension=opcache
[root@Nginx ~]# systemctl reload php-fpm
[root@Nginx no-debug-non-zts-20230831]# php -m | grep mem
memcache
[root@Nginx ~]# yum install memcached -y
[root@Nginx ~]# systemctl enable --now memcached.service
[root@Nginx ~]# netstat -antlupe | grep memcache
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN
976 1037243 186762/memcached
[root@Nginx ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"
訪問 http://php.timinglee.org/example.php 不斷刷新
訪問 http://php.timinglee.org/memcache.php 查看命中效果
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/index.php
@@@內容忽略@@@
Concurrency Level: 10
Time taken for tests: 0.514 seconds
Complete requests: 500
Failed requests: 44
(Connect: 0, Receive: 0, Length: 44, Exceptions: 0)
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/example.php
@@@內容忽略@@@
Concurrency Level: 10
Time taken for tests: 0.452 seconds
Complete requests: 500
Failed requests: 0
6.3.4 php高速緩存
[root@Nginx ~]# rm -fr /apps/nginx/
[root@Nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@Nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@Nginx ~]# cd nginx-1.26.1/
[root@Nginx nginx-1.26.1]# ./configure --prefix=/apps/nginx --user=nginx --
group=nginx --with-http_ssl_module --with-http_v2_module --withhttp_realip_module --with-http_stub_status_module --with-http_gzip_static_module
--with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --
add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-
0.33
[root@Nginx nginx-1.26.1]# make && make install
[root@Nginx ~]# vim /apps/nginx/conf.d/php.conf
upstream memcache {
server 127.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name php.timinglee.org;
root /data/php;
location /memc {
internal;
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
memc_read_timeout 100ms;
set $memc_key $query_string; #使用內置變量$query_string來作為key
set $memc_exptime 300; #緩存失效時間300秒
memc_pass memcache;
}
location ~ \.php$ {
set $key $uri$args; #設定key的值
srcache_fetch GET /memc $key; #檢測mem中是否有要訪問的php
srcache_store PUT /memc $key; #緩存為加載的php數據
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
[root@Nginx ~]# systemctl start nginx.service
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/index.php
Concurrency Level: 10
Time taken for tests: 0.255 seconds
Complete requests: 500
Failed requests: 0
7?nginx 二次開發版本
7.1 openresty
7.2 編譯安裝 openresty
[root@Nginx ~]#dnf -yq install gcc pcre-devel openssl-devel perl
[root@Nginx ~]#useradd -r -s /sbin/nologin nginx
[root@Nginx ~]#cd /usr/local/src
[root@Nginx src]#wget https://openresty.org/download/openresty-1.17.8.2.tar.gz
[root@Nginx src]#tar xf openresty-1.17.8.2.tar.gz
[root@Nginx src]#cd openresty-1.17.8.2/
[root@Nginx openresty-1.17.8.2]#./configure \
--prefix=/apps/openresty \
--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
[root@Nginx openresty-1.17.8.2]#make && make install
[root@Nginx openresty-1.17.8.2]#ln -s /apps/openresty/bin/* /usr/bin/
[root@Nginx openresty-1.17.8.2]#openresty -v
nginx version: openresty/1.17.8.2
[root@Nginx openresty-1.17.8.2]#openresty
[root@Nginx openresty-1.17.8.2]#ps -ef |grep nginx
[root@Nginx ~]#curl 10.0.0.18