accept_mutex与性能的关系 (nginx)
- nginx的 1(master)+N(worker) 多进程模型:master在启动过程中负责读取nginx.conf中配置的监听端口,然后加入到一个cycle->listening数组中。
- init_cycle函数中会调用init_module函数,init_module函数会调用所有注册模块的module_init函数完成相关模块所需资源的申请以及其他一些工作;其中event模块的module_init函数申请一块共享内存用于存储accept_mutex锁信息以及连接数信息
//////////// nginx/src/event/ngx_event.c /////// shm.size = size;
 shm.name.len = sizeof("nginx_shared_zone") - 1;
 shm.name.data = (u_char *) "nginx_shared_zone";
 shm.log = cycle->log; if (ngx_shm_alloc(&shm) != NGX_OK) {
 return NGX_ERROR;
 } shared = shm.addr; ngx_accept_mutex_ptr = (ngx_atomic_t *) shared;
 ngx_accept_mutex.spin = (ngx_uint_t) -1; if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) shared,
 cycle->lock_file.data)
 != NGX_OK)
 {
 return NGX_ERROR;
 }
////////////   nginx/src/event/ngx_event.c   ///////
    /* for each listening socket */
    ls = cycle->listening.elts;
    for (i = 0; i < cycle->listening.nelts; i++) {
#if (NGX_HAVE_REUSEPORT)
        if (ls[i].reuseport && ls[i].worker != ngx_worker) {
            continue;
        }
#endif
        c = ngx_get_connection(ls[i].fd, cycle->log);
        if (c == NULL) {
            return NGX_ERROR;
        }
        c->type = ls[i].type;
        c->log = &ls[i].log;
        c->listening = &ls[i];
        ls[i].connection = c;
        rev = c->read;
        rev->log = c->log;
        rev->accept = 1;
        ...............
////////////   nginx/src/event/ngx_event.c   ///////
     if (ngx_use_accept_mutex) {
        if (ngx_accept_disabled > 0) {
            ngx_accept_disabled--;
        } else {
            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
                return;
            }
            if (ngx_accept_mutex_held) {
                flags |= NGX_POST_EVENTS;          //增加NGX_POST_EVENTS标识
            } else {
                if (timer == NGX_TIMER_INFINITE
                    || timer > ngx_accept_mutex_delay)
                {
                    timer = ngx_accept_mutex_delay;
                }
            }
        }
    }
////////////////////////
ngx_int_t
ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
{
    if (ngx_shmtx_trylock(&ngx_accept_mutex)) {
        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "accept mutex locked");
        if (ngx_accept_mutex_held && ngx_accept_events == 0) {
            return NGX_OK;
        }
        if (ngx_enable_accept_events(cycle) == NGX_ERROR) {     //将cycle->listening加入到当前worker进程的epoll
            ngx_shmtx_unlock(&ngx_accept_mutex);
            return NGX_ERROR;
        }
        ngx_accept_events = 0;
        ngx_accept_mutex_held = 1;
        return NGX_OK;
    }
    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "accept mutex lock failed: %ui", ngx_accept_mutex_held);
    if (ngx_accept_mutex_held) {
        if (ngx_disable_accept_events(cycle, 0) == NGX_ERROR) {     //将cycle->listening从当前worker进程的epoll移除
            return NGX_ERROR;
        }
        ngx_accept_mutex_held = 0;
    }
    return NGX_OK;
}
/////////////////  nginx/src/event/modules/ngx_epoll_module.c  //////////
    if (flags & NGX_POST_EVENTS) {
                queue = rev->accept ? &ngx_posted_accept_events
                                    : &ngx_posted_events;
                ngx_post_event(rev, queue);
            } else {
                rev->handler(rev);
            }
////////////    nginx/src/event/ngx_event.c ///////////
    (void) ngx_process_events(cycle, timer, flags);
    delta = ngx_current_msec - delta;
    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "timer delta: %M", delta);
    ngx_event_process_posted(cycle, &ngx_posted_accept_events);
    if (ngx_accept_mutex_held) {
        ngx_shmtx_unlock(&ngx_accept_mutex);
    }
    if (delta) {
        ngx_event_expire_timers();
    }
    ngx_event_process_posted(cycle, &ngx_posted_events);
- 上述分析的主要是accept_mutex打开的情况。对于不打开的情况,比较简单,所有worker的epoll都会监听listening数组中的所有fd,所以一旦有新连接过来,就会出现worker“抢夺资源“的情况。对于分布式的大量短链接来讲,打开accept_mutex选项较好,避免了worker争夺资源造成的上下文切换以及try_lock的锁开销。但是对于传输大量数据的tcp长链接来讲,打开accept_mutex就会导致压力集中在某几个worker上,特别是将worker_connection值设置过大的时候,影响更加明显。因此对于accept_mutex开关的使用,根据实际情况考虑,不可一概而论。
- 根据分析我们的压测程序,发现是采用的长tcp连接的方式,然后调用http请求;而且worker_connection也比较大,这样就出现了accept_mutex打开worker负载不均造成QPS下降的问题。
- 目前新版的Linux内核中增加了EPOLLEXCLUSIVE选项,nginx从1.11.3版本之后也增加了对NGX_EXCLUSIVE_EVENT选项的支持,这样就可以避免多worker的epoll出现的惊群效应,从此之后accept_mutex从默认的on变成了默认off。
accept_mutex与性能的关系 (nginx)的更多相关文章
- paip.提升性能---mysql 优化cpu多核以及lan性能的关系.
		paip.提升性能---mysql 优化cpu多核以及lan性能的关系. 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:/ ... 
