Nginx源码分析1--------编写Nginx扩展模块

近日来申请通过CSDN准专家,为了顺利在六个月后升级为认证专家,并对得起这个勋章,我感觉 不能松懈博客的更新频率以及质量了。C/C++ windows下的开发是我相对来说做的比较多的地方,对于Linux下的服务器开发
等等也算是半路出家,恰逢近来在研究分布式存储,涉及到了 Nginx 扩展开发以及配置,查阅了好多的资料发现Nginx配置部署起来相当的容易,但是源代码是真的晦涩难懂,经常会看的我们百思不得其解,所以扩展开发Nginx模块也不是一个轻松的事情,那我就从Nginx扩展模块开始,一步一步剖析Nginx源代码,

~~太暴力了有木有。 

参考了下一些开源代码的实现发现,Nginx代码看似天书实际上是有理可依据的,在Nginx下 我们大约可以写三种类型的扩展 ,我只打算写一个简单的http扩展~但是这带领入门足矣。

1、http扩展

如下图所示的扩展  这些扩展是Nginx自带的 下面我打算仿写的就是这一类扩展 形似神似的东西

     

2、Filter过滤器

 这家伙能干的事情可大了~我们可以把我们的Filter挂接到Nginx的Filter上,进行数据流过滤,具体应用在什么地方大家自己考虑去 ,这里不做解释了。

3、负载均衡器 

你是否抱怨过 Nginx的 轮询机制  IP_HASH  以及 服务器权重方式 实现的负载均衡达不到想到的效果? 既然Nginx不能满足你的需求 你需要自己满足自己的需求,你可以扩展一个自己的负载

均衡器。

多说无用啊~~~~还是先上代码吧

英文Ubuntu下搜狗出了点问题 Qt下打不出中文了,注释部分写了英文 凑合看吧。英文也不规范

/****************************************************
 * Nginx Extension Module By YDW
 * ********************************************************/
//定义了一堆宏  并且根据预编译选项 区分不同的操作系统加载不同的配置文件
#include </home/usher/Downloads/nginx-1.6.2/src/core/ngx_config.h>
//nginx内核头文件 包含了nginx所需要的基本头文件 以及 定义了部分nginx 结构体的别名
#include </home/usher/Downloads/nginx-1.6.2/src/core/ngx_core.h>
//nginx类型 string  ngx_str_t  作者真够变态的 所有的类型 操作函数 都自己定义了一遍  而且开发扩展nginx 有些时候必须要用
//作者提供的ngx 系列的类型和函数 这个切记
#include </home/usher/Downloads/nginx-1.6.2/src/core/ngx_string.h>
//定义了处理http协议的结构和函数
#include </home/usher/Downloads/nginx-1.6.2/src/http/ngx_http.h>

//define nginx hello_ydw module struct  定义
typedef struct
{
    //nginx style of string
    ngx_str_t output_words;
} ngx_http_hello_ydw_loc_conf_t;

//process  the hello_ydw command
static char* ngx_http_hello_ydw(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
//allocate memory for hello world command
static void*ngx_http_hello_ydw_create_loc_conf(ngx_conf_t*cf);
//copy hello ydw argument to another place
static char* ngx_http_hello_ydw_merge_loc_conf(ngx_conf_t*cf,void*parent,void *child);

//structure for hello_ydw Command
// Structure for the HelloWorld command
static ngx_command_t ngx_http_hello_ydw_commands[] = {
    {
        ngx_string("hello_ydw"), // The command name
        NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
        ngx_http_hello_ydw, // The command handler  处理命令的函数
        NGX_HTTP_LOC_CONF_OFFSET,
        offsetof(ngx_http_hello_ydw_loc_conf_t, output_words),
        NULL
    },
    ngx_null_command
};

// Structure for the HelloWorld context
static ngx_http_module_t ngx_http_hello_ydw_module_ctx = {
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    ngx_http_hello_ydw_create_loc_conf,
    ngx_http_hello_ydw_merge_loc_conf
};

// Structure for the HelloWorld module, the most important thing
ngx_module_t ngx_http_hello_ydw_module = {
    NGX_MODULE_V1,
    &ngx_http_hello_ydw_module_ctx,
    ngx_http_hello_ydw_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};
//注意这里才是主要的http请求处理函数
static ngx_int_t ngx_http_hello_ydw_handler(ngx_http_request_t* r) {
    ngx_int_t rc;
    ngx_buf_t* b;
    ngx_chain_t out[2];

    ngx_http_hello_ydw_loc_conf_t* hlcf;
    hlcf = ngx_http_get_module_loc_conf(r, ngx_http_hello_ydw_module);

    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));

    out[0].buf = b;
    out[0].next = &out[1];

    b->pos = (u_char*)"hello_ydw, ";
    b->last = b->pos + sizeof("hello_ydw, ") - 1;
    b->memory = 1;

    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

    out[1].buf = b;
    out[1].next = NULL;

    b->pos = hlcf->output_words.data;
    b->last = hlcf->output_words.data + (hlcf->output_words.len);
    b->memory = 1;
    b->last_buf = 1;

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = hlcf->output_words.len + sizeof("hello_ydw, ") - 1;
    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]);
}
//这个函数只是在nginx内存池分配了一个 结构

