为啥须要?在理论开发中咱们常常会遇到须要长时间期待后盾事件的状况,例如较为常见的扫码登录性能,二维码界面需期待后盾扫码登录胜利的事件,再如导入导出等须要较长时间能力解决实现的工作,此时须要把工作放到后盾由异步工作进行解决,实现后再给前台界面推送实现事件,以上需要咱们须要用长连贯能力实现推送,但长连贯推送状态治理简单,且须要部署独立零碎,零碎流程简单且横向程度扩大艰难,此时抉择更简略long polling期待是一个更好的抉择,http申请间接期待返回,显然逻辑更简略,可用性可维护性也会更高。
openresty是一个构建在nginx上的高性能能零碎,个别状况下咱们也须要在本身服务前部署nginx作为网关,那么抉择openresty来构建一个高性能的long polling服务显然是一个好抉择。slock是高性能的状态及原子操作数据库,redis则是高性能的内存缓存数据库,应用下边nginx配置文件即可疾速基于slock和redis构建一个高性能高可用long polling服务。同时构建的此long polling服务是一个通用服务,即可用于扫码登录这样的需要实现状态推送,也可用于像音讯零碎、私信零碎等的音讯推送。
slock我的项目地址:https://github.com/snower/slock
slock简介可看:https://segmentfault.com/a/11...
疾速配置构建首先需在装置好的openresty服务中装置slock的lua client包。
我的项目地址:https://github.com/snower/slo...
装置形式即把slock-lua-nginx中slock.lua复制到openresty目录中的lualib/中,而后增加以下nginx配置文件批改相干参数即可。
init_worker_by_lua_block { local slock = require "slock" slock:connect("server1", "127.0.0.1", 5658)}server { listen 8081; default_type application/json; location /poll/event { content_by_lua_block { local cjson = require "cjson" local slock = require "slock" local slock_client = slock:get("server1") local default_type = ngx.var.arg_default_type or "clear" local wait_type = ngx.var.arg_wait_type or "" local event_key = ngx.var.arg_event or "" local wait_timeout = tonumber(ngx.var.arg_timeout) or 60 local sendResult = function(err_code, err_message) ngx.say(cjson.encode({ err_code = err_code, err_message = err_message, })) end if event_key == "" then return sendResult(400, "event key is empty") end local event = nil if default_type == "set" then event = slock_client:newDefaultSetEvent(event_key, 5, wait_timeout * 2) else event = slock_client:newDefaultClearEvent(event_key, 5, wait_timeout * 2) end if wait_type == "reset" then local ok, err = event:waitAndTimeoutRetryClear(wait_timeout) if not ok then return sendResult(504, "wait event timeout") end return sendResult(0, "succed") end local ok, err = event:wait(wait_timeout) if not ok then return sendResult(504, "wait event timeout") end return sendResult(0, "succed") } } location /poll/message { content_by_lua_block { local cjson = require "cjson" local redis = require "resty.redis" local slock = require "slock" local redis_client = redis:new() local slock_client = slock:get("server1") local default_type = ngx.var.arg_default_type or "clear" local wait_type = ngx.var.arg_wait_type or "" local event_key = ngx.var.arg_event or "" local wait_timeout = tonumber(ngx.var.arg_timeout) or 60 local sendResult = function(err_code, err_message, data) ngx.say(cjson.encode({ err_code = err_code, err_message = err_message, data = data, })) end if event_key == "" then return sendResult(400, "event key is empty") end redis_client:set_timeouts(5000, wait_timeout * 500, wait_timeout * 500) local ok, err = redis_client:connect("10.10.10.251", 6379) if not ok then return sendResult(502, "redis connect fail") end local message, err = redis_client:lpop(event_key) if err ~= nil then return sendResult(500, "redis lpop fail") end if message ~= ngx.null then redis_client:set_keepalive(7200000, 16) return sendResult(0, "", message) end local event = nil if default_type == "set" then event = slock_client:newDefaultSetEvent(event_key, 5, wait_timeout * 2) else event = slock_client:newDefaultClearEvent(event_key, 5, wait_timeout * 2) end if wait_type == "reset" then local ok, err = event:waitAndTimeoutRetryClear(wait_timeout) if not ok then return sendResult(504, "wait timeout") end local message, err = redis_client:lpop(event_key) if err ~= nil then return sendResult(500, "redis lpop fail") end redis_client:set_keepalive(7200000, 16) return sendResult(0, "succed", message) end local ok, err = event:wait(wait_timeout) if not ok then return sendResult(504, "wait timeout") end local message, err = redis_client:lpop(event_key) if err ~= nil then return sendResult(500, "redis lpop fail") end redis_client:set_keepalive(7200000, 16) return sendResult(0, "succed", message) } }}/poll/event 接口只期待事件触发,不返回数据。
...