當前位置: 妍妍網 > 碼農

只知道 Nginx 牛逼!卻不知道它怎麽支持百萬並行?

2024-03-15碼農

戳下方名片 ,關註並 星標

回復「 1024 」獲取 2TB 學習資源!

👉 體系化學習:

特色專欄

/ /

/ /

/ /

/ /

/ /

大家好,我是民工哥!

前段時間在網上看到一個有意思的話題:

確實,這是一個好問題,面試常問,很多人都在這上面栽過跟頭!

所以,今天我們就來一起聊一聊這個話題。

大家都知道,無論是運維、開發、測試,Nginx 技術棧的學習總是必不可少的,只是不同的崗位掌握的深度與廣度不同而已。

什麽是 Nginx?

Nginx 是開源、高效能、高可靠的 Web 和反向代理伺服器,支持熱部署,幾乎可以做到 7 * 24 小時不間斷執行,還可在不間斷服務的情況下對軟體版本進行熱更新。Nginx 效能非常牛逼,占用記憶體少、並行能力強、能支持高並行,支持絕大部份協定,如TCP、UDP、SMTP、HTTPS等。最重要的是, Nginx 是免費開源的且可以商業化,配置使用也比較簡單。

在中國有眾多互聯網大廠,如百度、京東、新浪、網易、騰訊等都在使用 Nginx,也有很多高知名度的國外網站也在使用 Nginx,比如:Netflix、GitHub、SoundCloud、MaxCDN等。

官方網站:http://www.nginx.org

Nginx 架構

Nginx 是如何支持百萬並行?

Nginx 能夠支持百萬並行連線,主要透過以下幾個方面來實作:

主行程與工作行程

當 Nginx 啟動時,會生成主行程(master)和工作行程(worker)。

