虽然代码理解起来比较混乱,但是使用还是比较简单的,常用的有创建 hash 和在 hash 中进行查找两个操作,对于创建hash的操作,过程一般为: 查找的过程很简单 需要注意的是,nginx 的 hash 在查找时使用的是分桶后线性查找法,因此当分桶数确定时查找效率同其中的总 key-val 对数量成反比。 下面是一些demo代码(可以从svn中找到) 运行结果 ngx_list 的结构并不复杂,ngx为我们封装了ngx_list_create, ngx_list_init, 和 ngx_list_push等(建立,初始化,添加)操作, 但是对于我们来说最常用的是遍历操作, 下面是nginx的注释里面提到的遍历的例子 在开始这个task的学习的时候,经过搜索发现了langwan同学之前对nginx的源代码研究资料,很有参考意义,所以大量节省了我们的工作,我觉得对于本章的进行比较有用的是,下面这几个文章 为了方便研究,将nginx的debug 信息打开,重新编译 然后修改nginx.conf 打开debug信息的支持,并使用2个worker进程,通过查看 log 信息来了解 nginx 运行的情况 基于上面的配置信息,结合一个简单的http访问操作,我这里记录了一个 log日志的例子 其中一个比较重要的函数调用是, ngx_init_cycle, 这个是使用kscope输出的他的调用关系,他被main, ngx_master_process_cycle,ngx_single_process_cycle 调用, 其中后两者是在reconfigure的时候被调用的 他主要做了如下几件事情: 另外,ngx_master/single_process_cycle 里面会对init_process进行调用, 并且循环调用 ngx_process_events_and_timers , 其中里面会调用ngx_process_events(cycle, timer, flags); 对事件循环进行polliing 时间一般默认为 500 ms HTTP相关的Module都在 src/http 目录和其子目录下, 其中 src/http 下的文件为http模块的核心文件, src/http/modules 下的文件为http模块的扩展模块。 其中: ngx_http.c 中,注册了 http 这个指令的处理模块,对应ngx_http_block函数 这个函数里面会进行一些conf资源分配/Merge,配置文件解析等工作。 这里面有个一比较重要的工作是注册了nginx http 的 phase handler phase handler的类型在 ngx_http_core_module 这里定义: 每一个phase的handlers 都是一个数组,里面可以包含多个元素,通过 ngx_array_push 添加新的handler 其中每个phase的处理大都包含了对ngx_request_t 的 write 或者 read event的改写,其中 在 ngx_http_core_content_phase 里面, 有对location handler的调用, 其中的 r->content_handler 就是运行时刻从location handler中注册的, 其中, 在各个phase的结束阶段,一般都是调用 移动request 中 phase_handler的指针,并且示意主程序继续进行。 这里,无论是phase handler,还是 location handler,我们都是可以在程序里进行注册的。 另外, ngx_http_block 里面调用了 ngx_http_optimize_servers ,这个函数对listening和connection相关的变量进行了初始化和调优,并最终在 ngx_http_add_listening (被ngx_http_add_listening调用) 中注册了listening 的 handler 为 ngx_http_init_connection ngx_http_init_connection 在 ngx_http_request.c中定义,后续会进行详细的介绍 这里面,ngx_http_init_connection 注册了connection事件的读操作的回叫函数, 并将写操作设置为空函数 当新的连接进入的时候,就执行到 ngx_http_init_request, 开始对后面的流程进行处理,主要是将rev的handler 设置为ngx_http_process_request_line , 然后ngx_http_process_request_line 会先后有调度到 ngx_http_process_request_headers 和 ngx_http_process_request 函数对读取过来的event进行处理,其中, ngx_http_process_request_headers 里面会对http的请求头进行解析,ngx_http_process_request 设置event handler 到ngx_http_request_handler ,ngx_http_request_handler 中会根据事件可能是读取还是写入的操作分别调用 request 的 read_event_handler 和 write_event_handler ,所以后续程序对 request 的 read/writeevent_handler 调整 本质上类似对 rev 和 wev的handler的调整,只是回叫函数的参数变更为了 ngx_request_t 而不是之前的ngx_event_t 根据上面代码可以看出, 模块开始使用 ngx_http_block_reading 这个handler对后续的读请求进行处理 在注册完事件后, ngx_http_process_request 会分别调用下面的两个函数 其中, ngx_http_handler 在ngx_http_core_module中定义,处理程序的主请求, ngx_http_run_posted_requests 在ngx_http_request.c 里定义,处理所有提交的子请求数据的输出。 对于 ngx_http_core_module 是http 模块中比较重要的模块, 他本身是一个 NGX_HTTP_MODULE (不同于ngx_http_module, ngx_http_module本质上是一个 NGX_CORE_MODULE 这里面对http block下面的一些指令进行了处理, 比如 server, location 等, 同时, 上面提到的 ngx_http_handler 也在这里面 ngx_http_handler 所作的最核心的工作就是在最后调用 并将 write event 设置为 ngx_http_core_run_phases, 开始依次处理各个阶段的 handler 当handler处理完成后,http的处理流程也就基本上完成了.. run_phases 的过程实际上非常简单, 一次的运行每一个handler, 当任意一个handler返回ok或者所有handler执行完成后,整个流程结束。 这里需要注意的是, ph的下标变化是根据 r->phase_handler 变量决定的, 所以在每个handler内部,如果想要让主程序继续处理下一个 handler,需要手动的 r->phase_handler++ ,将phase handler数组的下标转移到下一个成员。
#include <stdio.h>
#include "ngx_config.h"
#include "ngx_conf_file.h"
#include "nginx.h"
#include "ngx_core.h"
#include "ngx_string.h"
#include "ngx_palloc.h"
#include "ngx_array.h"
#include "ngx_hash.h"
volatile ngx_cycle_t *ngx_cycle;
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...) { }
static ngx_str_t names[] = {ngx_string("rainx"),
ngx_string("xiaozhe"),
ngx_string("zhoujian")};
static char* descs[] = {"rainx's id is 1","xiaozhe's id is 2","zhoujian's id is 3"};
// hash table的一些基本操作
int main()
{
ngx_uint_t k; //, p, h;
ngx_pool_t* pool;
ngx_hash_init_t hash_init;
ngx_hash_t* hash;
ngx_array_t* elements;
ngx_hash_key_t* arr_node;
char* find;
int i;
ngx_cacheline_size = 32;
// hash key cal start
ngx_str_t str = ngx_string("hello, world");
k = ngx_hash_key_lc( str.data, str.len);
pool = ngx_create_pool(1024*10, NULL);
printf("caculated key is %u \n", k);
// hask key cal end
//
hash = (ngx_hash_t*) ngx_pcalloc(pool, sizeof(hash));
hash_init.hash = hash; // hash结构
hash_init.key = &ngx_hash_key_lc; // hash算法函数
hash_init.max_size = 1024*10; // max_size
hash_init.bucket_size = 64; // ngx_align(64, ngx_cacheline_size);
hash_init.name = "yahoo_guy_hash"; // 在log里会用到
hash_init.pool = pool; // 内存池
hash_init.temp_pool = NULL;
// 创建数组
elements = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t));
for(i = 0; i < 3; i++) {
arr_node = (ngx_hash_key_t*) ngx_array_push(elements);
arr_node->key = (names[i]);
arr_node->key_hash = ngx_hash_key_lc(arr_node->key.data, arr_node->key.len);
arr_node->value = (void*) descs[i];
//
printf("key: %s , key_hash: %u\n", arr_node->key.data, arr_node->key_hash);
}
if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) elements->elts, elements->nelts)!=NGX_OK){
return 1;
}
// 查找
k = ngx_hash_key_lc(names[0].data, names[0].len);
printf("%s key is %d\n", names[0].data, k);
find = (char*)
ngx_hash_find(hash, k, (u_char*) names[0].data, names[0].len);
if (find) {
printf("get desc of rainx: %s\n", (char*) find);
}
ngx_array_destroy(elements);
ngx_destroy_pool(pool);
return 0;
}
rainx@rainx-laptop:~/land/nginxsrp/src/demo/basic_types$ ./hash_op
caculated key is 3654358412
key: rainx , key_hash: 108275556
key: xiaozhe , key_hash: 2225329080
key: zhoujian , key_hash: 3269715264
rainx key is 108275556
get desc of rainx: rainx's id is 1
ngx_list
part = &list.part;
data = part->elts;
for (i = 0 ;; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
data = part->elts;
i = 0;
}
... data[i] ...
}
了解nginx的core module 的结构和运行机制
参考资料
Debug信息的输出
rainx@rainx-laptop:~/land/nginx-0.7.61$ ./configure --prefix=/home/rainx/land/test --with-debug
worker_processes 2;
error_log logs/error.log debug;
ngx_init_cycle
初始化cycle是基于旧有的cycle进行的,比如这里的 init_cycle,会继承old cycle的很多属性, 比如log等, 但是同时会对很多资源重新分配,比如pool, shared mem, file handler, listening socket 等,同时清除旧有的cycle的资源
了解nginx的http core module 的结构和运行机制
ngx_http.[c|h]
static ngx_command_t ngx_http_commands[] = {
{ ngx_string("http"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_http_block,
0,
0,
NULL },
ngx_null_command
};
if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
return NGX_CONF_ERROR;
}
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
if (r->content_handler) {
r->write_event_handler = ngx_http_request_empty_handler;
ngx_http_finalize_request(r, r->content_handler(r)); /*实际的请求发送处理*/
return NGX_OK;
}
r->phase_handler++;
return NGX_AGAIN;
ls->handler = ngx_http_init_connection;
ngx_http_request.[c|h]
rev = c->read;
rev->handler = ngx_http_init_request;
c->write->handler = ngx_http_empty_handler;
c->read->handler = ngx_http_request_handler;
c->write->handler = ngx_http_request_handler;
r->read_event_handler = ngx_http_block_reading;
ngx_http_handler(r);
ngx_http_run_posted_requests(c);
ngx_http_core_module.[c|h]
while (ph[r->phase_handler].checker) {
rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
if (rc == NGX_OK) {
return;
}
}
相关推荐
### Nginx 代码研究知识点概览 #### 一、Nginx 概述与特点 **Nginx**(发音为 "engine X")是一款高性能的HTTP服务器、反向代理服务器以及IMAP/POP3/SMTP代理服务器。它以其高稳定性、丰富的功能集、示例配置文件...
在0.1版代码中,可以研究NGINX如何解析配置文件,理解指令解析、变量处理等过程,这对于定制和扩展NGINX配置有很大帮助。 通过对NGINX 0.1版源代码的分析,我们可以深入了解其基本架构和设计原则。尽管随着版本...
**Nginx Web服务器代码详解** Nginx是一款高性能、轻量级的Web服务器和反向代理服务器,因其高效的并发处理能力和低内存占用而受到广泛关注。它的设计目标是实现高并发、低延迟以及稳定性,因此在大型网站和互联网...
在 `src/core/ngx_event.h` 和 `src/event/ngx_event.c` 中,可以研究 Nginx 如何高效地处理网络事件。 **3. 多进程与多线程** Nginx 通常采用主进程+工作进程的模式,主进程负责管理工作进程和配置加载,工作进程...
通过研究Nginx 1.13.10的源代码,开发者不仅可以了解其工作原理,还能深入学习网络编程、并发处理、I/O模型等相关知识,对提升系统级编程技能大有裨益。同时,这也是定制Nginx功能、优化服务器性能的重要途径。
本资源提供的"nginx开源代码"为nginx的1.3.1版本,虽然不是最新版,但对于学习其核心架构和基本工作原理非常有帮助。 Nginx的源码分析主要涉及以下几个关键知识点: 1. **事件模型**:Nginx采用的是异步非阻塞的...
Nginx源代码分析最新版本深入解析 Nginx,作为高性能的HTTP和反向代理服务器,以及IMAP/POP3/SMTP服务器,自推出...同时,我们也欢迎更多的朋友参与到Nginx源代码的研究和讨论中来,共同推动互联网技术的发展与进步。
- 源代码中关于静态文件的缓存和优化策略值得研究,以便提高服务效率。 7. **错误处理与日志记录** - Nginx 有完善的错误处理机制,包括记录错误日志、返回错误页面等,这些在实际运维中非常关键。 - 源代码中的...
通过深入研究Nginx的源代码,开发者不仅可以学习到网络编程、并发处理、服务器架构等相关知识,还可以提升在高并发环境下的问题解决能力。对于想要优化Nginx或者基于Nginx进行二次开发的工程师来说,理解源代码是至...
深入研究Nginx的源代码,能帮助开发者理解如何构建高性能、低延迟的网络服务,并为自定义扩展提供基础。对于想要优化服务器性能或开发网络应用的人来说,理解Nginx的源代码无疑是一项重要的技能。
**NGINX源代码详解** ...通过深入学习和研究NGINX的源代码,开发者可以更好地理解和定制这款强大的Web服务器,以满足特定场景的需求。同时,NGINX的源代码也是学习网络编程、并发处理和高性能服务器设计的良好教材。
3. **编译Nginx**:进入Nginx源代码目录,执行`./configure`进行配置,然后用`make`和`sudo make install`进行编译和安装。 4. **编译PHP**:在PHP源代码目录下,同样执行`./configure --with-nginx`指定Nginx路径...
通过学习和研究"nginx web服务器最新代码",我们可以深入理解Nginx的工作机制,同时也能为旧版本的维护和升级提供参考。无论是初学者还是经验丰富的开发者,对Nginx的深入理解都是提高服务质量的关键。
通过研究这个早期版本,你可以深入了解Nginx是如何从最初的代码逐渐演变为如今广泛使用的Web服务器的。同时,这个过程也是对Linux系统编程的一次深入实践,有助于提升你在C/C++编程、网络编程和系统调用方面的技能。
深入研究 Nginx 1.3.14 的源代码,可以理解其模块化设计、事件驱动架构和高效并发处理能力。这对于开发基于 Nginx 的扩展功能或者优化现有部署都是必不可少的。同时,源代码中的注释也能帮助我们了解每个功能的实现...
对于想要深入了解Nginx工作原理、进行定制化开发或者参与Nginx社区的开发者来说,研究其源代码是必不可少的步骤。你可以通过阅读源码了解Nginx如何处理网络请求、如何实现高效的并发处理机制,以及它是如何与其他...
然后,结合《深入理解Nginx》深入研究Nginx的内部机制。同时,通过阅读和分析Nginx源码,可以更直观地看到这些概念如何在实际代码中实现。 总之,掌握Nginx源码不仅可以提升Web服务的运维技能,还能为开发者提供一...
收集的 nginx 源码 解析 ,非常全 architecture.png Emiller的Nginx模块开发指南.docx Nginx(en).pdf nginx@taobao.pdf nginx_internals.pdf nginx核心讲解(0.2).doc nginx核心讲解(0.4).doc ...Ningx代码研究.docx
**Nginx源代码分析与学习笔记** Nginx是一款高性能、轻量级的Web服务器/反向代理服务器,以其高效的并发处理能力、低内存占用和丰富的模块化设计而受到广泛应用。本文将深入探讨Nginx的源代码,并结合学习笔记,...
通过研究Nginx 1.5.7的源码,我们可以深入了解网络服务器的设计理念,学习如何构建高性能、高并发的应用。同时,对于希望改进或定制Nginx功能的开发者来说,源码阅读是必不可少的步骤。通过深入源码,我们可以发现更...