ngx.log源码的简单介绍

hacker|
111

文章目录:

如何xcode学习nginx源码

1、基本结构

先来学习一下nginx内存池的几个主要数据结构:[见:./src/core/ngx_palloc.h/.c]

ngx_pool_data_t(内存池数据块结构)

1: typedef struct {

2: u_char *last;

3: u_char *end;

4: ngx_pool_t *next;

5: ngx_uint_t failed;

6: } ngx_pool_data_t;

ngx_pool_s(内存池头部结构)

1: struct ngx_pool_s {

2: ngx_pool_data_t d;

3: size_t max;

4: ngx_pool_t *current;

5: ngx_chain_t *chain;

6: ngx_pool_large_t *large;

7: ngx_pool_cleanup_t *cleanup;

8: ngx_log_t *log;

9: };

nginx 源码 epoll模块在哪个文件

Linux平台上,Nginx使用epoll完成事件驱动,实现高并发;本文将不对epoll本身进行介绍(网上一堆一堆的文章介绍epoll的原理及使用方法,甚至源码分析等),仅看一下Nginx是如何使用epoll的。

Nginx在epoll模块中定义了好几个函数,这些函数基本都是作为回调注册到事件抽象层的对应接口上,从而实现了事件驱动的具体化,我们看如下的一段代码:

[cpp] view plain copy print?

ngx_event_module_t ngx_epoll_module_ctx = {

epoll_name,

ngx_epoll_create_conf, /* create configuration */

ngx_epoll_init_conf, /* init configuration */

{

ngx_epoll_add_event, /* add an event */

ngx_epoll_del_event, /* delete an event */

ngx_epoll_add_event, /* enable an event */

ngx_epoll_del_event, /* disable an event */

ngx_epoll_add_connection, /* add an connection */

ngx_epoll_del_connection, /* delete an connection */

NULL, /* process the changes */

ngx_epoll_process_events, /* process the events */

ngx_epoll_init, /* init the events */

ngx_epoll_done, /* done the events */

}

};

这段代码就是epoll的相关函数注册到事件抽象层,这里所谓的事件抽象层在前面的博文中有提过,就是Nginx为了方便支持和开发具体的I/O模型,从而实现的一层抽象。代码后面的注释将功能说明得很详细了,本文就只重点关注ngx_epoll_init和ngx_epoll_process_events两个函数,其他几个函数就暂且忽略了。

ngx_epoll_init主要是完成epoll的相关初始化工作,代码分析如下:

[cpp] view plain copy print?

static ngx_int_t

ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)

{

ngx_epoll_conf_t *epcf;

/*取得epoll模块的配置结构*/

epcf = ngx_event_get_conf(cycle-conf_ctx, ngx_epoll_module);

/*ep是epoll模块定义的一个全局变量,初始化为-1*/

if (ep == -1) {

/*创一个epoll对象,容量为总连接数的一半*/

ep = epoll_create(cycle-connection_n / 2);

if (ep == -1) {

ngx_log_error(NGX_LOG_EMERG, cycle-log, ngx_errno,

"epoll_create() failed");

return NGX_ERROR;

}

}

/*nevents也是epoll模块定义的一个全局变量,初始化为0*/

if (nevents epcf-events) {

if (event_list) {

ngx_free(event_list);

}

/*event_list存储产生事件的数组*/

event_list = ngx_alloc(sizeof(struct epoll_event) * epcf-events,

cycle-log);

if (event_list == NULL) {

return NGX_ERROR;

}

}

nevents = epcf-events;

/*初始化全局变量ngx_io, ngx_os_is定义为:

ngx_os_io_t ngx_os_io = {

ngx_unix_recv,

ngx_readv_chain,

ngx_udp_unix_recv,

ngx_unix_send,

ngx_writev_chain,

};(位于src/os/unix/ngx_posix_init.c)

*/

ngx_io = ngx_os_io;

/*这里就是将epoll的具体接口函数注册到事件抽象层接口ngx_event_actions上。

具体是上文提到的ngx_epoll_module_ctx中封装的如下几个函数

ngx_epoll_add_event,

ngx_epoll_del_event,

ngx_epoll_add_event,

ngx_epoll_del_event,

ngx_epoll_add_connection,

ngx_epoll_del_connection,

ngx_epoll_process_events,

ngx_epoll_init,

ngx_epoll_done,

*/

ngx_event_actions = ngx_epoll_module_ctx.actions;

#if (NGX_HAVE_CLEAR_EVENT)

/*epoll将添加这个标志,主要为了实现边缘触发*/

ngx_event_flags = NGX_USE_CLEAR_EVENT

#else

/*水平触发*/

ngx_event_flags = NGX_USE_LEVEL_EVENT

#endif

|NGX_USE_GREEDY_EVENT /*io的时候,直到EAGAIN为止*/

|NGX_USE_EPOLL_EVENT; /*epoll标志*/

return NGX_OK;

}

