欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談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ā)生,那么他就會(huì)喚醒等待的所有進(jìn)程(或者線程),但是最終卻只能有一個(gè)進(jìn)程(線程)獲得這個(gè)時(shí)間的“控制權(quán)”,對(duì)該事件進(jìn)行處理,而其他進(jìn)程(線程)獲取“控制權(quán)”失敗,只能重新進(jìn)入休眠狀態(tài),這種現(xiàn)象和性能浪費(fèi)就叫做驚群效應(yīng)。

簡單的講(我的大白話)

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

原因&問題

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

而問題就是,最終還是只能有一個(gè)進(jìn)程能來處理。當(dāng)請(qǐng)求多了,不停地喚醒、休眠、喚醒、休眠,做了很多的無用功,上下文切換又累,對(duì)吧。那怎么解決這個(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é)如:啟動(dòng)、讀取配置文件,監(jiān)聽處理各種信號(hào)等工作。

圖片

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

nginx 使用 epoll

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

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 對(duì)象,也就是每個(gè) worker 都有自己的 epoll 對(duì)象,而監(jiān)聽的sokcet 是一樣的!

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

問題的關(guān)鍵

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

如何解決

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

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

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

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

accept_mutex

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

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

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

EPOLLEXCLUSIVE

EPOLLEXCLUSIVE 是 2016 年 4.5+ 內(nèi)核新添加的一個(gè) epoll 的標(biāo)識(shí)。它降低了多個(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)程可能會(huì)發(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)程會(huì)獲得連接。效果就和下圖所示一樣。

圖片

而使用方式則是:

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

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

圖片

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

總結(jié)

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

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

您可能感興趣的文章:

相關(guān)文章

  • 配置ab來為Nginx服務(wù)器做壓力測(cè)試的方法

    配置ab來為Nginx服務(wù)器做壓力測(cè)試的方法

    這篇文章主要介紹了配置ab來為Nginx服務(wù)器做壓力測(cè)試的方法,ab是針對(duì)Apache的測(cè)試工具但本文講解其測(cè)試Nginx的過程,需要的朋友可以參考下
    2016-01-01
  • Nginx服務(wù)器下配置個(gè)性二級(jí)域名及多個(gè)域名的實(shí)例講解

    Nginx服務(wù)器下配置個(gè)性二級(jí)域名及多個(gè)域名的實(shí)例講解

    這篇文章主要介紹了Nginx服務(wù)器下配置個(gè)性二級(jí)域名及多個(gè)域名的實(shí)例講解,注意一下rewrite的寫法規(guī)則,需要的朋友可以參考下
    2016-01-01
  • Nginx?Proxy?Manager配置Web?WAF應(yīng)用防火墻

    Nginx?Proxy?Manager配置Web?WAF應(yīng)用防火墻

    Nginx?Proxy?Manager是一款功能強(qiáng)大的開源軟件,配置Web應(yīng)用防火墻,可以防止常見的web攻擊,本文就來介紹一下Nginx?Proxy?Manager配置Web?WAF應(yīng)用防火墻,感興趣的可以了解一下
    2025-02-02
  • 阿里云ssl證書如何通過Nginx部署到服務(wù)器

    阿里云ssl證書如何通過Nginx部署到服務(wù)器

    這篇文章主要介紹了阿里云ssl證書通過Nginx部署到服務(wù)器的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 如何配置Nginx每個(gè)進(jìn)程最多打開的文件數(shù)量

    如何配置Nginx每個(gè)進(jìn)程最多打開的文件數(shù)量

    這篇文章主要介紹了配置Nginx每個(gè)進(jìn)程最多打開的文件數(shù)量,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • nginx日志導(dǎo)入elasticsearch的方法示例

    nginx日志導(dǎo)入elasticsearch的方法示例

    這篇文章主要介紹了nginx日志導(dǎo)入elasticsearch的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Nginx配置-日志格式配置方式

    Nginx配置-日志格式配置方式

    這篇文章主要介紹了Nginx配置-日志格式配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Nginx與Tomcat之間的關(guān)系及說明

    Nginx與Tomcat之間的關(guān)系及說明

    Nginx和Tomcat在現(xiàn)代Web應(yīng)用架構(gòu)中扮演重要角色,Nginx主要負(fù)責(zé)處理HTTP請(qǐng)求、反向代理、負(fù)載均衡、SSL加密和靜態(tài)資源服務(wù),而Tomcat則專注于處理動(dòng)態(tài)請(qǐng)求和運(yùn)行JavaWeb應(yīng)用,它們通過反向代理和負(fù)載均衡機(jī)制緊密合作,優(yōu)化系統(tǒng)性能和擴(kuò)展性,適用于高并發(fā)和大流量場(chǎng)景
    2025-02-02
  • Nginx的偽靜態(tài)配置中使用rewrite來實(shí)現(xiàn)自動(dòng)補(bǔ)全的實(shí)例

    Nginx的偽靜態(tài)配置中使用rewrite來實(shí)現(xiàn)自動(dòng)補(bǔ)全的實(shí)例

    這篇文章主要介紹了Nginx的偽靜態(tài)配置中使用rewrite來實(shí)現(xiàn)自動(dòng)補(bǔ)全的實(shí)例,文中對(duì)rewrite的相關(guān)參數(shù)和正則表達(dá)使用也做了介紹,需要的朋友可以參考下
    2015-12-12
  • Nexus使用nginx代理實(shí)現(xiàn)支持HTTPS協(xié)議

    Nexus使用nginx代理實(shí)現(xiàn)支持HTTPS協(xié)議

    這篇文章主要介紹了Nexus使用nginx代理實(shí)現(xiàn)支持HTTPS協(xié)議,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05

最新評(píng)論