`

解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现

 
阅读更多

解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现

  • 作者:柳大·Poechant(钟超)
  • 邮箱:zhongchao.ustc#gmail.com(# -> @)
  • 博客:Blog.CSDN.net/Poechant
  • 日期:June 2nd, 2012

还记得我们定义过一个结构体如下吗?

typedef struct {
    ngx_str_t output_words;
} ngx_http_hello_world_loc_conf_t;

它就是 HelloWorld 的 location 组件配置,其中有一个字符串成员 output_words。

1 create location

用于 ngx_http_hello_world_module_ctx 中的 location 创建函数:

static void* ngx_http_hello_world_create_loc_conf(ngx_conf_t* cf) {
    ngx_http_hello_world_loc_conf_t* conf;

    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_hello_world_loc_conf_t));
    if (conf == NULL) {
        return NGX_CONF_ERROR;
    }
    conf->output_words.len = 0;
    conf->output_words.data = NULL;

    return conf;
}

我们可以看到,就是先分配一段 ngx_http_hello_world_loc_conf_t 所使用的大小的内存。并初始化 ngx_http_hello_world_loc_conf_t 唯一的成员 output_words。

2 merge location

用于 ngx_http_hello_world_module_ctx 中的 location 合并函数:

static char* ngx_http_hello_world_merge_loc_conf(ngx_conf_t* cf,
        void* parent,
        void* child) {
    ngx_http_hello_world_loc_conf_t* prev = parent;
    ngx_http_hello_world_loc_conf_t* conf = child;
    ngx_conf_merge_str_value(conf->output_words, prev->output_words, "boy");
    return NGX_CONF_OK;
}

3 ngx_http_hello_world

3.1 ngx_http_conf_get_module_loc_conf

首先你要了解一个 Nginx 提供的一个“函数”:

ngx_http_conf_get_module_loc_conf(
    cf, // configuration
    module
);

实际上它是一个宏定义,在 ngx_http_config.h 中:

#define ngx_http_conf_get_module_loc_conf(cf, module) \
    ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]

它的作用是通过 cf 配置的上下文,找到指定的 module 中的 location configuration。

3.2 ngx_http_hello_world

用于 ngx_http_hello_world_commands 中我们定义的唯一的一个命令的 set 字段。

static char* ngx_http_hello_world(ngx_conf_t* cf,
        ngx_command_t* cmd,
        void* conf) {
    ngx_http_core_loc_conf_t* clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_hello_world_handler;
    ngx_conf_set_str_slot(cf, cmd, conf);
    return NGX_CONF_OK;
}

这个函数的作用,就是生成对请求的响应内容,即本例中的hello_world, Poechant。然后获取到 http_core_module 的 location configuration,即 clcf(Core Location ConF)。给 clcf 的 handler 字段赋值 ngx_http_hello_world_handler,这个函数下面会介绍。然后再常规地调用 ngx_conf_set_str_slot。

4 ngx_http_hello_world_handler

首先你要再了解一个 Nginx 提供的一个“函数”:

4.1 ngx_http_conf_get_module_loc_conf

ngx_http_conf_get_module_loc_conf(
    r, // request
    module
);

实际上它是一个宏定义,在 ngx_http_config.h 中:

#define ngx_http_get_module_loc_conf(r, module)  (r)->loc_conf[module.ctx_index]

其作用是根据 module 的索引字段(ctx_index),找到 request 所请求的 location 配置。

4.2 ngx_http_hello_world_handler

首先来看看 Nginx 中比较经典的缓冲区 ngx_buf_t 吧。这里只介绍与本文相关的部分。

struct ngx_buf_s {
    u_char          *pos;
    u_char          *last;

    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */

    …
};

这四个指针把缓冲区划分为 3 个部分。分别如下:

  • 第一部分(start 到 pos):
    • 只读缓冲区:对于只读缓冲区,这部分是已读部分;
    • 只写缓冲区:对于只写缓冲区,不会有这部分。
  • 第二部分(pos 到 last):
    • 只读缓冲区:对于只读缓冲区,这部分是欲读取的部分;
    • 只写缓冲区:对于只写缓冲区,已写入的区域。
  • 第三部分(last 到 end):
    • 只读缓冲区:对于只读缓冲区,不会有这部分;
    • 只写缓冲区:对于只写缓冲区,剩余可写区域。

ngx_buf_t 之所以经典的另一个原因,是因为nginx可以提前flush输出,所以这些buf被输出后就可以重复使用,可以避免重分配,提高系统性能,被称为free_buf,而没有被输出的buf就是busy_buf。

那么来看 ngx_http_hello_world_handler 吧:

static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t* r) {
    ngx_int_t rc;
    ngx_buf_t* b;
    ngx_chain_t out[2];

    ngx_http_hello_world_loc_conf_t* hlcf;
    hlcf = ngx_http_get_module_loc_conf(r, ngx_http_hello_world_module);

    // 设置 request 的 header
    r->headers_out.content_type.len = sizeof("text/plain") - 1;
    r->headers_out.content_type.data = (u_char*)"text/plain";

    // 分配缓冲区的内存空间   
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

    // 第 1 块缓冲区
    out[0].buf = b;
    out[0].next = &out[1];

    // 本模块中,缓冲区只需要写入数据,所以只设置 pos 和 last
    b->pos = (u_char*)"hello_world, ";
    b->last = b->pos + sizeof("hello_world, ") - 1;
    b->memory = 1; // 标示缓冲区是内存缓冲

    // 分配缓冲区的内存空间
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

    // 第 2 块缓冲区
    out[1].buf = b;
    out[1].next = NULL;

    // 本模块中,缓冲区只需要写入数据,所以只设置 pos 和 last
    b->pos = hlcf->output_words.data;
    b->last = hlcf->output_words.data + (hlcf->output_words.len);
    b->memory = 1; // 标示缓冲区是内存缓冲
    b->last_buf = 1; // 标示整个响应最后一个缓冲区,nginx会立即发送缓冲的所有数据

    // 设置 request 的 header
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = hlcf->output_words.len + sizeof("hello_world, ") - 1;

    // 发送 request
    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        return rc;
    }

    return ngx_http_output_filter(r, &out[0]);
}

5 Reference

  1. www.evanmiller.org/nginx-modules-guide.html
  2. http://blog.sina.com.cn/s/blog_7303a1dc0100x70t.html

-

转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant

-

分享到:
评论

相关推荐

    ngx_http_proxy_connect_module.zip

    ngx_http_proxy_connect_module是一个针对Nginx服务器的第三方模块,主要功能是支持HTTP代理的"CONNECT"方法。在默认情况下,Nginx仅处理HTTP和HTTPS请求,但不支持通过HTTP代理进行TCP连接,比如SSL/TLS隧道。这个...

    nginx限制连接数ngx_http_limit_conn_module模块1

    【Nginx 限制连接数 ngx_http_limit_conn_module 模块详解】 在互联网服务中,服务器经常面临流量异常、负载过大的情况,尤其在遭受大流量恶意攻击时,带宽的浪费、服务器压力的增大都会对业务造成严重影响。为了...

    lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams.zip

    lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams 电子邮件名称ngx_http_lua_upstream - Nginx MODULE,用于向 Nginx upstreams公开Lua到 ngx_lua目录NAME状态概要说明函数get_...

    ngx_http_mytest_module.zip_nginx_world

    在本文中,我们将深入探讨如何进行Nginx的模块二次开发,特别关注“ngx_http_mytest_module.zip_nginx_world”这个示例项目。这个压缩包包含了一个基础的Nginx自定义模块,可以视为模块开发的"Hello, World!"级别...

    ngx_lua_module-windows-1.1.2.0

    ngx_lua_module是一款强大的扩展模块,专为Nginx服务器设计,允许在Nginx配置文件中直接嵌入Lua脚本,极大地增强了Nginx的功能和灵活性。这个"ngx_lua_module-windows-1.1.2.0"是该模块的一个Windows版本,适应于...

    ngx_http_dav_ext_module.so

    ngx_http_dav_ext_module.so centos7 nginx 1.18 可以作为模块加载

    使用nginx作为http/https正向代理ipm包,包含ngx_http_proxy_connect_module 模块,第三方图片代理,带有缓存

    使用nginx作为http/https正向代理ipm包,包含ngx_http_proxy_connect_module 模块,附带了第三方图片代理配置,带有缓存,可直接做图片服务器 下载后执行:rpm -ivh nginx-1.12.2-1.el7_4.ngx.x86_64.rpm 打包教程:...

    ngx_devel_kit-0.3.0

    ngx_devel_kit(通常缩写为 NDK)是一个针对Nginx的模块开发工具集,它为构建自定义Nginx模块提供了便利。在Nginx生态系统中,NDK是一个重要的扩展工具,允许开发者利用C语言直接操作Nginx的内部结构,以实现更高级...

    ngx_stream_ssl_preread_module调研.docx

    NGX_STREAM_SSL_PREREAD_MODULE 是一个基于流媒体(Stream)实现的 SSL/TLS 协议 ClientHello 消息提取模块,主要用于提取 SNI(Server Name Indicate)或者 ALPN(Application Layer Protocol Negotiation,应用层...

    nginx-1.25.4-x86-64-ngx-http-proxy-connect-module

    增加了ngx_http_proxy_connect_module模块的,已经编译好的windows exe文件。 可以正向代理https请求。来源地址:https://github.com/dyq94310/nginx-build-msys2/releases 使用方法,放到从官网下的nginx windows...

    ngx_http_consistent_hash-master.zip

    描述提到的是 Nginx 上一致性哈希的实现,通过第三方模块 ngx_http_consistent_hash。一致性哈希是一种分布式哈希算法,常用于负载均衡系统中,特别是在分布式缓存和微服务架构中,以确保在节点增减时尽量少地改变已...

    ngx_http_proxy_connect_module-master (2).zip

    用于nginx的http正向代理https使用的模块

    Nginx的SQLite模块ngx_sqlite.zip

    ngx_sqlite 是嵌入 sqlite 数据库的 nginx 模块。通过强大的nginx server,可以使用http协议访问sqlite数据库。环境- sqlite 3- nginx-1.6.3 安装```sh $ git clone https://github.com/rryqszq4/ngx_sqlite.git...

    Nginx模块ngx_req_status

    ngx_req_status用来展示nginx请求状态信息,类似于apache的status,nginx自带的模块只能显示连接数等等信息,我们并不能知道到底有哪些请求、以及各url域名所消耗的带宽是多少。ngx_req_status提供了这些功能. 1、按...

    nginx缓存清除插件ngx_cache_purge.zip

    ngx_cache_purge 是 nginx 模块,此模块可以清理 nginx 的 FastCGI、proxy、 SCGI 和 uWSGI 的缓存。配置指令(相同位置语法)fastcgi_cache_purgesyntax: fastcgi_cache_purge on|off|<method> [from all|<ip> [.....

    ngx_stream_module.so

    nginx1.20.2

    ngx_http_captcha_module:用于生成验证码和验证验证码的Nginx模块

    此nginx模块可直接生成验证码和验证验证码,可在nginx配置中自定义验证码大小、长度、字体、过期时间等。此项目无需版权,可自由下载使用或二次开发。 安装方法: 1. $ cp ngx_...

    nginx_upstream_check_module-master.zip

    nginx自带是没有针对负载均衡后端节点的健康检查的,但是可以通过默认自带的ngx_http_proxy_module 模块和ngx_http_upstream_module模块中的相关指令来完成当后端节点出现故障时,自动切换到健康节点来提供访问。

    ngx_kafka_module, Nginx Kafka 模块,将日志日志数据发送到 Kafka 群集.zip

    ngx_kafka_module, Nginx Kafka 模块,将日志日志数据发送到 Kafka 群集 Nginx Kafka 模块 Nginx Kafka MODULE 用于接收 HTTP POST 数据并向 Kafka 传递消息。如果使用这里 MODULE 时存在任何问题,请随时向我发送...

Global site tag (gtag.js) - Google Analytics