Nginx下惊群现象的处理
来源:互联网 发布:正版凯立德导航软件 编辑:程序博客网 时间:2024/06/05 16:20
Nginx(“engine x”)是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。它可以托管网站,进行Http服务处理,也可以作为反向代理服务器使用。
1.Nginx的优点:
1.处理静态文件,索引文件以及自动索引;打开文件描述符缓冲。2.无缓存的反向代理加速,简单的负载均衡和容错。
Nginx具有很高的稳定性。其他HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。Nginx官方表示保持10000个没有活动的链接,只占2.5M内存。
Nginx支持热部署。启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还可以在不间断服务的情况下,对软件版本进行升级。
Nginx采用master-slave模型,能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。
2.Nginx负载均衡
负载均衡是为了解决有可能一个进程处理了多个连接,因此就需要让多进程更平均的处理连接。
Nginx的upstream目前支持4种方式的分配
1) 轮询(默认)
每个请求按时间顺序逐一分配到不同的后端,如果后端服务器down掉,能自动剔除。
2) weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3) ip_hash
每个请求按访问ip的hash结果分配,如果每个访客固定访问一个后端服务器,可以解决session的问题。
4) fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5) url_hash(第三方)
按访问url的hash结果来分配请求,是每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
3.Nginx中惊群的处理
惊群现象:如果多个工作进程同时拥有多个监听套接口,那么一但该套接口出现客户端请求,此时就将引发所有拥有该套接口的工作进程去争抢这个请求(accept),能争抢到的肯定只有某一个工作进程,而其他工作进程注定要无功而返,这种现象称为“惊群”。
在看代码之前,先来看ngx_use_accept_mutex这个变量,如果有个变量,说明nginx有必要使用accept互斥体,这个变量的初始化在ngx_event_process_init中。
这里还有两个变量,一个是ngx_accept_mutex_held,一个是ngx_accept_mutex_delay,其中前一个表示当前是否以及持有锁,后一个表示,当获得锁失败后,再次去请求锁的间隔时间,这个时间可以看到,在配置文件中设置的。
//如果使用了master worker,并且worker个数大于1,并且配置文件里面有设置使用accept_mutex的话,设置ngx_use_accept_mutexif(ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex){ ngx_use_accept_mutex = 1; ngx_accept_mutex_held = 0; ngx_accept_mutex_delay = ecf->accept_mutex_delay; }else{ ngx_use_accept_mutex = 0; }
这里还有一个变量是ngx_accept_disabled,这个变量是一个阈值,如果大于0,说明当前的进程处理的连接过大。
下面是这个值的初始化,可以看到初始值是全部连接的7/8(注意是负值0)
ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n;
然后来看ngx_process_events_and_timers中的处理。
//如果有使用mutex,则才会进行处理。if (ngx_use_accept_mutex) {//如果大于0,则跳过下面的锁的处理,并减一。 if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else {//试着获得锁,如果出错则返回。 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return; }//如果ngx_accept_mutex_held为1,则说明已经获得锁,此时设置flag,这个flag后面会解释。 if (ngx_accept_mutex_held) { flags |= NGX_POST_EVENTS; } else {//否则,设置timer,也就是定时器。接下来会解释这段。 if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) { timer = ngx_accept_mutex_delay; } } }}
然后先来看NGX_POST_EVENTS标记,设置了这个标记就说明当socket有数据被唤醒时,我们并不会马上accept或者说读取,而是将这个事件保存起来,然后当我们释放锁之后,才会进行accept或者读取这个句柄。
//如果ngx_posted_accept_events不为NULL,则说明有accept event需要nginx处理。if (ngx_posted_accept_events) { ngx_event_process_posted(cycle, &ngx_posted_accept_events); }
而如果没有设置NGX_POST_EVENTS 标记的话,nginx会立即accept或者读取句柄。
然后是定时器,这里如果nginx没有获得锁,并不会马上再去获得锁,而是设置定时器,然后再epoll休眠(如果没有其他的东西唤醒)。此时如果有链接到达,当前休眠进程会被提前唤醒,然后立即accept。否则,休眠ngx_accept_mutex_delay时间,然后继续try lock.
最后是个核心函数,那就是ngx_trylock_accept_mutex.这个函数尝试获得accept mutex.
ngx_int_tngx_trylock_accept_mutex(ngx_cycle_t *cycle){//尝试获得锁 if (ngx_shmtx_trylock(&ngx_accept_mutex)) { //如果本来已经获得锁,则直接返回Ok if (ngx_accept_mutex_held && ngx_accept_events == 0 && !(ngx_event_flags & NGX_USE_RTSIG_EVENT)) { return NGX_OK; } //到达这里,说明重新获得锁成功,因此需要打开被关闭的listening句柄。 if (ngx_enable_accept_events(cycle) == NGX_ERROR) { ngx_shmtx_unlock(&ngx_accept_mutex); return NGX_ERROR; } ngx_accept_events = 0; //设置获得锁的标记。 ngx_accept_mutex_held = 1; return NGX_OK; }//如果我们前面已经获得了锁,然后这次获得锁失败,则说明当前的listen句柄已经被其他的进程锁监听,因此此时需要从 if (ngx_accept_mutex_held) { if (ngx_disable_accept_events(cycle) == NGX_ERROR) { return NGX_ERROR; } //设置锁的持有为0. ngx_accept_mutex_held = 0; } return NGX_OK;}
这里可以看到大部分情况下,每次只会有一个进程在监听listen句柄,而只有当ngx_accept_disabled大于0的情况下,才会出现一定程度的惊群。
而nginx中,由于锁的控制(以及获得锁的定时器),每个进程都能相对公平的accept句柄,也就是比较好的解决了子进程负载均衡。
- Nginx下惊群现象的处理
- Nginx惊群现象的处理
- 网页恶意代码的现象及处理方法
- nginx 惊群现象
- nginx惊群现象
- nginx的超时处理
- Nginx的超时处理
- nginx的超时处理
- Nginx的超时处理
- nginx的请求处理
- nginx的事件处理
- nginx的请求处理
- 关于myeclipse关联源文件没有反应的的现象处理
- crash现象的原因及避免与处理的方法
- Nginx如何解决“惊群”现象
- Nginx如何解决“惊群”现象
- Nginx解决惊群现象
- 上网遇到恶意网页时的现象及处理办法
- volatile的个人简单见解
- 67. Add Binary
- TCP协议详解
- android 5.0 Camera 之 ZSL说明
- Servlet
- Nginx下惊群现象的处理
- keras
- String、StringBuffer与StringBuilder之间区别
- i.MX6 Yocto工程简介与分析
- B树
- 一般人不告诉的精通linux系统秘籍
- Android自定义View——自定义ViewPager
- java语言程序设计第十章课后题Triangle2D
- 集合最大元问题(递归与分治)——算法设计与分析