zoukankan      html  css  js  c++  java
  • [开发记录]Nginx模块开发(二)

    引言:Nginx模块提供了upstream(上游服务器)的异步回调处理模块开发,以memcached 模块为例

    commands结构的初始化为相应的命令添加回调函数,用来处理 memcached_pass 这个命令

     1 static ngx_command_t  ngx_http_memcached_commands[] = {
     2 
     3     { ngx_string("memcached_pass"),
     4       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
     5       ngx_http_memcached_pass,  // 这里添加回调
     6       NGX_HTTP_LOC_CONF_OFFSET,
     7       0,
     8       NULL },
     9      .....
    10 }

    看看 ngx_http_memcached_pass 的实现:

    此函数会对 conf 做一些初始化操作

    static char *
    ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_http_memcached_loc_conf_t *mlcf = conf;
    
        ngx_str_t                 *value;
        ngx_url_t                  u;
        ngx_http_core_loc_conf_t  *clcf;
    
        if (mlcf->upstream.upstream) {
            return "is duplicate";
        }
    
        value = cf->args->elts;
    
        ngx_memzero(&u, sizeof(ngx_url_t));
    
        u.url = value[1];
        u.no_resolve = 1;
    
        mlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
        if (mlcf->upstream.upstream == NULL) {
            return NGX_CONF_ERROR;
        }
    
        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    
        clcf->handler = ngx_http_memcached_handler; //为此请求添加回调
    
        if (clcf->name.data[clcf->name.len - 1] == '/') {
            clcf->auto_redirect = 1;
        }
    
        mlcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
    
        if (mlcf->index == NGX_ERROR) {
            return NGX_CONF_ERROR;
        }
    
        return NGX_CONF_OK;
    }
    

    整个模块的定义:

    ngx_http_memcached_commands 是传入的变量

    ngx_http_memcached_module_ctx 是模块的 context 结构

    此结构存储了所有的为配置信息初始化的回调函数

     1 ngx_module_t  ngx_http_memcached_module = {
     2     NGX_MODULE_V1,
     3     &ngx_http_memcached_module_ctx,        /* module context */
     4     ngx_http_memcached_commands,           /* module directives */
     5     NGX_HTTP_MODULE,                       /* module type */
     6     NULL,                                  /* init master */
     7     NULL,                                  /* init module */
     8     NULL,                                  /* init process */
     9     NULL,                                  /* init thread */
    10     NULL,                                  /* exit thread */
    11     NULL,                                  /* exit process */
    12     NULL,                                  /* exit master */
    13     NGX_MODULE_V1_PADDING
    14 };

     1 static ngx_http_module_t  ngx_http_memcached_module_ctx = {
     2     NULL,                                  /* preconfiguration */
     3     NULL,                                  /* postconfiguration */
     4 
     5     NULL,                                  /* create main configuration */
     6     NULL,                                  /* init main configuration */
     7 
     8     NULL,                                  /* create server configuration */
     9     NULL,                                  /* merge server configuration */
    10 
    11     ngx_http_memcached_create_loc_conf,    /* create location configration */
    12     ngx_http_memcached_merge_loc_conf      /* merge location configration */
    13 };

    回调 ngx_http_memcached_create_loc_conf 用来为配置信息分配存储空间并初始化

    以后需要使用到配置信息的参数的时候使用方式如下:

        ngx_http_memcached_loc_conf_t  *mlcf;
        mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
    

    其中 ngx_http_memcached_loc_conf_t 是自己定义的配置信息的结构

    memcached 模块的定义如下:

    1 typedef struct {
    2     ngx_http_upstream_conf_t   upstream;
    3     ngx_int_t                  index;
    4 } ngx_http_memcached_loc_conf_t;

    这些都是初始化的操作,看看核心函数:

    ngx_http_memcached_handler

     1 static ngx_int_t
     2 ngx_http_memcached_handler(ngx_http_request_t *r)
     3 {
     4     ngx_int_t                       rc;
     5     ngx_http_upstream_t            *u;
     6     ngx_http_memcached_ctx_t       *ctx;
     7     ngx_http_memcached_loc_conf_t  *mlcf;
     8 
     9     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
    10         return NGX_HTTP_NOT_ALLOWED;
    11     }
    12 
    13     rc = ngx_http_discard_request_body(r);
    14 
    15     if (rc != NGX_OK) {
    16         return rc;
    17     }
    18 
    19     if (ngx_http_set_content_type(r) != NGX_OK) {
    20         return NGX_HTTP_INTERNAL_SERVER_ERROR;
    21     }
    22     // 创建一个 upstream
    23     if (ngx_http_upstream_create(r) != NGX_OK) {
    24         return NGX_HTTP_INTERNAL_SERVER_ERROR;
    25     }
    26     //取得这个 upstream
    27     u = r->upstream;
    28 
    29     ngx_str_set(&u->schema, "memcached://");
    30     u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module;
    31 
    32     ngx_http_memcached_loc_conf_t  *mlcf;
    33     mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
    34 
    35     u->conf = &mlcf->upstream;
    36     //为 upstream 添加回调
    37     u->create_request = ngx_http_memcached_create_request;     //创建到 upstream的后端请求
    38     u->reinit_request = ngx_http_memcached_reinit_request;     //失败后再次创建
    39     u->process_header = ngx_http_memcached_process_header;     //处理来自后端的数据
    40     u->abort_request = ngx_http_memcached_abort_request;       //放弃数据
    41     u->finalize_request = ngx_http_memcached_finalize_request; //析构这个请求
    42 
    43     ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t));
    44     if (ctx == NULL) {
    45         return NGX_HTTP_INTERNAL_SERVER_ERROR;
    46     }
    47 
    48     ctx->rest = NGX_HTTP_MEMCACHED_END;
    49     ctx->request = r;
    50 
    51     ngx_http_set_ctx(r, ctx, ngx_http_memcached_module);
    52 
    53     u->input_filter_init = ngx_http_memcached_filter_init;
    54     u->input_filter = ngx_http_memcached_filter;
    55     u->input_filter_ctx = ctx;
    56 
    57     r->main->count++;
    58 
    59     ngx_http_upstream_init(r);
    60 
    61     return NGX_DONE;
    62 }

    其中可以看到, 大部分的回调都是传入参数 ngx_http_request_t *r

    1 static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r);
    2 static ngx_int_t ngx_http_memcached_reinit_request(ngx_http_request_t *r);
    3 static ngx_int_t ngx_http_memcached_process_header(ngx_http_request_t *r);
    4 static ngx_int_t ngx_http_memcached_filter_init(void *data);
    5 static ngx_int_t ngx_http_memcached_filter(void *data, ssize_t bytes);
    6 static void ngx_http_memcached_abort_request(ngx_http_request_t *r);
    7 static void ngx_http_memcached_finalize_request(ngx_http_request_t *r,
    8     ngx_int_t rc);

    函数处理时候会通过 r 取得 upstream并做一番”加工“

    create_request 的时候会有 r -> upstream = u ;

    设置完这几个回调函数以后,就会为相应的请求添加这个回调,来自下游的服务器的请求会被分发到upstream中去,但是Nginx在本身的转发过程中是不阻塞的  

      

    文章属原创,转载请注明出处 联系作者: Email:zhangbolinux@sina.com QQ:513364476
  • 相关阅读:
    再说LZ77压缩算法
    关于LZ77压缩算法
    Qt 简易设置透明按钮
    MFC edit 控件 自动将光标置于想要输入内容的位置
    事件和委托
    2016/06/07
    2016/04/28
    2016/4/27
    2016/04/26
    重载和重写(Overload, Override)
  • 原文地址:https://www.cnblogs.com/Bozh/p/2658961.html
Copyright © 2011-2022 走看看