epoll初始化工作没有想象中的复杂,和我们平时使用epoll都一样,下面看ngx_epoll_process_events,这个函数主要用来完成事件的等待并处理。

[cpp] view plain copy print?

static ngx_int_t

ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)

{

int events;

uint32_t revents;

ngx_int_t instance, i;

ngx_uint_t level;

ngx_err_t err;

ngx_log_t *log;

ngx_event_t *rev, *wev, **queue;

ngx_connection_t *c;

/*一开始就是等待事件,最长等待时间为timer;nginx为事件

专门用红黑树维护了一个计时器。后续对这个timer单独分析。

*/

events = epoll_wait(ep, event_list, (int) nevents, timer);

if (events == -1) {

err = ngx_errno;

} else {

err = 0;

}

if (flags NGX_UPDATE_TIME || ngx_event_timer_alarm) {

/*执行一次时间更新, nginx将时间缓存到了一组全局变量中,方便程序高效的获取事件。*/

ngx_time_update();

}

/*处理wait错误*/

if (err) {

if (err == NGX_EINTR) {

if (ngx_event_timer_alarm) {

ngx_event_timer_alarm = 0;

return NGX_OK;

}

level = NGX_LOG_INFO;

} else {

level = NGX_LOG_ALERT;

}

ngx_log_error(level, cycle-log, err, "epoll_wait() failed");

return NGX_ERROR;

}

/*wait返回事件数0,可能是timeout返回,也可能是非timeout返回;非timeout返回则是error*/

if (events == 0) {

if (timer != NGX_TIMER_INFINITE) {

return NGX_OK;

}

ngx_log_error(NGX_LOG_ALERT, cycle-log, 0,

"epoll_wait() returned no events without timeout");

return NGX_ERROR;

}

log = cycle-log;

/*for循环开始处理收到的所有事件*/

for (i = 0; i events; i++) {

/*取得发生此事件的连接*/

c = event_list[i].data.ptr;

instance = (uintptr_t) c 1;

c = (ngx_connection_t *) ((uintptr_t) c (uintptr_t) ~1);

/*获得该连接上的读事件*/

rev = c-read;

。。。。。。。。。。。。。

/*取得发生一个事件*/

revents = event_list[i].events;

/*记录wait的错误返回状态*/

if (revents (EPOLLERR|EPOLLHUP)) {

ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,

"epoll_wait() error on fd:%d ev:%04XD",

c-fd, revents);

}

if ((revents (EPOLLERR|EPOLLHUP))

(revents (EPOLLIN|EPOLLOUT)) == 0)

{

/*

* if the error events were returned without EPOLLIN or EPOLLOUT,

* then add these flags to handle the events at least in one

* active handler

*/

revents |= EPOLLIN|EPOLLOUT;

}

/*该事件是一个读事件,并该连接上注册的读事件是active的*/

if ((revents EPOLLIN) rev-active) {

if ((flags NGX_POST_THREAD_EVENTS) !rev-accept) {

rev-posted_ready = 1;

} else {

rev-ready = 1;

}

/*事件放入相应的队列中;关于此处的先入队再处理,在前面的文章中已经介绍过了。*/

if (flags NGX_POST_EVENTS) {

queue = (ngx_event_t **) (rev-accept ?

ngx_posted_accept_events : ngx_posted_events);

ngx_locked_post_event(rev, queue); /*入队*/

} else {

rev-handler(rev);

}

}

wev = c-write;

/*发生的是一个写事件,和读事件完全一样的逻辑过程*/

if ((revents EPOLLOUT) wev-active) {

if (flags NGX_POST_THREAD_EVENTS) {

wev-posted_ready = 1;

} else {

wev-ready = 1;

}

/*先入队再处理*/

if (flags NGX_POST_EVENTS) {

ngx_locked_post_event(wev, ngx_posted_events);

} else {

wev-handler(wev);

}

}

}