static void* ngx_http_hello_ydw_create_loc_conf(ngx_conf_t* cf) {
    ngx_http_hello_ydw_loc_conf_t* conf;

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

    return conf;
}
//合并父子配置文件
static char* ngx_http_hello_ydw_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child) {
    ngx_http_hello_ydw_loc_conf_t* prev = parent;
    ngx_http_hello_ydw_loc_conf_t* conf = child;
    ngx_conf_merge_str_value(conf->output_words, prev->output_words, "Nginx");
    return NGX_CONF_OK;
}
//处理 hello_ydw命令的函数
static char* ngx_http_hello_ydw(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_ydw_handler;
    ngx_conf_set_str_slot(cf, cmd, conf);
    return NGX_CONF_OK;
}

代码编写玩了 现在我们来编写编译配置文件 config复制一个开源扩展的格式我们修改下即可 

ngx_addon_name=ngx_http_hello_ydw_module
HTTP_MODULES="$HTTP_MODULES ngx_http_hello_ydw_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_ydw_module.c"

代码配置文件 写完了 现在我们建立一个 文件夹 ngx_http_hello_ydw_module 来存放 config 和 ngx_http_hello_ydw_module.c结构如下  好了我们的模块就编写好了啊~~~~~

开始编译安装吧我用的是Nginx_1.62 ,我们下载nginx源代码 解压  

依次

./configure --add-module=../nginx_http_ydw_module/ --prefix=/usr/local/nginx2 --conf-path=/etc/nginx2/nginx.conf

make&&make install  

看到如下结构   最后ngx_http_hello_ydw_module.o已经编译完毕 说明我们的扩展编译成功了 

等待make install结束安装 。




好了编译安装完nginx 那么我们首先修改Nginx的配置文件 nginx.conf

添加上一行 

location /hello_ydw

 {       

           #处理hello_ydw命令 这个命令我们在代码声明过得哦。
            hello_ydw  ExtensionSuccessful;
 }


现在启动Nginx

/usr/local/nginx2/sbin/nginx  

现在开始测试效果吧   看吧成功了 到了这一步意味着你可以自己写Nginx的扩展程序了哦 

时间: 2024-09-20 09:33:08

Nginx源码分析1--------编写Nginx扩展模块的相关文章

Nginx源码分析-Epoll模块

