nginx 为什么这么快
nginx 架构1介绍及常见的问题
nginx 架构2
nginx 架构3
上面三篇讲的都可以。
问题
- 为什么不采用多线程模型管理连接?
无状态服务,无需共享进程内存
采用独立的进程,可以让互相之间不会影响。一个进程异常崩溃,其他进程的服务不会中断,提升了架构的可靠性。
进程之间不共享资源,不需要加锁,所以省掉了锁带来的开销。
- 为什么不采用多线程处理逻辑业务?
进程数已经等于核心数,再新建线程处理任务,只会抢占现有进程,增加切换代价。
作为接入层,基本上都是数据转发业务,网络IO任务的等待耗时部分,已经被处理为非阻塞/全异步/事件驱动模式,在没有更多CPU的情况下,再利用多线程处理,意义不大。并且如果进程中有阻塞的处理逻辑,应该由各个业务进行解决,比如openResty中利用了Lua协程,对阻塞业务进行了优化。
- 惊群是什么? nginx是如何处理的?
由于worker都是由master进程fork产生,所以worker都会监听相同端口。这样多个子进程在accept建立连接时会发生争抢,带来著名的“惊群”问题。
解决方法:
1)将连接事件与读写事件进行分离。连接事件存放为ngx_posted_accept_events,读写事件存放为ngx_posted_events。
2)设置ngx_accept_mutex锁,只有获得锁的进程,才可以处理连接事件。
配置文件中开启或者关闭
events {
accept_mutex off;
}
为什么关闭?
OS may wake all processes waiting on accept() and select(), this is called thundering herd problem.
This is a problem if you have a lot of workers as in Apache (hundreds and more), but this insensible
if you have just several workers as nginx usually has. Therefore turning accept_mutex off is as
scheduling incoming connection by OS via select/kqueue/epoll/etc (but not accept()).
简单点说:Apache动辄就会启动成百上千的进程,如果发生惊群问题的话,影响相对较大;但是对Nginx而言,一般来说,worker_processes会设置成CPU个数,所以最多也就几十个,即便发生惊群问题的话,影响相对也较小。
另:高版本的Linux中,accept不存在惊群问题,不过epoll_wait等操作还有。
- 负载均衡什么时候触发?
Worker间的负载关键在于各自接入了多少连接,其中接入连接抢锁的前置条件是ngx_accept_disabled > 0,所以ngx_accept_disabled就是负载均衡机制实现的关键阈值。
ngx_int_t ngx_accept_disabled;
ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n;
connection_n
: 为nginx配置文件中最大连接数free_connection_n
: 未连接数
因此,在nginx启动时,ngx_accept_disabled
的值就是一个负数,其值为连接总数的7/8。当该进程的连接数达到总连接数的7/8时,该进程就不会再处理新的连接了。
同时每次调用ngx_process_events_and_timers
时,将ngx_accept_disabled
减1,直到其值低于阈值时,才试图重新处理新的连接。
因此,nginx各worker子进程间的负载均衡仅在某个worker进程处理的连接数达到它最大处理总数的7/8时才会触发,其负载均衡并不是在任意条件都满足
还没有评论,来说两句吧...