标签:
前面分析了Nginx的基本数据结构,现在看一下功能模块。
Nginx将各功能模块组成一条链,当有请求到达时,请求依次进过这条链上的部分或全部模块进行处理。
Nginx使用一个多进程模型来提供服务,一个master进程和多个worker进程。类似的原理可以参见分布式进程。框架如下:
master分管多个work进程。每个worker执行死循环接收来自客户端的请求。死循环由ngx_worker_process_cycle
实现。一个请求的简单处理流程如下:
static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
ngx_int_t worker = (intptr_t) data;
ngx_uint_t i;
ngx_connection_t *c;
ngx_process = NGX_PROCESS_WORKER;
ngx_worker = worker;
//设定n个worker进程
ngx_worker_process_init(cycle, worker);
ngx_setproctitle("worker process");
for ( ;; ) {
//如果进程退出,关闭所有连接
if (ngx_exiting) {
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
if (c[i].fd != -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
//定时器归0
ngx_event_cancel_timers();
//判断timer的红黑树是否为空
if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel) {
ngx_worker_process_exit(cycle);
}
}
ngx_process_events_and_timers(cycle);
//处理中断信号
if (ngx_terminate) {
ngx_worker_process_exit(cycle);
}
//处理退出信号
if (ngx_quit) {
ngx_quit = 0;
ngx_setproctitle("worker process is shutting down");
if (!ngx_exiting) {
ngx_close_listening_sockets(cycle);
ngx_exiting = 1;
}
}
//处理重启log
if (ngx_reopen) {
ngx_reopen = 0;
ngx_reopen_files(cycle, -1);
}
}
}
其中几个关键函数是
ngx_worker_process_init
处理子进程初始化
ngx_process_events_and_timers(cycle)
ngx_worker_process_exit(cycle)
子进程退出
下面来看一下子进程的初始化操作:
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_process) {
if (ngx_modules[i]->init_process(cycle) == NGX_ERROR{ exit(2);
}
}
}
里面关键的函数是init_process
。
for (n = 0; n < ngx_last_process; n++) {
if (ngx_processes[n].pid == -1) {
continue;
}
//跳过当前worker
if (n == ngx_process_slot) {
continue;
}
if (ngx_processes[n].channel[1] == -1) {
continue;
}
//关闭其它workers channel[1]
if (close(ngx_processes[n].channel[1]) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"close() channel failed");
}
}
//关闭当前worker channel[0]
if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"close() channel failed");
}
if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,ngx_channel_handler) == NGX_ERROR)
{
exit(2);
}
ngx_add_channel_event
把句柄ngx_channel
(当前worker的channel[1])上建立的连接的可读事件加入事件监控队列,事件处理函数为ngx_channel_hanlder
。当有可读事件的时候,ngx_channel_handler
负责处理消息,具体代码可以查看src/os/unix/ngx_process_cycle.c
,过程如下:
static void
ngx_channel_handler(ngx_event_t *ev)
{
//...
for ( ;; ) {
//从channe[1]读取消息
n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
//处理消息命令
switch (ch.command) {
case NGX_CMD_QUIT:
ngx_quit = 1;
break;
case NGX_CMD_TERMINATE:
ngx_terminate = 1;
break;
case NGX_CMD_REOPEN:
ngx_reopen = 1;
break;
case NGX_CMD_OPEN_CHANNEL:
ngx_processes[ch.slot].pid = ch.pid;
ngx_processes[ch.slot].channel[0] = ch.fd;
break;
case NGX_CMD_CLOSE_CHANNEL:
if (close(ngx_processes[ch.slot].channel[0]) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"close() channel failed");
}
ngx_processes[ch.slot].channel[0] = -1;
break;
}
}
}
http://blog.csdn.net/lengzijian/article/details/7591025
标签:
原文地址:http://my.oschina.net/lvyi/blog/423286