本文是对陶辉《深入理解Nginx》第5章内容的梳理以及实现,代码和注释基本出自此书。

 

(一)模块框架

  首先要明确的是,这里是编写一个使用upstream的模块,而不是编写upstream模块。因此,和HelloWorld类似,模块结构体ngx_http_mytest_module、模块上下文结构体ngx_http_mytest_module_ctx、数组ngx_http_mytest_command[]、方法ngx_http_mytest()和ngx_http_mytest_handler()的框架是不可少而且又十分相似的。如果忘记了它们之间的关系,请回顾原书或《深入理解Nginx》阅读与实践(一):Nginx安装配置与HelloWorld

  模块处理的请求是ngx_http_request_t结构对象r,它包含了一个ngx_http_upstream_t类型的成员upstream。当upstream非NULL时,将会根据其中设置的内容定制访问第三方服务的方式。而这个请求的处理是由upstream模块来完成的。从这里开始,要注意区分请求r中的upstream成员和Nginx提供的upstream模块不是一回事,而是由前者来指导后者的工作。前者的设定与开启(即告知upstream模块需要进行处理,通过ngx_http_upstream_init()实现)是由我们编写的的第三方模块(本文中是mytest)来完成的。

 

(二)upstream设置

  upstream工作方式的配置可以通过填写由ngx_http_upstream_create(ngx_http_request_t *r)所传入的请求r中的ngx_http_upstream_t结构体来完成。这个函数成功返回时,即把请求r中的upstream设置为非NULL。ngx_http_upstream_t结构体主要包含了一下几个成员,由于原书对这里模块编写所需要用到的成员已做详细介绍(暂时用不到的成员在12章介绍),这里只做一个部分的概括:

typedef ngx_http_upstream_s ngx_http_upstream_t;
sturct ngx_http_upstream_s {
  ...

  ngx_chain_t request_bufs;//发给上游服务器的请求,由create_request()完成

  ngx_http_upstream_conf_t conf;//超时时间等限制性参数

  ngx_http_upstream_resolved_t resolved;//用于直接指定的上游服务器地址

  //设定方法请见mytest模块的ngx_http_mytest_handler()方法

  

  /* 3个必须实现的回调方法 */

  ngx_int_t   (*create_request)(ngx_http_request_t *r);//构造向上游服务器发送的请求内容。调用mytest时,只调用一次

  ngx_int_t   (*process_header)(ngx_http_request_t *r);//收到上游服务器后对包头进行处理的方法

  void (*finalize_request)  (ngx_http_request_t *r, ngx_int_t rc);//销毁upstream请求时调用

 

  /* 5个可选的回调方法,本文中用不到*/

  ngx_int_t  (*input_filter_init)(void *data);//处理上游包体

  ngx_int_t  (*input_filter)(void *data,ssize_t bytes);//处理上游包体

  ngx_int_t  (*reinit_request)(ngx_http_request_t *r);//第一次向上游服务器建立连接失败时调用

  void     (*abort_request)(ngx_http_request_t *r);

  ngx_int_t   (*rewrite_redirect)(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix); //主要用于反向代理

  ...
}

   可见,使用upstream功能时,除了需要按HelloWorld编写自己的模块和提供处理配置项的方法ngx_http_mytest_create_loc_conf()、ngx_http_mytest_merge_loc_conf()外,还需要填写ngx_http_upstream_t结构体并实现3个必备的回调方法。要注意的是,这些回调方法都是由模块的编写者提供、再由upstream模块来调用的

 

(三)配置项获取

  原书例子是将访问的URL请求/test?lumia转化成对www.google.com的搜索请求/search?q=lumia。为了简化,大部分参数采用硬编码的形式nginx.conf的添加的内容和以前一样:

location /test {
    mytest;
}
typedef struct {
    ngx_http_upstream_conf_t upstream;
} ngx_http_mytest_conf_t;


static void* ngx_http_mytest_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_mytest_conf_t  *mycf;
    mycf = (ngx_http_mytest_conf_t *)ngx_pcalloc(cf->pool,sizeof(ngx_http_mytest_conf_t));
    if(mycf == NULL) {
        return NULL;
    }
    mycf->upstream.connect_timeout = 60000;
    mycf->upstream.send_timeout = 60000;
    mycf->upstream.read_timeout = 60000;
    mycf->upstream.store_access = 0600;

    mycf->upstream.buffering = 0;
    mycf->upstream.bufs.num = 8;
    mycf->upstream.bufs.size =ngx_pagesize;
    mycf->upstream.buffer_size = ngx_pagesize;
    mycf->upstream.busy_buffers_size = 2*ngx_pagesize;
    mycf->upstream.max_temp_file_size = 1024*1024*1024;

    mycf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
    mycf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
    return mycf;
}


static char* ngx_http_mytest_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_mytest_conf_t *prev = (ngx_http_mytest_conf_t *)parent;
    ngx_http_mytest_conf_t *conf = (ngx_http_mytest_conf_t *)child;
    //ngx_conf_merge_str_value(conf->my_str,prev->my_str,"defaultstr");
    ngx_hash_init_t     hash;
    hash.max_size = 100;
    hash.bucket_size = 1024;
    hash.name = "proxy_headers_hash";
    if(ngx_http_upstream_hide_headers_hash(cf,&conf->upstream,
                &prev->upstream,ngx_http_proxy_hide_headers,&hash)!=NGX_OK)
    {
        return NGX_CONF_ERROR;
    }
    return NGX_CONF_OK;
}
原书的ngx_http_mytest_create_loc_conf()和ngx_http_mytest_merge_loc_conf()

相关文章:

  • 2021-12-19
  • 2021-06-19
  • 2022-12-23
  • 2021-06-23
  • 2021-12-23
  • 2021-12-23
猜你喜欢
  • 2021-11-27
  • 2021-12-15
  • 2021-07-14
  • 2022-01-22
  • 2021-10-04
相关资源
相似解决方案