Hello!
2012/11/25 fengmo.q wrote:
> 你之前fd0a8fb182f045f9e71018dd8031730fa70f3d5f (refactor: now ngx_lua issues
> subrequests without updating r->postpone)这个commit的作用是什么?
这个 commit 的作用是建立 ngx_lua 自己的新的子请求模型。这个模型和 Nginx 核心中的子请求模型的主要区别是,
1. 当有多个子请求仍在运行中时,父请求可以立即输出数据而不致被 r->postpone 强行缓冲;
2. 各个子请求的输出可以像 Facebook Pigpipe 那样无序输出,而不同于 Nginx 经典的子请求模型强制子请求的输出顺序与子请求的发起顺序一致。
ngx_lua 模块的 ngx.thread 轻量级线程 API 与
ngx.location.capture/ngx.location.capture_multi 的兼容性也完全依赖于新的子请求模型。
在我看来,Nginx 现有的子请求模型算是一个 dead end 了.
> 看起来是有点问题的,在subrequest的post
> handler里面强行的将r->connection->data赋值给当前的子请求,这样对于ssi这种模块同时并发发出2个以上的子请求(假设为S1,S2,),S1调用一个包含content_by_lua的location,lua代码都调用了capture接口产生子请求S11,S2调用另一个包含conetent_by_lua的location,lua代码都调用了capture接口产生子请求S21。运行序列上来说,S1执行中产生S11;接着运行S2产生S21;接着运行S11,S11执行完调用post
> handler,将数据保存在S1上,将connection->data设置为S11,post
> handler执行完在finalize_request中connect->data又被设置为S11的父请求也就是S1;接着运行S21,类似S11,S21执行完之后,由于在post
> handler中connction->data被强制设置为S21,导致在finalize_request中connction->data被传递给S21的父请求S2;接着运行S1,此时S1本应该输出数据了,但是connction->data被设置为了S2,导致S1不会输出数据;接着执行S2,由于connction->data为S2,所以S2往外输出了数据,并将connection->data传递给S2的父请求也就是主请求;...最后直到主请求执行把connection->data传递给S1,S1才能往外输出数据。
> 这里就导致了数据乱序。另外这里仅仅是2层,4个子请求,如果更复杂的情况下,可能导致更混乱的结果。
> 不知道这里你不更新r->postpone的目的是什么?
ngx_lua 的子请求并没有设计成与经典的 Nginx 子请求模型一起工作。所以当使用 SSI 子请求访问配置了 ngx_lua 的
location,同时又在 ngx_lua 的 location 中发起新的(孙)子请求,绝对是一个坏主意 :)
两个建议:
1. 把 SSI 层直接取消掉,而换用纯粹的 ngx_lua 子请求模型,或者
2. 在 ngx_lua 层中避免使用子请求,而改用 cosocket 来进行 I/O 通信。
Best regards,
-agentzh