nginx
采用多进程模型,含一个master
进程和多个worker
进程,worker进程数目可配置,一般与机器CPU核心数目一致,master进程主要职责是:接收外界信号,如star,stop,restart,监控worker进程状态。worker进程主要职责:负责处理客户端请求。
这种进程模型的好处:
nginx利用多进程+非阻塞
的模型,能轻松处理上万连接。其处理请求的大致过程为:
惊群现象
)处理三种常见事件:信号、定时器、网络IO,其中信号有专门的handler来处理,定时器事件和网络IO在主循环中处理。
用一段伪代码来总结Nginx的事件处理机制:
while (true) {
for t in run_tasks:
t.handler();
update_time(&now);
timeout = ETERNITY;
for t in wait_tasks: /* sorted already 处理定时器事件*/
if (t.time <= now) {
t.timeout_handler();
} else {
timeout = t.time - now;
break;
}
nevents = poll_function(events, timeout);/*处理网络IO事件*/
for i in nevents:
task t;
if (events[i].type == READ) {
t.handler = read_handler;
} else { /* events[i].type == WRITE */
t.handler = write_handler;
}
run_tasks_add(t);
}
master进程会事先创建好监听套接字,然后fork worker子进程时,会继承监听套接字,当listen socket可读时,所有进程都将被唤醒,都会去accept这个请求,最终只有一个进程会成功,其他则失败,这就是惊群现象
nginx解决方法:提供一个ngx_accept_mutex
,worker进程尝试accept之前会去获取该mutex,获取成功的采取accept连接。
nginx的进程通信分为三种类别:linux 系统与nginx 通信, master 进程与worker进程通信, worker进程间通信。
memcached是一款服务器缓存软件,基于libvent
开发,使用的多线程模型,主线程listen\accept,工作线程处理消息。
主要流程是:
Redis采用单线程模型
,通过IO多路复用
来监听多个连接,非阻塞IO,同时单线程避免了不必要的锁的开销。
Redis同时处理文件事件和时间事件
文件事件,Redis将产生事件套接字放入一个队列
中,然后依次分派给文件事件处理器;Redis编写了多个文件事件处理器,如
networking.c/acceptTcpHandler
;networking.c/readQueryFromClinet
;networking.c/sendReplyToClient
;时间事件包含定时事件
和周期性事件
,Redis将其放入一个无序链表
中,每当时间事件执行器运行时,就遍历链表,查找已经到达的时间事件,调用相应的处理器。
Redis中一个重要的时间事件是serverCron
,Redis利用该函数来定期对自身的资源和状态进行检查和调整,时间周期可以参考redis.conf
关于hz选项说明,其主要工作包含:
Redis主函数
关于事件处理的代码表示如下:
def main():
#一直循环处理事件
while(not_stop){
aeProcessEvents()
}
下面展示aeProcessEvents
调度文件事件和时间事件的过程:
def aeProcessEvents():
time_event = aeSearchNearestTimer() #获取当前时间最近的时间事件
remaind_ms = time_event.when - unix_ts_now() #获取最近的时间事件达到的毫秒时间
if remaind_ms < 0 : #时间为负数,赋值0
remaind_ms = 0
timeval = create_timeval_with_ms(remainds_ms) #创建等待的时间结构
aeApiPoll(timeval) #等待文件事件产生,时间取决于remainds_ms
processFileEvent() #处理文件事件
processTimeEvent() #处理时间事件
原文:
http://panzhengguang.github.io/2016/06/15/nginx_memcached_server_model/