Hello!
2014-02-16 23:21 GMT-08:00 Harold.Miao:
> ngx从后端取一些比较大的文件,ngx跟后端速率很高。 前端由于网络环境下载速度波动很大(但总体上比后端速率要小很多很多) 。
>
> 如果从后端拿来的数据不能及时下载到客户端,就会导致内存拥堵 (对于下载小文件来说cache缓存可以,但是对于大文件(1G以上)却导致内存暴涨)
>
你这里需要使用严格的非缓冲处理(或者说流式处理)。即总是确保上游和下游速率保持一致,从而确保你的内存使用量是一个常数,而不论数据流本身的总长度有多长。
这在 ngx_lua 中是非常容易实现的,可以通过下面这个伪代码示例来演示:
while true do
-- read a data chunk from upstream (via cosocket, for example)
local chunk, err = get_data_chunk_from_upstream()
if not chunk then
if not err then
-- end of data stream
ngx.eof()
break
end
ngx.log(ngx.ERR, "failed to get a chunk from upstream: ", err)
return ngx.exit(ngx.ERROR)
end
-- write the data chunk to the downstream:
local ok, err = ngx.print(chunk)
if not ok then
ngx.log(ngx.ERR, "failed to write data to downstream: ", err)
return ngx.exit(ngx.ERROR)
end
-- wait nonblockingly until the chunk is completely flushed out
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "failed to flush data to downstream: ", err)
return ngx.exit(ngx.ERROR)
end
end
> 所以需要动态知道下载速率以调整ngx跟后端的速率(具体就是调用ngx.sleep()睡眠)。
>
不要用 ngx.sleep(),因为它会引入不必要的额外的延时。在上面那个 例子里,我使用 ngx.flush(true)
来等待当前的块全部被写出。一旦当前数据全刷进系统发送缓冲区之后,ngx.flush 就会立即返回。所以这种方式要高效得多。
> 请教 ngx_lua能动态获取下载和后端速率吗? 获取两个速率变量再做个自适应算法这种方案靠谱吗?
>
这里根本不用这么麻烦。见上面那个实现严格流式数据代理的 Lua 循环 :)
Regards,
-agentzh