设为首页 收藏本站
查看: 574|回复: 0

[经验分享] nginx module开发利器:subrequest

[复制链接]

尚未签到

发表于 2016-12-24 08:39:01 | 显示全部楼层 |阅读模式
  nginx是个高性能web server,很多时候我们会把它当成reverse proxy或者web server container使用,但有时我们也会开发它的第三方module,因为module才能完全使用nginx的全事件驱动、无阻塞调用机制,充分使用系统资源,达到SERVER最大处理吞吐量。
  

  在开发nginx module时,我们最有可能遇到的一件事就是,在处理一个请求时,我们需要访问其他多个backend server网络资源,拉取到结果后分析整理成一个response,再发给用户。这个过程是无法使用nginx upstream机制的,因为upstream被设计为用来支持nginx reverse proxy功能,所以呢,upstream默认是把其他server的http response body全部返回给client。这与我们的要求不符,这个时候,我们可以考虑subrequest了,nginxhttp模块提供的这个功能能够帮我们搞定它。
  

  先看看subrequest调用函数长什么样:
ngx_int_tngx_http_subrequest(ngx_http_request_t *r,ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
挨个分析下参数吧。r是我们的module handler中,nginx调用时传给我们的请求,这时我们直接传给subrequest即可。uri和args是我们需要访问backend server的URL,而psr是subrequest函数执行完后返回给我们的新请求,即将要访问backend server的请求指针。ps指明了回调函数,就是说,如果这个请求执行完毕,接收到了backend server的响应后,就会回调这个函数。flags会指定这个子请求的一些特征。  看看ngx_http_post_subrequest的结构:
typedef struct {ngx_http_post_subrequest_pt       handler;void                             *data;} ngx_http_post_subrequest_t;
这里的handler你可以指向一个函数,这个函数会在这个子请求结束以后被nginx调用,这时传给函数的request是子请求,不是原始的父请求哈。  

  而flag我们一般只会感兴趣下面这个NGX_HTTP_SUBREQUEST_IN_MEMORY,flag设为这个宏时,表示发起的子请求,访问的网络资源返回的响应将全部放在内存中,我们可以从upstream->buffer里取到响应内容。所以这里如果用了这个flag,一定要确保返回内容不可以很大,例如不能去下载一个大文件。
  

  所以,当我们写nginx的module时,需要去拉取某个网络资源,就可以这么写:
    ngx_http_post_subrequest_t          *psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));if (psr == NULL) {return NGX_HTTP_INTERNAL_SERVER_ERROR;}psr->handler = ngx_http_my_post_subrequest;psr->data = ctx;ngx_flag_t flag = NGX_HTTP_SUBREQUEST_IN_MEMORY ngx_str_t sub_location = ngx_string("/testlocation");ngx_str_t sub_args = ngx_string("para=1");;rc = ngx_http_subrequest(r, &sub_location, &url_args, &sr, psr, sr_flag);
这样,在这个subrequest执行完后,将会调用ngx_http_my_post_subrequest方法,再次注意,此时传给你的ngx_http_request_t上下文是子请求的,不是原始的父请求,所以,如果你需要在父请求的上下文中处理这个请求,可以在ngx_http_my_post_subrequest中找到父请求的handler,设置为一个处理函数即可。比如:ngx_http_request_t          *pr = r->parent;pr->write_event_handler = ngx_http_parent_handler;
这样,这个ngx_http_my_post_subrequest执行完毕后,nginx开始换醒父请求,这时ngx_http_parent_handler将会被调用。  

  最后我们要注意,一个请求中,我们只能调用一次subrequest,不能一次生成多个subrequest。我们可以在儿子请求中再创建孙子请求,一直下去都行,但是不能一次创建多个子请求。为什么呢?因为nginx本身的设计就是,每处理完一个事件后,将会检查有没有它对应的一个post事件(一对一),如果有则处理。上面的subrequest就是用这个流程的。如果一个请求中我们想同时生成多个子请求,就不能用subrequest了,我们必须自己创建nginx事件来处理了。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-318614-1-1.html 上篇帖子: nginx的会话保持 下篇帖子: Nginx IP Hash一点记录
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表