天天看點

OpenResty與Lua實作高并發請求處理

OpenResty與Lua實作高并發請求處理

前言

官網:

http://openresty.org/cn/

介紹

OpenResty 是一個基于 Nginx 與 Lua 的高性能 Web 平台,其内部內建了大量精良的 Lua 庫、第三方子產品以及大多數的依賴項。用于友善地搭建能夠處理超高并發、擴充性極高的動态 Web 應用、Web 服務和動态網關。由中國人張亦春發起,提供了很多高品質的第三方子產品。

OpenResty 通過彙聚各種設計精良的 Nginx 子產品(主要由 OpenResty 團隊自主開發),進而将 Nginx 有效地變成一個強大的通用 Web 應用平台。這樣,Web 開發人員和系統工程師可以使用 Lua 腳本語言調動 Nginx 支援的各種 C 以及 Lua 子產品,快速構造出足以勝任 10K 乃至 1000K 以上單機并發連接配接的高性能 Web 應用系統。

OpenResty 的目标是讓你的Web服務直接跑在 Nginx 服務内部,充分利用 Nginx 的非阻塞 I/O 模型,不僅僅對 HTTP 用戶端請求,甚至于對遠端後端諸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都進行一緻的高性能響應。

配置

安裝 OpenResty 軟體後,因為 OpenResty 基于 Nginx 開發,是以配置 OpenResty 隻需要配置 Nginx 即可。

在 OpenResty 安裝目錄下配置 nginx

# nginx 攔截 /update_context 請求,交給 lua 腳本處理
location /update_context {
    content_by_lua_file /root/lua/update_content.lua
}
location /get_context {
    content_by_lua_file /root/lua/get_content.lua
}      

Lua 腳本

lua redis 腳本參考:

https://github.com/openresty/lua-resty-redis

lua mysql 腳本參考:

https://github.com/openresty/lua-resty-mysql

update_content.lua 腳本

ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")
local mysql = require("resty.mysql")
-- 擷取使用者的請求參數
local uri_args = ngx.req.get_uri_args()
-- 擷取請求參數中的 id
local id = uri_args["id"]
-- 連接配接 mysql
local db = mysql:new()
db:set_timeout(1000)
local props = {
    host = "192.168.8.4",
    port = 3306,
    database = "changgou_content",
    user = "root",
    password = "123456"
}
-- 查詢mysql
local res = db:connect(props)
local select_sql = "select url,pic from tb_content where status = '1' and category_id =" ..id.." order by sort_order"
res = db:query(select_sql)
db:close()
-- 連接配接redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000)
local ok, err = red:connect("192.168.8.4", 6379)
if not ok then
    ngx.say("failed to connect: ", err)
    return
end
red:set("content_"..id, cjson.encode(res))
red:close()
ngx.say("{flag:true}")      

get_content.lua 腳本

ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")
local mysql = require("resty.mysql")
local uri_args = ngx.req.get_uri_args()
local id = uri_args["id"]
-- 擷取nginx緩存資料,如果沒有從redis中擷取
-- 需要定義 ngx.shared.dis_cache 子產品,lua 緩存命名空間(dis_cache)
local cache_ngx = ngx.shared.dis_cache;
local contentCache = cache_ngx:get("content_"..id)
if contentCache == "" or contentCache == nil then
    ngx.say("contentCache not found ")
else
    ngx.say(contentCache)
    return
end
-- 連接配接redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000)
local ok, err = red:connect("192.168.8.4", 6379)
if not ok then
    ngx.say("failed to connect: ", err)
    return
end
-- 從 redis 中擷取資料
local res, err = red:get("content_"..id)
if not res then
    ngx.say("failed to get content_"..id, err)
    return
end
if res == ngx.null then
    ngx.say("content_"..id.." not found.")
    -- redis緩存中沒有連接配接資料庫查詢,并放入redis緩存中
    local db = mysql:new()
    local props = {
        host = "192.168.8.4",
        port = 3306,
        database = "changgou_content",
        user = "root",
        password = "123456"
    }
    local ok, err, errcode, sqlstate = db:connect(props)
    if not ok then
        ngx.say("failed to connect: ", err, ": ", errcode, " ", sqlstate)
        return
    end
    ngx.say("connected to mysql.")
   
     local select_sql = "select url,pic from tb_content where status = '1' and category_id =" ..id.." order by sort_order"
    local res, err, errcode, sqlstate = db:query(select_sql)
    if not res then
        ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
        return
    end
    -- 設定緩存到 nginx 中, 10*60: 10分鐘
    cache_ngx:set("content_"..id, res, 10*60)
    -- 存入緩存到 redis 中
    red:set("content_"..id, cjson.encode(res))
    -- 輸出
    ngx.say("content_"..id, cjson.encode(res))
    db:close()
    return
end
-- 設定緩存到 nginx 中
cache_ngx:set("content_"..id, res, 10*60)
ngx.say("content_"..id, res)
red:close()      

定義 ngx.shared.dis_cache 子產品 ,需要在 nginx 配置檔案中的 http 子產品下添加

# 定義 lua 緩存命名空間(dis_cache)及其大小(128m)
lua_shared_dict dis_cache 128m;      

如圖

OpenResty與Lua實作高并發請求處理

繼續閱讀