[root@nginx ~]# ps -ef|grep nginx
root 6324 1 0 09:06 ? 00:00:00 nginx: master process /usr/local/nginx-1.12.2/sbin/nginx
nobody 6325 6324 0 09:06 ? 00:00:00 nginx: worker process
root 6327 1244 0 09:06 pts/0 00:00:00 grep --color=auto nginx

  • 主行程主要負責排程工作行程(管理 Worker 行程),並不直接處理網路請求。

  • 工作行程(所有 Worker 行程都對等的)是實際處理網路請求及響應的行程,每個工作行程都是獨立的,可同時處理數以千計的網路請求。

  • 事件驅動模型

    Nginx 的事件驅動模型由事件收集器、發送器和處理器三部份基本單元組成。

  • 事件收集器:收集 worker 行程的各種 IO 請求

  • 事件發送器:將 IO 事件發送到事件處理器

  • 事件處理器:處理各種事件的響應工作

  • Nginx 事件驅動架構是基於異步及非阻塞的方式,這種設計允許 Nginx 同時處理多個網路請求。

    當一個客戶端發起請求時,Nginx 會將該請求交給一個工作行程,由工作行程負責處理請求。工作行程采用異步方式處理請求,每個請求在一個單獨的工作行程中處理,這樣就不會因為一個請求的阻塞而影響其他請求的處理。因些,它可以同時處理多個客戶端請求,從而提高了並行處理能力。

    非阻塞IO

    Nginx 在處理請求時采用了非阻塞 I/O 操作,這意味著它不會在等待 I/O 操作完成時阻塞行程。透過使用非阻塞 I/O,Nginx 可以同時處理多個 I/O 操作,從而提高了整體的處理能力。

    如前面的圖,事件發送器會將事件放入一個類似待處理的列表中,然後采用非非阻塞 I/O 方式來呼叫事件處理器來處理這個請求。

    這種處理模式我們又將其稱為「多路復用 I/O」,最常見的有括這三種:select 模型、poll模型、epoll 模型。

    記憶體管理

    Nginx 使用了強大記憶體池技術來管理記憶體,記憶體池中的記憶體塊是預先分配的,避免了頻繁的記憶體分配和釋放操作,從而減少了記憶體分配和釋放的開銷,這樣可以使 Nginx 在處理大量並行連線時更加高效。

    負載均衡

    Nginx 可以作為反向代理伺服器使用,將客戶端請求轉發給後端伺服器處理。透過配置負載均衡策略,Nginx 可以將請求分發到多個後端伺服器,進一步提高整體的處理能力,這也是它給支持百萬並行的一大關鍵技術。

    upstream server_pools { 
    server 192.168.1.100:8888 weight=5;
    server 192.168.1.101:9999 weight=5;
    server 192.168.1.102:6666 weight=5;
    #weigth參數列示權值,權值越高被分配到的機率越大
    }
    server {
    listen 80; 
    server_name mingongge.com;
    location / {
    proxy_pass http://server_pools; 
    }
    }

    Nginx 實作負載均衡的策略

  • 輪詢策略:預設情況下采用的策略,將所有客戶端請求輪詢分配給伺服端。這種策略是可以正常工作的,但是如果其中某一台伺服器壓力太大,出現延遲,會影響所有分配在這台伺服器下的使用者。

  • 最小連線數策略:將請求優先分配給壓力較小的伺服器,它可以平衡每個佇列的長度,並避免向壓力大的伺服器添加更多的請求。

  • 最快響應時間策略:優先分配給響應時間最短的伺服器。

  • 客戶端 ip 繫結策略:來自同一個 ip 的請求永遠只分配一台伺服器,有效解決了動態網頁存在的 session 共享問題。

  • 緩存

    Nginx 支持緩存功能,Nginx 緩存作為效能最佳化的一個重要手段,可以極大減輕後端伺服器的負載。

    我們可以透過 Nginx 配置將靜態檔儲存在本地磁盤上,直接提供給客戶端,減少了請求後端伺服器的次數,提高了效能和並行處理能力。

    proxy_cache_path #代理緩存的路徑
    #語法格式
    proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_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];
    proxy_cache #開啟或關閉代理緩存
    #語法格式
    proxy_cache zone | off; #zone為記憶體區域的名稱,即上面中keys_zone設定的名稱。
    proxy_cache_key #定義如何生成緩存的鍵
    #語法格式
    proxy_cache_key string; #string為生成Key的規則,如proxy_host$request_uri。
    proxy_cache_valid #緩存生效的狀態碼與過期時間。
    #語法格式
    proxy_cache_valid [code ...] time; #code為狀態碼,time為有效時間,可以根據狀態碼設定不同的緩存時間。如:proxy_cache_valid 200 302 30m;
    proxy_cache_min_uses #設定資源被請求多少次後被緩存。
    #語法格式
    proxy_cache_min_uses number; #number為次數,預設為1。
    proxy_cache_use_stale #當後端出現異常時,是否允許Nginx返回緩存作為響應。
    #語法格式
    proxy_cache_use_stale error; #error為錯誤型別
    proxy_cache_lock #是否開啟鎖機制
    #語法格式
    proxy_cache_lock on | off;
    proxy_cache_lock_timeout #配置鎖超時機制,超出規定時間後會釋放請求。
    #語法格式
    proxy_cache_lock_timeout time;
    proxy_cache_methods #設定對於那些HTTP方法開啟緩存。
    #語法格式
    proxy_cache_methods method; #method為請求方法型別,如GET、HEAD等。
    proxy_no_cache #設定不儲存緩存的條件,符合時不會保存。
    #語法格式
    proxy_no_cache string...; #string為條件,如arg_nocache $arg_comment;
    proxy_cache_bypass #設定不讀取緩存的條件,符合時不會從緩存中讀取。
    #語法格式
    proxy_cache_bypass string...; #與上面proxy_no_cache的配置方法類似。
    add_header #配置往響應頭中添加欄位資訊。
    #語法格式
    add_header fieldName fieldValue;
    $upstream_cache_status#記錄了緩存是否命中的資訊,存在以下多種情況:
    MISS:請求未命中緩存。
    HIT:請求命中緩存。
    EXPIRED:請求命中緩存但緩存已過期。
    STALE:請求命中了陳舊緩存。
    REVALIDDATED:Nginx驗證陳舊緩存依然有效。
    UPDATING:命中的緩存內容陳舊,但正在更新緩存。
    BYPASS:響應結果是從原始伺服器獲取的。
    #註:這是一個Nginx內建變量,與上面的參數不同。










    下面是一個配置例項

    server{
    location / {
    # 使用名為nginx_cache的緩存空間
    proxy_cache hot_cache;
    # 對於200、206、304、301、302狀態碼的數據緩存1天
    proxy_cache_valid 200 206 304 301 302 1d;
    # 對於其他狀態的數據緩存30分鐘
    proxy_cache_valid any 30m;
    # 定義生成緩存鍵的規則(請求的url+參數作為key)
    proxy_cache_key $host$uri$is_args$args;
    # 資源至少被重復存取三次後再加入緩存
    proxy_cache_min_uses 3;
    # 出現重復請求時,只讓一個去後端讀數據,其他的從緩存中讀取
    proxy_cache_lock on;
    # 上面的鎖超時時間為3s,超過3s未獲取數據,其他請求直接去後端
    proxy_cache_lock_timeout 3s;
    # 對於請求參數或cookie中聲明了不緩存的數據,不再加入緩存
    proxy_no_cache $cookie_nocache$arg_nocache$arg_comment;
    # 在響應頭中添加一個緩存是否命中的狀態(便於偵錯)
    add_header Cache-status $upstream_cache_status;
    }

    模組化設計

    Nginx 的模組化設計使得它能夠根據需求選擇和載入不同的模組,以支持各種功能,如日誌記錄、身份驗證等。這種設計靈活性高,便於擴充套件和維護。

    Nginx 的模組主要包括核心模組、標準HTTP模組、可選HTTP模組、信件服務模組和第三方模組等。這些模組透過事件驅動模型和非阻塞I/O等技術手段,實作了高效地處理大量的並行連線,支持百萬級別的並行存取。

    Nginx 這種模組化設計使得它可以根據不同的需求去載入不同的模組,從而去支持各種不同的功能,這個設計非常靈活,且便於擴充套件與維護。

    核心模組是Nginx的基礎部份,主要實作了底層的自身的一部份通訊協定,也為其他的一些模組和Nginx的行程等內容提供了一個執行時的環境。標準HTTP模組是核心中的一部份,負責定義除配置模組之外的其他模組。可選HTTP模組則提供了更多高級功能,如負載均衡、SSL加密等。信件服務模組則與信件相關。第三方模組則是一些由第三方提供的模組,可以擴充套件Nginx的功能。

    總的來說,Nginx 的模組化設計是其高效能、高並行能力的關鍵因素之一。

    代理機制

    Nginx 作為反向代理伺服器使用時,會接收客戶端的請求並轉發給後端伺服器處理。透過代理機制,Nginx能夠實作請求的轉發、負載均衡、緩存等功能,提高了處理效能和並行能力。

    相關的介紹文章可以參考: 以下是一個基本的配置範例:

    http {
    .............
    upstream product_server{
    127.0.0.1:8081;
    }
    upstream admin_server{
    127.0.0.1:8082;
    }
    upstream test_server{
    127.0.0.1:8083;
    }
    server {
    #預設指向product的server
    location / {
    proxy_pass http://product_server;
    }
    location /product/{
    proxy_pass http://product_server;
    }
    location /admin/ {
    proxy_pass http://admin_server;
    }
    location /test/ {
    proxy_pass http://test_server;
    }
    }
    }





    Nginx透過這些優秀的技術設計,然後將這些技術手段在 Nginx 中廣泛套用,使得 Nginx 能夠高效地處理大量的並行連線,我們在實際套用中,可以透過合理的配置 Nginx,來提高與最佳化其效能,進一步提高並行處理能力,從而去支持百萬級別的並行存取。

    註:圖片均來自於網路素材,版權歸原作者所有,本文只作分享技術使用。

    公眾號讀者專屬技術群

    構建高品質的技術交流社群,歡迎從事後端開發、運維技術進群( 備註崗位,已在技術交流群的請勿重復添加微信好友 )。主要以技術交流、內推、行業探討為主,請文明發言。 廣告人士勿入,切勿輕信私聊,防止被騙。

    掃碼加我好友,拉你進群

    PS:因為公眾號平台更改了推播規則,如果不想錯過內容,記得讀完點一下 在看 ,加個 星標 ,這樣每次新文章推播才會第一時間出現在你的訂閱列表裏。 在看 支持我們吧!