一次openrestyhttp.lua效能調優之旅
記一次openresty http.lua 效能調優之旅
1 背景
最近要用Nginx lua進行http 資料互動,因此想到了resty/http.lua,因此開啟一段效能調優之旅。
2 傳送HTTP GET請求程式碼
local ok, status, headers, code, body = hc:request {
url = uri,
method = "GET",
}
很簡單的一段程式碼,利用http.lua request 函式傳送http get 請求並返回body及相關資訊。
3 效能表現及現象
在get 小檔案的時候效能表現正常,符合預期,但是get 大檔案的時候非常慢,在內網環境下GET 1個 1M左右的Object 竟然需要1s+,這效能實在不能忍,而且隨著檔案增大效能急劇下降。開始懷疑是不是http server 的原因,用wget 試了一下,發現很快,排除server的原因。百思不得其解後開始分析http.lua 程式碼
4 http.lua 分析
這是Lua 讀取http body 程式碼,可以看出這裡有個fetch_size引數,從程式碼上看直觀含義是一次從底層網路讀上來資料塊的大小
161 local function read_body_data(sock, size, fetch_size, callback)
162 local p_size = fetch_size
163 while size and size > 0 do
164 if size < p_size then
165 p_size = size
166 end
167 local data, err, partial = sock:receive(p_size)
168 if not err then
169 if data then
170 callback(data) --這裡有個callback,下面看看是啥
171 end
172 elseif err == "closed" then
173 if partial then
174 callback(partial)
175 end
176 return 1 -- `closed`
177 else
178 return nil, err
179 end
180 size = size - p_size
181 end
182 return 1
183 end
看下fetch size 設定值是多少
nreqt.fetch_size = reqt.fetch_size or 16*1024
預設為16K
再看一下function read_body_data 在哪裡呼叫的,引數callback 傳又是什麼
185 local function receivebody(sock, headers, nreqt)
186 local t = headers["transfer-encoding"] -- shortcut
187 local body = ``
188 local callback = nreqt.body_callback
189 if not callback then
190 local function bc(data, chunked_header, ...)
191 if chunked_header then return end
192 body = body .. data
193 end
194 callback = bc
195 end
196 if t and t ~= "identity" then
197 -- chunked
198 while true do
199 local chunk_header = sock:receiveuntil("
")
200 local data, err, partial = chunk_header()
201 if not data then
202 return nil,err
203 else
204 if data == "0" then
205 return body -- end of chunk
206 else
207 local length = tonumber(data, 16)
208
209 -- TODO check nreqt.max_body_size !!
210
211 local ok, err = read_body_data(sock,length, nreqt.fetch_size, callback)
212 if err then
213 return nil,err
214 end
215 end
216 end
217 end
218 elseif headers["content-length"] ~= nil and tonumber(headers["content-length"]) >= 0 then
219 -- content length
220 local length = tonumber(headers["content-length"])
221 if length > nreqt.max_body_size then
222 ngx.log(ngx.INFO, `content-length > nreqt.max_body_size !! Tail it !`)
223 length = nreqt.max_body_size
224 end
225
226 local ok, err = read_body_data(sock,length, nreqt.fetch_size, callback)
227 if not ok then
228 return nil,err
229 end
230 else
231 -- connection close
232 local ok, err = read_body_data(sock,nreqt.max_body_size, nreqt.fetch_size, callback)
233 if not ok then
234 return nil,err
235 end
236 end
237 return body
238 end
這裡可以看到我們的程式中沒有傳callback 進去,callback 預設是
190 local function bc(data, chunked_header, ...)
191 if chunked_header then return end
192 body = body .. data -- 注意這裡會對每次接收到的body 進行拼接
193 end
194 callback = bc
分析到這裡問題已經很明顯了
fetch_size 是一次sock:receive 呼叫讀上來的body 的size,每次讀出來fetch_size 的body 後會回撥預設callback 對body 進行拼接,如果檔案size 很大而fetch size 很小就會造成因字串拼接造成的CPU資源消耗及記憶體消耗。而我們的場景是需要快取所有body後處理,所以一次讀出越多body越好。
預設Callback是
if chunked_header then return end
body = body .. data
end```
假設按照fetch size預設值16k 來算,get 1MB 檔案光string 拼接就要進行64次,所以一次性接收所有body效能最佳,fetch_size 設定為1GB。(大家都知道字串拼接需要額外記憶體分配會消耗大量CPU)
### 5 結論
fetch_size 設定太小導致大檔案body 拼接次數過多導致,從我的場景來看要快取所有body後才能進行下一步因此fetch_size 設定越大越好
修正後程式碼為:
url = uri,
fetch_size = 1024*1024*1024,
method = "GET",
}```
注意:如果你的業務場景是需要流式處理或者轉發這個值只需要將fetch_size 調整為一個合適的值即可。
相關文章
- 一次效能測試調優總結
- 一次效能優化調整過程.優化
- python效能調優的一次記錄Python
- 一次效能壓測及分析調優實踐
- 記一次 Laravel 應用效能調優經歷Laravel
- Spark 效能調優--資源調優Spark
- Spark 效能調優--Shuffle調優 SortShuffleManagerSpark
- 一次 kafka 消費者的效能調優過程Kafka
- 【效能調優】效能測試、分析與調優基礎
- ElasticSearch效能調優Elasticsearch
- Nginx 效能調優Nginx
- iOS效能調優iOS
- php效能調優PHP
- Java效能調優Java
- Spark效能調優Spark
- oracle效能調優Oracle
- 一次移動優化之旅(二)優化
- 效能調優學習之硬體調優
- 效能調優實戰
- 效能調優 jstackJS
- MySQL 效能調優技巧MySql
- RedHat 效能調優指南Redhat
- Spark的效能調優Spark
- Oracle 效能調優 概述Oracle
- weblogic效能調優Web
- Kafka 線上效能調優Kafka
- 效能監控調優
- Nginx安全優化與效能調優Nginx優化
- JVM 效能調優實戰之:一次系統效能瓶頸的尋找過程JVM
- 淺談Nginx效能調優Nginx
- linux調優效能命令Linux
- Java效能調優準則Java
- sqlldr效能調優測試SQL
- Mysql 效能調優 一 1MySql
- Mysql 效能調優 一 2MySql
- Mysql 效能調優 一 3MySql
- Mysql 效能調優 二 1MySql
- Mysql 效能調優 二 2MySql