return NGX_OK;

}

本文将关注的两个epoll函数也就这么一点代码了,但整个epoll还有添加事件和删除事件等的相关函数,代码都很简单,本文就不做具体的分析了。

写到此处的时候,我感觉epoll模块没有分析的足够详细,或者说是没有足够的理解作者的用意,如果你有更好的理解,希望能够告诉我。或许,随着后面的分析,能够逐渐的真正明白吧。

nginx log format 中分别对应request中的那些变量.

是这样子的,nginx的ngx_http_variables.c文件中对于nginx内置的http变量进行了定义。

从nginx的源码来分析,修改headers_in中的host成员是不会修改$host变量的值的。

如下是nginx的代码:

{ ngx_string("http_host"), NULL, ngx_http_variable_header,

offsetof(ngx_http_request_t, headers_in.host), 0, 0 },

{ ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },

/**

*从如上的nginx变量的定义可知,对于$http_host变量,对应的才是headers_in结构体的host*成员。

*$host变量是通过ngx_http_variable_host函数去获取的。

*接下来,我们看ngx_http_variable_host的函数定义。

*/

static ngx_int_t

ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,

uintptr_t data)

{

ngx_http_core_srv_conf_t  *cscf;

if (r-headers_in.server.len) {

v-len = r-headers_in.server.len;

v-data = r-headers_in.server.data;

} else {

cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

v-len = cscf-server_name.len;

v-data = cscf-server_name.data;

}

v-valid = 1;

v-no_cacheable = 0;

v-not_found = 0;

return NGX_OK;

}

/**

*从函数定义可知,$host变量的值实际上是取得header_in结构中的server成员。如果该成员 *为空,取得的是配置文件中的server_name指令的值。

*/

因此,通过上述的分析,你修改了header_in的host成员,$host变量不变是正常的。可以用$http_host来代替$host来试试。

全部来自转载并非原创

nginx + lua 有没有办法获取到 upstream 中某个上游挂了的信息

1下载luajit2.0并安装我是直接使用源码makemakeinstall所以lib和include是直接放在/usr/local/lib和usr/local/include2下载nginx源码,解压注意版本号,如果机子上已经装了nginx,不想升级的话,请使用/to/nginx/sbin/nginx–v来查看版本号3下载ngx_devel_kitHERE解压4下载nginx_lua_moduleHERE解压5进入nginx源码文件夹cdnginx-1.0.11/6导入环境变量,编译exportLUAJIT_LIB=/usr/local/lib#这个很有可能不一样exportLUAJIT_INC=/usr/local/include/luajit-2.0#这个很有可能不一样./configure--prefix=/opt/nginx\#nginx的安装路径--add-module=/path/to/ngx_devel_kit\#ngx_devel_kit的源码路径--add-module=/path/to/lua-nginx-module#nginx_lua_module的源码路径make-j2makeinstall7测试是否成功:nginxconfig中加入location/hello{default_type'text/plain';content_by_lua'ngx.say("hello,lua")';}使用/to/nginx/sbin/nginx–t检查nginx配置,此时应该没有报错8/to/nginx/sbin/nginx#启动nginx或者/to/nginx/sbin/nginx–sreload#重启nginx访问192.168.100.1/hello会出现“hello,lua”

4条大神的评论

  • avatar
    访客 2022-07-13 上午 05:12:55

    ithout timeout"); return NGX_ERROR; } log = cycle-log; /*for循环开始处理收到的所有事件*/ for

  • avatar
    访客 2022-07-13 上午 03:55:59

    t failed; 6: } ngx_pool_data_t;ngx_pool_s(内存池头部结构) 1: struct ngx_pool_s { 2: ngx_pool_data_t d; 3:

  • avatar
    访客 2022-07-13 上午 01:58:37

    nx-1.0.11/6导入环境变量,编译exportLUAJIT_LIB=/usr/local/lib#这个很有可能不一样exportLUAJIT_INC=/usr/local/include/luajit-2.0#这个很有可能不一样./configure--prefix=/opt/ng

  • avatar
    访客 2022-07-13 上午 04:44:36

    og_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "epoll_wait() error on fd:%d ev:%04XD",

发表评论