- 浅析I/O处理过程与存储性能的关系
		浅析I/O处理过程与存储性能的关系 https://community.emc.com/docs/DOC-28653 性能”这个词可以说伴随着整个IT行业的发展,每次新的技术出现,从硬件到软件大多数情 ... 
- 高性能web服务器(热死你)Resin Linux的安装、配置、部署,性能远超Nginx支持Java、PHP等
		高性能web服务器(热死你)Resin Linux的安装.配置.部署,性能远超Nginx支持Java.PHP等 一. 安装resin 1. 下载resin: 下载地址:http://cauch ... 
- API网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd  API 网关出现的原因
		API网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd http://www.infoq.com/cn/articles/compa ... 
- NGINX比Apache的性能高是因为NGINX由C语言开发,而Apache由C++开发
		事实上,NGINX比Apache的性能高是因为NGINX由C语言开发,而Apache由C++开发.因此,NGINX效率大概是Apache的10倍左右 
- web性能优化——代理(nginx)
		简介 一个很好的原则是调优时每次只个性一个配置.如果对配置的个性不能提高性能的话,改回默认值 优化必须要通过性能测试.不能意淫,需要前后对比,真实说明问题. 场景 优化nginx. 确保每次请求控制一 ... 
- API Gateway性能比较:NGINX vs. ZUUL vs.Cloud Gateway vs. Linkerd[译]
		2018-03-04 15:07 联发科的反思 前几天拜读了 OpsGenie 公司(一家致力于 Dev & Ops 的公司)的资深工程师 Turgay elik 博士写的一篇文章(链接在 ... 
- API网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd(转)
		前几天拜读了 OpsGenie 公司(一家致力于 Dev & Ops 的公司)的资深工程师 Turgay Çelik 博士写的一篇文章(链接在文末),文中介绍了他们最初也是采用 Nginx 作 ... 
- HTTP/2 服务器推送(Server Push)教程(HTTP/2 协议的主要目的是提高网页性能,配置Nginx和Apache)
		HTTP/2 协议的主要目的是提高网页性能. 头信息(header)原来是直接传输文本,现在是压缩后传输.原来是同一个 TCP 连接里面,上一个回应(response)发送完了,服务器才能发送下一个, ... 
随机推荐
- C# 文章导航
			1. C#相关文章 1.1 C# 基础(一) 访问修饰符.ref与out.标志枚举等等 1.2 C# 基础(二) 类与接口 1.3 C# DateTime日期格式化 1.4 C# DateTime与时 ... 
- Windows 7上执行Cake 报错原因是Powershell 版本问题
			在Windows 7 SP1 电脑上执行Cake的的例子 http://cakebuild.net/docs/tutorials/getting-started ,运行./Build.ps1 报下面的 ... 
- ADO.NET对象的详解
			1. Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接数据库所需要的其它参数.Connection对象会被Command对象使用,这样就能 ... 
- 06.SQLServer性能优化之---数据库级日记监控
			汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 之前说了一下数据库怎么发邮件:http://www.cnblogs.com/duniti ... 
- Android业务组件化之现状分析与探讨
			前言: 从个人经历来说的话,从事APP开发这么多年来,所接触的APP的体积变得越来越大,业务的也变得越来越复杂,总来来说只有一句话:这是一个APP臃肿的时代!所以为了告别APP臃肿的时代,让我们进入一 ... 
- 浅谈JSP中include指令与include动作标识的区别
			JSP中主要包含三大指令,分别是page,include,taglib.本篇主要提及include指令. include指令使用格式:<%@ include file="文件的绝对路径 ... 
- JAVA回调机制解析
			一.回调机制概述 回调机制在JAVA代码中一直遇到,但之前不懂其原理,几乎都是绕着走.俗话说做不愿意做的事情叫做突破,故诞生了该文章,算是新年的新气象,新突破! 回调机制是什么?其实回 ... 
- PHP static静态属性和静态方法
			这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么样调用),需要弄明白了他们在内存中存放位置,这样就非常容易理解了.静态属性.方法(包括静态与非静态)在内 ... 
- jquery实现下拉框多选
			一.说明 本文是利用EasyUI实现下拉框多选功能,在ComboxTree其原有的基础上对样式进行了改进,样式表已上传demo,代码如下 二.代码 <!DOCTYPE html PUBLIC & ... 
- mysql开启慢查询日志及查询--windows
			MySQL慢查询配置 1. 慢查询有什么用? 它能记录下所有执行超过long_query_time时间的SQL语句, 帮你找到执行慢的SQL, 方便我们对这些SQL进行优化. 2. 如何开启慢查询? ... 
