學習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: