最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Nginx是如何解決驚群效應(yīng)的

 更新時(shí)間:2025年04月21日 09:26:03   作者:湯姆yu  
驚群效應(yīng)是Nginx在處理大量并發(fā)連接時(shí)可能出現(xiàn)的一個(gè)性能問題,本文主要介紹了淺談Nginx是如何解決驚群效應(yīng)的,具有一定的參考價(jià)值,感興趣的可以了解一下

什么是驚群效應(yīng)?

第一次聽到的這個(gè)名詞的時(shí)候覺得很是有趣,不知道是個(gè)什么意思,總覺得又是奇怪的中文翻譯導(dǎo)致的。

復(fù)雜的說(來源于網(wǎng)絡(luò))TLDR;

驚群效應(yīng)(thundering herd)是指多進(jìn)程(多線程)在同時(shí)阻塞等待同一個(gè)事件的時(shí)候(休眠狀態(tài)),如果等待的這個(gè)事件發(fā)生,那么他就會喚醒等待的所有進(jìn)程(或者線程),但是最終卻只能有一個(gè)進(jìn)程(線程)獲得這個(gè)時(shí)間的“控制權(quán)”,對該事件進(jìn)行處理,而其他進(jìn)程(線程)獲取“控制權(quán)”失敗,只能重新進(jìn)入休眠狀態(tài),這種現(xiàn)象和性能浪費(fèi)就叫做驚群效應(yīng)。

簡單的講(我的大白話)

有一道雷打下來,把很多人都吵醒了,但只有其中一個(gè)人去收衣服了。也就是:有一個(gè)請求過來了,把很多進(jìn)程都喚醒了,但只有其中一個(gè)能最終處理。

原因&問題

說起來其實(shí)也簡單,多數(shù)時(shí)候?yàn)榱颂岣邞?yīng)用的請求處理能力,會使用多進(jìn)程(多線程)去監(jiān)聽請求,當(dāng)請求來時(shí),因?yàn)槎加心芰μ幚?,所以就都被喚醒了?/p>

而問題就是,最終還是只能有一個(gè)進(jìn)程能來處理。當(dāng)請求多了,不停地喚醒、休眠、喚醒、休眠,做了很多的無用功,上下文切換又累,對吧。那怎么解決這個(gè)問題呢?下面就是今天要看的重點(diǎn),我們看看 nginx 是如何解決這個(gè)問題的。

Nginx 架構(gòu)

第一點(diǎn)我們需要了解 nginx 大致的架構(gòu)是怎么樣的。nginx 將進(jìn)程分為 master 和 worker 兩類,非常常見的一種 M-S 策略,也就是 master 負(fù)責(zé)統(tǒng)籌管理 worker,當(dāng)然它也負(fù)責(zé)如:啟動、讀取配置文件,監(jiān)聽處理各種信號等工作。

圖片

但是,第一個(gè)要注意的問題就出現(xiàn)了,master 的工作有且只有這些,對于請求來說它是不管的,就如同圖中所示,請求是直接被 worker 處理的。如此一來,請求應(yīng)該被哪個(gè) worker 處理呢?worker 內(nèi)部又是如何處理請求的呢?

nginx 使用 epoll

接下來我們就要知道 nginx 是如何使用 epoll 來處理請求的。下面可能會涉及到一些源碼的內(nèi)容,但不用擔(dān)心,你不需要全部理解,只需要知道它們的作用就可以了。順便我會簡單描述一下我是如何去找到這些源碼的位置的。

master 的工作

其實(shí) master 并不是毫無作為,至少端口是它來占的。

ngx_open_listening_sockets(ngx_cycle_t *cycle)
{
    .....
    for (i = 0; i < cycle->listening.nelts; i++) {
        .....
        if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {

        if (listen(s, ls[i].backlog) == -1) {
}

那么,根據(jù)我們 nginx.conf 的配置文件,看需要監(jiān)聽哪個(gè)端口,于是就去 bind 的了,這里沒問題。

【發(fā)現(xiàn)源碼】這里我是直接在代碼里面搜 bind 方法去找的,因?yàn)槲抑溃还苣阍趺礃?,你總是要綁定端口?/p>

然后是創(chuàng)建 worker 的,雖不起眼,但很關(guān)鍵。

ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
    char *name, ngx_int_t respawn)
{
    ....
    pid = fork();

【發(fā)現(xiàn)源碼】這里我直接搜 fork,整個(gè)項(xiàng)目里面需要 fork 的情況只有兩個(gè)地方,很快就找到了 worker

由于是 fork 創(chuàng)建的,也就是復(fù)制了一份 task_struct 結(jié)構(gòu)。所以 master 的幾乎全部它都有。

worker 的工作

nginx 有一個(gè)分模塊的思想,它將不同功能分成了不同的模塊,而 epoll 自然就是在 ngx_epoll_module.c 中了

ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
    ngx_epoll_conf_t  *epcf;

    epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);

    if (ep == -1) {
        ep = epoll_create(cycle->connection_n / 2);

其他不重要,就連 epoll_ctl 和 epoll_wait 也不重要了,這里你需要知道的就是,從調(diào)用鏈路來看,是 worker 創(chuàng)建的 epoll 對象,也就是每個(gè) worker 都有自己的 epoll 對象,而監(jiān)聽的sokcet 是一樣的!

【發(fā)現(xiàn)源碼】這里更加直接,搜索 epoll_create 肯定就能找到

問題的關(guān)鍵

此時(shí)問題的關(guān)鍵基本就能了解了,每個(gè) worker 都有處理能力,請求來了此時(shí)應(yīng)該喚醒誰呢?講道理那不是所有 epoll 都會有事件,所有 worker 都 accept 請求?顯然這樣是不行的。那么 nginx 是如何解決的呢?

如何解決

解決方式一共有三種,下面我們一個(gè)個(gè)來看:

  • accept_mutex(應(yīng)用層的解決方案)

  • EPOLLEXCLUSIVE(內(nèi)核層的解決方案)

  • SO_REUSEPORT(內(nèi)核層的解決方案)

accept_mutex

看到 mutex 可能你就知道了,鎖嘛!這也是對于高并發(fā)處理的 ”基操“ 遇事不決加鎖,沒錯(cuò),加鎖肯定能解決問題。

https://github.com/nginx/nginx/blob/b489ba83e9be446923facfe1a2fe392be3095d1f/src/event/ngx_event_accept.c#L328

具體代碼就不展示了,其中細(xì)節(jié)很多,但本質(zhì)很容易理解,就是當(dāng)請求來了,誰拿到了這個(gè)鎖,誰就去處理。沒拿到的就不管了。鎖的問題很直接,除了慢沒啥不好的,但至少很公平。

EPOLLEXCLUSIVE

EPOLLEXCLUSIVE 是 2016 年 4.5+ 內(nèi)核新添加的一個(gè) epoll 的標(biāo)識。它降低了多個(gè)進(jìn)程/線程通過 epoll_ctl 添加共享 fd 引發(fā)的驚群概率,使得一個(gè)事件發(fā)生時(shí),只喚醒一個(gè)正在 epoll_wait 阻塞等待喚醒的進(jìn)程(而不是全部喚醒)。

關(guān)鍵是:每次內(nèi)核只喚醒一個(gè)睡眠的進(jìn)程處理資源

但,這個(gè)方案不是完美的解決了,它僅是降低了概率哦。為什么這樣說呢?相比于原來全部喚醒,那肯定是好了不少,降低了沖突。但由于本質(zhì)來說 socket 是共享的,當(dāng)前進(jìn)程處理完成的時(shí)間不確定,在后面被喚醒的進(jìn)程可能會發(fā)現(xiàn)當(dāng)前的 socket 已經(jīng)被之前喚醒的進(jìn)程處理掉了。

SO_REUSEPORT

nginx 在 1.9.1 版本加入了這個(gè)功能

https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/

其本質(zhì)是利用了 Linux 的 reuseport 的特性,使用 reuseport 內(nèi)核允許多個(gè)進(jìn)程 listening socket 到同一個(gè)端口上,而從內(nèi)核層面做了負(fù)載均衡,每次喚醒其中一個(gè)進(jìn)程。

反應(yīng)到 nginx 上就是,每個(gè) worker 進(jìn)程都創(chuàng)建獨(dú)立的 listening socket,監(jiān)聽相同的端口,accept 時(shí)只有一個(gè)進(jìn)程會獲得連接。效果就和下圖所示一樣。

圖片

而使用方式則是:

http {
     server {
          listen 80 reuseport;
          server_name  localhost;
          # ...
     }
}

從官方的測試情況來看確實(shí)是厲害

圖片

當(dāng)然,正所謂:完事無絕對,技術(shù)無銀彈。這個(gè)方案的問題在于內(nèi)核是不知道你忙還是不忙的。只會無腦的丟給你。與之前的搶鎖對比,搶鎖的進(jìn)程一定是不忙的,現(xiàn)在手上的工作都已經(jīng)忙不過來了,沒機(jī)會去搶鎖了;而這個(gè)方案可能導(dǎo)致,如果當(dāng)前進(jìn)程忙不過來了,還是會只要根據(jù) reuseport 的負(fù)載規(guī)則輪到你了就會發(fā)送給你,所以會導(dǎo)致有的請求被前面慢的請求卡住了。

總結(jié)

本文,從了解什么 ”驚群效應(yīng)“ 到 nginx 架構(gòu)和 epoll 處理的原理,最終分析三種不同的處理 “驚群效應(yīng)” 的方案。分析到這里,我想你應(yīng)該明白其實(shí) nginx 這個(gè)多隊(duì)列服務(wù)模型是所存在的一些問題,只不過絕大多數(shù)場景已經(jīng)完完全全夠用了。

到此這篇關(guān)于淺談Nginx是如何解決驚群效應(yīng)的的文章就介紹到這了,更多相關(guān)Nginx 驚群效應(yīng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • Nginx生產(chǎn)環(huán)境平滑升級的實(shí)現(xiàn)

    Nginx生產(chǎn)環(huán)境平滑升級的實(shí)現(xiàn)

    本文主要介紹了Nginx生產(chǎn)環(huán)境平滑升級的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Linux配置Nginx服務(wù)器全過程

    Linux配置Nginx服務(wù)器全過程

    本文簡要介紹了Nginx服務(wù)器的安裝與配置,重點(diǎn)講解了基于域名的虛擬主機(jī)配置方式,包括新建目錄和配置文件、創(chuàng)建日志文件、測試Nginx服務(wù)器等步驟,并提供了詳細(xì)的配置方法和步驟說明
    2026-04-04
  • Nginx反向代理一個(gè)80端口下配置多個(gè)微信項(xiàng)目詳解

    Nginx反向代理一個(gè)80端口下配置多個(gè)微信項(xiàng)目詳解

    這篇文章主要介紹了Nginx反向代理一個(gè)80端口下配置多個(gè)微信項(xiàng)目詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • nginx實(shí)現(xiàn)動靜分離的方法示例

    nginx實(shí)現(xiàn)動靜分離的方法示例

    Nginx的靜態(tài)處理能力很強(qiáng),但是動態(tài)處理能力不足,因此,在企業(yè)中常用動靜分離技術(shù),本文就詳細(xì)的介紹一下如何使用,感興趣的可以了解一下
    2021-11-11
  • Nginx配置管理與Flask登錄日志查詢優(yōu)化實(shí)戰(zhàn)指南

    Nginx配置管理與Flask登錄日志查詢優(yōu)化實(shí)戰(zhàn)指南

    在 Web 開發(fā)和服務(wù)器運(yùn)維中,Nginx 的配置管理和后端 API 的數(shù)據(jù)查詢優(yōu)化是常見的需求,本文將通過兩個(gè)典型場景進(jìn)行詳細(xì)講解文章包含詳細(xì)的操作步驟、代碼示例和優(yōu)化建議,需要的朋友可以參考下
    2025-05-05
  • filebeat同時(shí)收集錯(cuò)誤日志與普通日志并存詳解

    filebeat同時(shí)收集錯(cuò)誤日志與普通日志并存詳解

    這篇文章主要為大家介紹了filebeat同時(shí)收集錯(cuò)誤日志與普通日志并存詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • nginx使用replace-filter-nginx-module實(shí)現(xiàn)內(nèi)容替換的示例

    nginx使用replace-filter-nginx-module實(shí)現(xiàn)內(nèi)容替換的示例

    本篇文章主要介紹了nginx使用replace-filter-nginx-module實(shí)現(xiàn)內(nèi)容替換的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • Nginx狀態(tài)監(jiān)控以及日志分析詳解

    Nginx狀態(tài)監(jiān)控以及日志分析詳解

    這篇文章主要給大家介紹了關(guān)于Nginx狀態(tài)監(jiān)控以及日志分析的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Nginx具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 一些可能是你極易忽略的Nginx知識點(diǎn)總結(jié)

    一些可能是你極易忽略的Nginx知識點(diǎn)總結(jié)

    無論是運(yùn)維、開發(fā)、測試,Nginx技術(shù)棧的學(xué)習(xí)是必不可少的,只是不同的崗位掌握的深度與廣度不同而已,這篇文章主要介紹了一些可能是你極易忽略的Nginx知識點(diǎn),需要的朋友可以參考下
    2026-06-06
  • 一文詳解nginx中的root與alias

    一文詳解nginx中的root與alias

    Nginx是一款流行的高性能Web服務(wù)器和反向代理服務(wù)器,這篇文章主要給大家介紹了關(guān)于如何通過一文詳解nginx中的root與alias的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11

最新評論

东莞市| 丰城市| 邢台县| 都匀市| 郸城县| 南安市| 清原| 杭州市| 抚松县| 利津县| 板桥市| 丰宁| 元朗区| 博湖县| 巴青县| 巴中市| 枣阳市| 米泉市| 二连浩特市| 慈利县| 宁德市| 乌拉特后旗| 康马县| 营山县| 巴彦淖尔市| 海门市| 吉木萨尔县| 镇原县| 神农架林区| 平遥县| 连江县| 和平区| 休宁县| 临夏市| 安阳县| 威远县| 台北市| 湖口县| 邛崃市| 文水县| 云安县|