Nginx系列(十七):HTTP subrequest子请求

一个主请求无论产生多少子请求,epoll中始终只包含一个连接的写事件,当该连接的可写事件触发时,该连接所有父子请求都会被处理一遍。c->data 始终指向后序遍历的首个节点位置。顺序从下往上,从左往右,即先产生的子请求要求先发送。
在这里插入图片描述

一、子请求建立
  • ngx_http_subrequest
    r->postponed:该请求子请求和已产生数据的树状结构。
    r->posted_requests:单链表,保存所有需要被处理的父子请求。
    sr->read_event_handler:子请求的读回调,为空。
    sr->write_event_handler:子请求的写回调,初始化为ngx_http_handler。
二、子请求处理

连接epoll触发(ngx_http_request_handler)->当前请求c->data处理(r->write_event_handler)->其它请求处理(ngx_http_run_posted_requests)
其它请求处理一次后,就被从posted_requests单链表中删除,后续只能等待c->data改变时,请求被重新添加到posted_requests链表中时才会被再次处理。
产生子请求时,c->data已被置为子请求,且posted_requests中没有子请求,所以即使c的写事件触发,父请求也始终不会被处理,直至所有子请求全部被处理,处理权c->data被重新设置为父请求。

三、子请求数据发送
  • . ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
    • 当前处理的请求非拥有发送权利的节点(c->data)
      创建pp,保存数据,挂在当前请求pp队列末尾;
    • 当前处理的请求为拥有发送权利的节点(c->data)
      (1)当前处理的请求没有子请求或已产生数据,直接发送数据;
      (2)当前处理的请求有子请求或已产生数据:
      数据:发送已产生数据和当前数据;
      子请求:设置c->data为该请求,并将该请求加入posted_requests链表,使其获得一次运行的机会。理论上c->data始终指向拥有发送权利的节点,为什么还会出现c->data产生数据时,它还存在子请求的情况?因为某个子请求结束后,c->data会首先指向父请求,在这里,会将优先发送权c->data重新赋给子请求。
四、子请求结束

ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)

  • 当前处理的请求为c->data
    (1)从r的父请求的postponed中删除r;
    (2)将发送权利 c->data交给r的父请求,即使父请求还存在其它子请求,原因见上述灰色部分;
  • 当前处理的请求非c->data
    到这里其实表明该子请求提前执行完成,则它下次再次获得 执行机会时,将会执行ngx_http_request_finalzier函数,它实际上是执行 ngx_http_finalzie_request(r,0),也就是什么都不干,直到c->data重新设置为它,调用ngx_http_set_write_handler使其获得发送的机会,并在ngx_http_writer中重新转移发送权利c->data。
  • 将父请求重新挂至posted_request队尾,获得一次重新运行的机会。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值