Linux平台上,Nginx使用epoll完成事件驱动,实现高并发:本文将不对epoll本身进行介绍(网上一堆一堆的文章介绍epoll的原理及使用方法,甚至源码分析等),仅看一下Nginx是如何使用epoll的. Nginx在epoll模块中定义了好几个函数,这些函数基本都是作为回调注册到事件抽象层的对应接口上,从而实现了事件驱动的具体化,我们看如下的一段代码: ngx_event_module_t ngx_epoll_module_ctx = { &epoll_name, ngx_epoll_

nginx线程池源码分析_nginx

周末看了nginx线程池部分的代码,顺手照抄了一遍,写成了自己的版本.实现上某些地方还是有差异的,不过基本结构全部摘抄. 在这里分享一下.如果你看懂了我的版本,也就证明你看懂了nginx的线程池. 本文只列出了关键数据结构和API,重在理解nginx线程池设计思路.完整代码在最后的链接里. 1.任务节点 typedef void (*CB_FUN)(void *); //任务结构体 typedef struct task { void *argv; //任务函数的参数(任务执行结束前,要保证参数

《深入剖析Nginx》一第1章 源码分析的准备工作

第1章 源码分析的准备工作 深入剖析Nginx 从Nginx(读作engine x)的官方网站1,我们可以看到如下介绍:Nginx是Igor Sysoev2编写的一款HTTP和反向代理服务器,另外它也可以当作邮件代理服务器.它一直被众多流量巨大的俄罗斯网站所使用,例如Yandex3.Mail.Ru4.VKontakte5以及Rambler6等.据Netcraft统计,截止到2012年8月份,世界上最繁忙的网站中有11.48%7在使用Nginx作为其服务器或者代理服务器.部分典型成功案例有:Net

《深入剖析Nginx》——第1章 源码分析的准备工作1.1 主要特性

第1章 源码分析的准备工作 从Nginx(读作engine x)的官方网站,我们可以看到如下介绍:Nginx是Igor Sysoev编写的一款HTTP和反向代理服务器,另外它也可以当作邮件代理服务器.它一直被众多流量巨大的俄罗斯网站所使用,例如Yandex.Mail.Ru.VKontakte以及Rambler等.据Netcraft统计,截止到2012年8月份,世界上最繁忙的网站中有11.48%在使用Nginx作为其服务器或者代理服务器.部分典型成功案例有:Netflix.Wordpress.co

《深入剖析Nginx》一1.4 源码分析工具

1.4 源码分析工具 深入剖析Nginx 对于Windows平台,首选Source Insight1源码阅读工具.该工具功能强大,根据其官方网站的介绍,Source Insight是一款面向项目开发的程序编辑器和代码浏览器,它拥有内置的对C/C++.C#和Java等程序的分析功能.Source Insight能自动分析和动态维护源码工程的符号数据库,并在用户查看代码时显示有用的对应上下文信息. 如果是在Linux平台下,则可以利用Vi2.Taglist3.Cscope4以及Ctag5这几个工具来

《深入剖析Nginx》——1.4 源码分析工具

1.4 源码分析工具 对于Windows平台,首选Source Insight1源码阅读工具.该工具功能强大,根据其官方网站的介绍,Source Insight是一款面向项目开发的程序编辑器和代码浏览器,它拥有内置的对C/C++.C#和Java等程序的分析功能.Source Insight能自动分析和动态维护源码工程的符号数据库,并在用户查看代码时显示有用的对应上下文信息. 如果是在Linux平台下,则可以利用Vi2.Taglist3.Cscope4以及Ctag5这几个工具来组合成阅读Nginx

Nginx源码安装及调优配置

由于Nginx本身的一些优点,轻量,开源,易用,越来越多的公司使用nginx作为自己公司的web应用服务器,本文详细介绍nginx源码安装的同时并对nginx进行优化配置. Nginx编译前的优化 [root@linuxprobe ~]# wget http://nginx.org/download/nginx-1.10.1.tar.gz [root@linuxprobe ~]# tar xvf nginx-1.10.1.tar.gz -C /usr/local/src/ [root@linux

菜鸟nginx源码剖析 框架篇(一) 从main函数看nginx启动流程(转)

俗话说的好,牵牛要牵牛鼻子 驾车顶牛,处理复杂的东西,只要抓住重点,才能理清脉络,不至于深陷其中,不能自拔.对复杂的nginx而言,main函数就是"牛之鼻",只要能理清main函数,就一定能理解其中的奥秘,下面我们就一起来研究一下nginx的main函数. 1.nginx的main函数解读 nginx启动显然是由main函数驱动的,main函数在在core/nginx.c文件中,其源代码解析如下,涉及到的数据结构在本节仅指出其作用,将在第二节中详细解释. nginx main函数的流

nginx模块_使用gdb调试nginx源码

工欲善其事必先利其器,如何使用调试工具gdb一步步调试nginx是了解nginx的重要手段. ps:本文的目标人群是像我这样初接触Unix编程的同学,如果有什么地方错误请指正. 熟悉gdb的使用 这里就不说了,谷歌一搜一堆,这里推荐一篇文章:GDB 命令详细解释 请重点看一下step,run,break,list,info,continue命令 下载nginx源码 这里使用nginx-1.0.14 src是源代码,auto文件夹是configure运行时候的各种命令集合 修改config并编译