學習nginx的一點記錄

一、nginx定義

Nginx是一款輕量級的高性能的,具備HTTP反向代理負載均衡的web伺服器,同時還提供IMAP/POP3/SMTP服務,其特點是佔用記憶體少並發能力強

二、nginx基本功能

1、部署多個虛擬主機

多個虛擬機就是指在nginx目錄下建立多個文件夾,作為虛擬工作目錄。使多個虛擬空間可以使用不同的地址訪問。

在配置文件中設置如下:

server {
    listen       8001;
    server_name  localhost;
    location / {
    root   html8001;
        index  index.html index.htm;
    }
}
server {
    listen       8002;
    server_name  localhost;
    location / {
        root   html8002;
        index  index.html index.htm;
    }
}

2、反向代理

首先說一下正向代理,正向代理是指對客戶端的代理,簡單來說就是客戶端想要訪問某個資源,但是無法直接訪問,於是通過代理伺服器訪問伺服器,代理伺服器是為客戶端服務的,代理對象是客戶端。反向代理是指代理對象是伺服器,客戶端訪問的對象是代理伺服器,然後由代理伺服器將請求轉到伺服器,並將結果轉到客戶端。代理伺服器由服務端部署,可以幫助服務端做負載均衡、網關等事情,減輕了服務端的壓力,從而達到保護伺服器的目的。

反向代理配置

 upstrem lxpsun {
    server 127.0.0.1:8080
}
server {
    listen    8080;
    listen    somename:8080;
    server_name somename alias another.alias;
    
    location / {
        proxy_pass //lxpsun;
        index index.html index.htm;
    }
}

在配置文件中將root即本地主機目的地址使用Proxy_pass替換,Proxy_pass對應的值為要訪問的伺服器域名,upstrem lxpsun即為域名對應的伺服器IP地址。

3、負載均衡

負載均衡是指將多個請求按照某種策略分配不同的伺服器上進行處理,其目的是避免伺服器在短時間內接收大量的請求,導致伺服器崩潰,也就是說給伺服器分配的請求要儘可能的均衡。Nginx負載均衡通常需要使用反向代理,通過反向代理將請求交給伺服器處理。

Nginx目前自帶有三種負載均衡策略,分別是輪詢策略、權重策略和ip_harsh策略,第三方策略有fair(根據響應時間)策略、url_harsh策略。

  • 輪詢策略

輪詢策略是Nginx默認的,通過將每個請求按順序分配給伺服器,如果有伺服器掛掉,則從表中刪除該伺服器。該方法的優點是演算法邏輯簡單,缺點是未考慮到每台伺服器之間的不同性能等因素,導致負載分配不均衡。

  • 權重策略

考慮到不同伺服器處理請求的時間等因素,選擇給處理請求較快的伺服器分配的權重值大,反之,給處理請求較慢的伺服器分配的權重值小。也就是給處理請求快的伺服器更多的請求任務,給較慢的分配少一些的請求任務。保證負載的均衡性。

upstream lxpsun {
     server localhost:8080 weight=7;
     server localhost:8081 weight=3;
}

此時代表給8080埠的伺服器分配70%的請求任務,給8081埠分配30%的請求任務。

  • ip_hash策略

前兩個策略適合處理無狀態的請求任務,也就是一次訪問。但是當訪問一些登錄等需要保存客戶端用戶資訊的網站,那麼服務端需要保存session資訊,便於下次訪問。如果使用前兩種策略,就會造成每次訪問都要提供客戶端資訊。因此,通過ip計算對應的hash的結果進行分配,可以確保每次訪問都會轉到同一個伺服器,避免了每次都要提供客戶端資訊。

upstream lxpsun {
    ip_hash;
    server localhost:8080;
    server localhost:8081;
}
  • farir(響應時間)策略

該策略根據伺服器的響應時間進行分配,響應時間快的優先分配。

upstream lxpsun { 
    fair; 
    server localhost:8080;
    server localhost:8081;
}
  • url_hash策略

該方法與ip_hash策略相似,通過計算url並映射為hash值,使得同一個url訪問同一個伺服器,避免session等快取不起作用。

upstream lxpsun { 
    hash $request_uri; 
    hash_method crc32; 
    server localhost:8080;
    server localhost:8081;
} 

