預設情況下, ngx.say和ngx.print都是非同步輸出的,先來看乙個例子:
location /test
}
執行測試,可以發現首先, /test 響應內容是在觸發請求 3s 後一起接收到響應體,第乙個ngx.say好像是被「繞過」,先執行sleep,然後和最後乙個ngx.say的內容一起輸出。
location /test
}
首先輸出"hello",然後停頓3秒,最後輸出"the world"——正如我們想象的那樣。ngx.flush執行顯示的輸出,前乙個ngx.say被「阻塞」住,執行完輸出後方往下執行。
再看乙個例子:
server }}
這個例子和第乙個例子相比,唯一不同就是ngx.say輸出內容長了不少,我們發現瀏覽器先收到所有的hello,接著又收到了"the world" 。然而如果我們把4000改為小一點的值如2000(不同配置這個相對大小或有不同),那麼仍然會出現先停頓3s,然後所有"hello"連同最後"the world"一起輸出的情況。
通過以上三個例子,我們可以得出下面的結論:
ngx.say和ngx.print的同步和非同步
ngx.flush的同步和非同步
lua-nginx也提到了ngx.flush的同步和非同步。某乙個ngx.say或者ngx.print呼叫後,這部分輸出內容會寫到輸出緩衝區,同步的方式ngx.flush(true)會等到內容全部寫到緩衝區再輸出到客戶端,而非同步的方式ngx.flush()會將內容一邊寫到緩衝區,而緩衝區則一邊將這些內容輸出到客戶端。
openresty和nginx流式輸出的比較
proxy_buffering on;
proxy_buffer_size 4k|8k;
proxy_buffers 8 4k|8k;
proxy_busy_buffers_size 8k|16k;
proxy_temp_path proxy_temp;
openresty的怎麼做到過大響應的輸出呢? 《openresty 最佳實踐》 提到了兩種情況:
輸出內容本身是由各種碎片拼湊的,碎片數量龐大
if k ~= "transfer-encoding" then --必須刪除上游transfer-encoding響應頭
ngx.header[k] = v
endend-- response body
local reader = res.body_reader
repeat
local chunk, err = reader(8192)
if err then
ngx.log(ngx.err, err)
break
endif chunk then
ngx.print(chunk)
ngx.flush(true) -- 開啟ngx.flush,實時輸出
end多達10w+的"碎片"的頻繁的呼叫ngx.pirnt()和ngx.flush(true),使得cpu不堪重負,出現了以下的問題:
這是開啟了ngx.flush(true)的情況(ngx.flush()時差別不大),如果不開啟flush同步模式,則情況會更糟糕。cpu幾乎一直維持在100%左右:
可見,在碎片極多的流式傳輸上,以上官方所推薦的openresty使用方法效果也不佳。
於是,回到nginx的upstream模組,改content_by_lua_file為proxy_pass再做測試,典型的資源使用情況為:
因此結論是,涉及到大輸出或者碎片化響應的情況,最好還是採用nginx自帶的upstream方式,簡單方便,精確控制。而openresty提供的幾種方式,無論是非同步的ngx.say/ngx.print還是同步的ngx.flush,實現效果都不理想。
OpenResty安裝 配置與使用
openresty 是乙個基於 nginx 與 lua 的高效能 web 平台,其內部整合了大量精良的 lua 庫 第三方模組以及大多數的依賴項。用於方便地搭建能夠處理超高併發 擴充套件性極高的動態 web 應用 web 服務和動態閘道器。lua是乙個簡潔 輕量 可擴充套件的程式語言,其設計目的是為...
OpenResty之指令與常用API
通過 lua 編寫 nginx 指令碼的基本構建塊是指令。指令常用於指定 lua 是幾時執行的以及如何使用執行的結果。下圖展示了指令執行的順序。語法 lua capture error log size 預設 none 上下文 http 啟用乙個指定大小的緩衝區來捕獲所有的 nginx 錯誤日誌,而...
OpenResty安裝與常見問題處理
一.安裝lua curl r o tar zxf lua 5.3.5.tar.gz cd lua 5.3.5 make linux test如果報錯 執行 yum install libtermcap devel ncurses devel libevent devel readline devel...