問題
后臺是 云服務器 ECS + Nginx + PHP 。服務器配置比較低好像是2核4GB,后臺提供接口,供前臺Node.js和路由器插件(小米,極路由等)以及安卓客戶端調(diào)用。
路由器插件端和安卓客戶端的一個邏輯就是要請求后臺獲取 sn,再通過sn做其它操作。那么如果獲取不到 sn 的時候,就會 10s 之后繼續(xù)請求,這就是問題的根源。
產(chǎn)品剛剛上線,大約有兩萬臺小米路由器設(shè)備于凌晨4點鐘重啟,不斷地請求獲取 sn 接口。后臺就掛了, Nginx 502 bad gateway, PHP-FPM 進程數(shù)過多。
路由器插件在用戶端,并不能做任何修改,只能是在后臺優(yōu)化使其能接受 20K 的 QPS。
為什么選擇 OenResty
可以搭負載均衡,但是當前只是單個接口訪問量特別高,單個服務器的性能并沒有發(fā)揮到極致。
后來我就發(fā)現(xiàn)了 OpenResty ,可以用這個嘗試下,然后我們先看下官網(wǎng)的描述??梢苑奖愕卮罱ㄌ幚沓卟l(fā),看起來是我想要的。
OpenResty是一個基于與 Lua 的高性能 Web 平臺,其內(nèi)部集成了大量精良的 Lua 庫、第三方模塊以及大多數(shù)的依賴項。用于方便地搭建能夠處理超高并發(fā)、擴展性極高的動態(tài) Web 應用、Web 服務和動態(tài)網(wǎng)關(guān)。
OpenResty 開發(fā)
OpenResty學習的話推薦一本小冊子 OpenResty 最佳實踐,講的很好。
有以下要注意的幾個點:
- Lua 的 數(shù)字都是 float 型,不能直接和字符串做比較。那么從 URL 接受的值要執(zhí)行數(shù)字相關(guān)操作的話,就要先將其轉(zhuǎn)為數(shù)字
local page = tonumber(arg['page'])
- Lua 中執(zhí)行 sql 查詢出來就是 table ,查詢出來就是多條數(shù)據(jù)的形式。并且其下標都是從1開始的。
local id = 1000
res, err, errno, sqlstate = db:query(
string.format([[select name from user where id = %d ]], id)
)
if not res then
ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
return
else
name = res[1]['name']
ngx.say("name is ", name)
end
我最難受的是OenResty 中的調(diào)試只能是通過 Nginx 的 error.log,每次出了問題都要看日志。可能是我現(xiàn)在還不知道 OpenResty 如何開發(fā)才是最合適的,如果你有更好的方式一定要告訴我。
總結(jié)
如果是某些簡單的業(yè)務,可以用 Lua 重寫,可以極大提高性能,快來體驗下吧。