其中hash_method表示使用該hash演算法。

4、Web伺服器

Nginx本身適合處理靜態資源的訪問,在動態請求任務方面,則不如Apache伺服器。對於動靜分離的項目來說,可以把如html、css、圖片等靜態資源放在Nginx伺服器上,對於動態請求,可以反向代理給Apache等伺服器去處理,以減輕伺服器的訪問壓力。因此,Nginx比較適合接收大量的請求,可以體現出Nginx高並發的能力,並進行反向代理和負載均衡。此外,還可以將伺服器返回的數據進行存儲,使得下次相同的請求直接返回對應的值,起到了快取作用。Nginx作為流量入口還可以當做網關使用。

三、nginx配置文件

Nginx的配置文件Nginx.conf總共可以分為三個部分,分別是:全局模組、event模組、http模組或其它模組。

   1、全局模組

主要做一些全局方面的Nginx配置,例如worker_process,該變數表示Nginx的worker進程的數量,值越大,並發處理的量也越多,也與伺服器的硬體相關,一般設置為伺服器的CPU或者核心的數量。

 

   2、event模組

event模組用於配置Nginx伺服器與用戶之間的網路連接,主要包含accept_mutex, multi_accept,worker_connections 和 use這幾個配置。

  • accept_mutex  

該配置主要是解決「驚群」問題,由於Nginx後台採用多進程模式,也就是運行了多個worker_process進程,當請求來臨時,會造成多個進程會被喚醒,獲取請求,但是最終只能有一個進程得到並處理請求。因為喚醒的進程數過多時,會影響Nginx整體的性能,所以需要設置accept_mutex,當設置為on時,會一個個喚醒進程去接收請求,直到請求被處理。如果Nginx伺服器worker進程較多,而請求較少時,適合開啟這種設置。一般worker進程的個數與伺服器的CPU個數有關,worker進程數較少,發生「驚群」情況也不會太嚴重,如果伺服器本身訪問量比較大的話,最好不要開啟,Nginx默認關閉該設置。

  • multi-accept

設置是否同時接收多個請求。

  • worker_connections

設置單個worker進程最大連接個數,默認1024。

  • use

設置Nginx伺服器用哪種方式去處理請求。分別有select、poll、epoll等。

events{ 
	accept_mutex on; 
	multi_accept on; 
	worker_commections 1024; 
	use epoll; 
}

詳情請參考:(64條消息) nginx events 模組配置_小星星1991的部落格-CSDN部落格_nginx 的events

     3、http模組

http模組主要分為全局部分、多個server部分、以及server下的多個location部分。

  • 全局部分

全局部分主要用來設置客戶端的類型、發送的請求大小、超時時間、 keepalive_timeout、是否開啟文件壓縮等。

  •  server部分

一個server部分相當於配置一個虛擬主機,server公共部分主要有listen和server_name兩個設置,listen為監聽的埠號,server_name為主機名,其他的還有ssl設置、proxy設置等。location部分主要用於根據請求的路徑匹配要訪問的資源或者代理伺服器。root表示要訪問的文件夾,proxy_pass表示代理伺服器名或者地址,配合upstream模組使用,用於負載均衡,請見關於2.3負載均衡的說明。

四、為什麼Nginx可以實現高並發

1、Nginx的工作過程

Nginx分為單工作進程(默認)和多工作進程模式。當Nginx伺服器啟動時,分別有一個master進程和一個或者多個worker進程。

master進程的作用:主要用於接收外界的訊號、給worker進程發送消息、監控worker進程、當老的worker進程因異常退出後,及時開啟新的worker進程補上。作為管理進程,他的主要任務是補齊worker進程、平滑升級、配置文件實時生效等。

worker進程的作用:主要用於接收請求,處理請求並返回數據。由於worker進程是由master進程fork過來的(包含listenfd,用於註冊讀事件)。當請求過來時,所有worker進程的listenfd都變成可讀的,但最終只有一個進程能夠處理該請求。

 

當客戶端發送請求到master進程後,由master進程通知給worker進程,如果請求較少時可以開啟accept_mutex,然後只能有一個worker進程搶到該請求。當worker進程搶到請求後,便使用 accept()接收到該請求,然後開始處理該請求,當請求需要IO操作或者訪問其它伺服器時,這個時候worker進程不會一直被阻塞,而是會註冊一個事件,等緩衝區里有數據時,再通知worker進程處理,這樣一來,worker進程就可以快速處理多個請求,實現高並發。

2、IO多路復用模型epoll

Nginx伺服器採用的是多進程工作模式,在每個worker進程下,只有一個執行緒,如果採用阻塞IO處理請求的話,就會造成處理請求緩慢,那麼就無法進行高並發處理,因此Nginx採用IO多路復用模型epoll進行處理。

首先當請求需要進行IO操作時,worker進程會將該請求對應的fd註冊為一個事件,並與執行IO操作的驅動程式建立回調關係,當驅動程式執行完成後,就會回調該事件,並將該事件添加到就緒鏈表中,然後通知主執行緒。因為IO多路復用使用了非同步阻塞,無需用戶進程負責讀寫,非同步 IO會負責將數據從內核空間拷貝到用戶空間。這樣情況下,Nginx就實現了在同一個進程中,利用同一個主執行緒去處理大量的請求。相較於select和poll來說,epoll能更好的完成IO復用操作,且不會隨著請求的增多,處理能力反而降低。

關於select、poll和epoll的區別和工作原理請參考:

你管這破玩意叫 IO 多路復用? (qq.com)

一文搞懂select、poll和epoll區別 – 知乎 (zhihu.com)

本部分參考如下:

Nginx工作原理(Master+Worker) – yblackd – 部落格園 (cnblogs.com)

Nginx為什麼支援那麼高的並發量? – 嗨,阿良 – 部落格園 (cnblogs.com)

(64條消息) nginx基本功能和工作原理_妄想翻身的鹹魚的部落格-CSDN部落格_nginx作用和工作原理

五、Nginx和Apache伺服器的區別

Nginx和Apache都是Web伺服器,但是因為兩個的工作原理不同,所以應用側重點也有所不同。Apache也是多進程的工作模式,分別有prefork、worker和event三種工作模式。

1、Apache伺服器的工作模式

prefork工作模式(默認)

在prefork模式中,伺服器會先fork若干個進程,避免因同時有多個請求時,需要創建進程帶來的開銷。也是為了避免頻繁的銷毀和創建進程。在prefork模式下,一個進程在同一時間內只能處理一個請求。那麼如果同時出現大量的請求時,就需要創建大量的進程來處理這些請求。在這種情況下,就會極大的加重作業系統的負擔,這點也是和Nginx伺服器不同的地方。

worker工作模式

在worker模式中,伺服器也會先fork若干個進程,其工作模式是阻塞IO+多進程中+多執行緒模式,在每個進程中開啟多個執行緒去處理請求。每個執行緒都會對應一個請求並處理。相比於prefork模式而言,開啟執行緒需要的時間和資源也小於開啟進程,適合於高並發的場景。但是缺點是隨著請求的增多,執行緒也會隨之增多,執行緒間的調度開銷也會增長,且如果單個執行緒出現問題時,也會影響同一進程中的其它執行緒。

2、兩者的缺點與結合

因此與Apache伺服器相比,Nginx伺服器適合處理IO密集型的請求。因為當請求需要IO處理時,Nginx伺服器的worker進程會通過註冊事件,然後去處理其它請求或者空閑,等待事件處理完畢後,再處理該請求。因此Nginx之所以更適合處理靜態資源,也是因為只涉及到IO操作。

如果請求本身涉及到複雜的計算時,Nginx的worker進程也就只能處理該請求,而不能同時處理其它請求,和Apache伺服器的prework工作模式差不多。不能發揮出Nginx的長處。

因此可以利用Nginx做反向代理和負載均衡,在前端接收大量的請求,然後根據負載均衡將請求轉發到多個伺服器。後台採用多個Apache伺服器接收請求,處理請求,計算結果,並將結果返回給Nginx伺服器。這樣做利用了Nginx伺服器高性能、高並發的優勢,同時由於Apache伺服器本身具有穩定性、模組多、功能強大,也能發揮出Apache伺服器的優勢。

Tags: