特性
- 使用連接池
項目源碼
https://github.com/helloJiu/o...
代碼
-- http客户端
-- https://github.com/ledgetech/lua-resty-http
local http = require("resty/http")
local config = {
max_idle_time = 30000,
pool_size = 1000,
timeout = 5000,
backlog = 1000
}
local _M = {}
function _M.new()
local instance = {
timeout = config.timeout or 5000,
max_idle_time = config.max_idle_time or 60000,
pool_size = config.pool_size or 1000,
backlog = config.backlog or 1000,
}
setmetatable(instance, { __index = _M })
return instance
end
function _M:exec(options, func)
local httpc = http:new()
-- Sets the socket timeout (in ms) for subsequent operations.
httpc:set_timeout(self.timeout)
-- https://github.com/openresty/lua-nginx-module#tcpsockconnect
-- pool_size 指定連接池的大小。
-- 如果省略且未 backlog提供任何選項,則不會創建任何池。如果省略但backlog已提供,
-- 則將使用等於lua_socket_pool_size 指令的值的默認大小創建池。
-- 連接池可容納可供pool_size後續調用connect重用的活動連接,
-- 但請注意,池外打開的連接總數沒有上限。如果您需要限制打開的連接總數,
-- 請指定backlog選項。當連接池超過其大小限制時,
-- 池中最近最少使用(保持活動)的連接將被關閉,以為當前連接騰出空間。請注意,
-- cosocket 連接池是每個 Nginx 工作進程而不是每個 Nginx 服務器實例,
-- 因此此處指定的大小限制也適用於每個 Nginx 工作進程。
-- 另請注意,連接池的大小一旦創建就無法更改。此選項首次在v0.10.14發行版中引入。
options.pool_size = self.pool_size
-- backlog 如果指定,此模塊將限制此池的打開連接總數。
-- pool_size任何時候都不能為此池打開更多的連接。
-- 如果連接池已滿,後續連接操作將排入與此選項值相等的隊列(積壓隊列)。
-- 如果排隊的連接操作數等於backlog,後續連接操作將失敗並返回nil錯誤字符串"too many waiting connect operations"。
-- 一旦池中的連接數小於 ,排隊的連接操作將恢復pool_size。
-- 排隊的連接操作將在排隊超過 時中止connect_timeout,由 settimeouts控制,並返回nil錯誤字符串。
-- "timeout". 此選項首次在v0.10.14發行版中引入。
options.backlog = self.backlog
options.ssl_verify = false
local ok, err = httpc:connect(options)
if not ok then
ngx.log(ngx.ERR, "http connect, err:", err)
return nil, err
end
-- 執行業務邏輯
local res, err = func(httpc)
if not res then
ngx.log(ngx.ERR, "http request, err:", err)
return nil, err
end
-- 讀取響應體
local res_body = ""
if res.status == 200 and res.has_body then
local reader = res.body_reader
local buffer_size = 4096
repeat
local buffer, err = reader(buffer_size)
if err then
ngx.log(ngx.ERR, "reader err", err)
break
end
if buffer then
res_body = res_body .. buffer
end
until not buffer
end
-- 將連接放回連接池
local ok = httpc:set_keepalive(self.max_idle_time, self.pool_size)
if not ok then
httpc:close()
end
-- 返回響應體 響應 以及err
return res_body, res, err
end
return _M
實際使用
local http = require("http")
local path = string.format("/cgi-bin/qrcode/create?access_token=%s", "accessToken")
local httpi = http.new()
local options = {
scheme = "https",
host = "api.weixin.qq.com",
port = "443",
}
local scene_str = "abc"
local body = {
expire_seconds = 3600*24,
action_name = "QR_SCENE",
action_info = {
scene = {
scene_str = scene_str
}
}
}
local resBody, res, err = httpi:exec(options, function(httpc)
return httpc:request({
method = "POST",
path = path,
body = json.encode(body),
headers = {["Content-Type"] = "application/json",},
})
end)
if not res then
ngx.log(ngx.ERR, "=============>send message request failed: ", err)
return nil
end
log.notice(resBody)