openresty

./configure -j2 --prefix=/usr/local/ --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-http_stub_status_module --add-module=/opt/nginx/nginx-rtmp-module-master --with-stream --with-stream_ssl_module


./configure -j2 --prefix=/usr/local/ --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module --add-module=/opt/nginx/nginx-rtmp-module-master --with-stream --with-stream_ssl_module


external

lua-nginx-module

GitHub - openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers

lua-resty-http

lua-resty-http

lua-resty-upload

lua-resty-upload

lua-resty-string

lua-resty-string

lua-resty-kafka

lua-resty-kafka


-- kafka
local ngx = require "ngx"
local cjson = require "cjson"
local client = require "resty.kafka.client"
local producer = require "resty.kafka.producer"

ngx.header['Content-Type']="application/json"

local broker_list = { 
    {host = "localhost", port = "9092"}
}

local key = "ngx.log"
--local message = "hello world"
--

local message = { 
    msg = "his is a message.",
    timestamp = os.time(),
    id = 1,
}

local cli = client:new(broker_list)

local brokers, partitions = cli:fetch_metadata(key)
if not brokers then
    ngx.say(cjson.encode({msg = "fetch_metadata failed, err: " .. partitions}))
end
metadata = { 
    brokers = brokers,
    partitions = partitions
} 
ngx.log(ngx.ERR, cjson.encode(metadata))

local p = producer:new(broker_list, { producer_type = "async"})

local ok, err = p:send(key, "123", cjson.encode(metadata))
if not ok then 
    ngx.say(cjson.encode({msg="send err: " .. err}))
end
ngx.say(cjson.encode({msg="success"}))

lua-resty-oss

lua-resty-oss

lua-resty-redis

lua-resty-redis

resty-redis-cluster

resty-redis-cluster

headers-more-nginx-module

headers-more-nginx-module

lua-resty-lock

lua-resty-lock


tips

no resolver defined to resolve "xxx.oss-cn-shenzhen.aliyuncs.com"

需要在nginx中配置 resolver: 8.8.8.8;

cjson处理url地址会转义 / -> /

  • 案例
local cjson = require("cjson")
print(cjson.encode({url="http://www.baidu.com"}))
output:
{"url":"http:\/\/www.biau.com"}
  • 修改cjson源码,重新编译openresty.
    openresty-xx/bundle/lua-cjson-xx/lua_cjson.c
    搜索 char2escape 修改字符:
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\/",
最后一个字符替换为:
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,

request/response headers

-- req
local xfid = ngx.req.get_headers()['X-F-ID']

local headers,err = ngx.req.get_headers()
ngx.log(ngx.INFO, cjson.encode(headers))

-- resp
-- 1
ngx.header['X-F-ID'] = "x-f-id"

-- 2
local ngx_resp = reuqire 'ngx.resp'
ngx_resp.add_header('X-F-ID', 'x-f-id')

文件上传

local

# nginx.conf
# 存储路径
set $store_dir "/opt/temp/upload/";
client_max_body_size 50m;
location /upload/local {
    content_by_lua_file conf/lua/upload-local.lua;
}
-- upload-local.lua
--==========================================
-- 文件上传本地文件系统
--==========================================
local upload = require "resty.upload"
local cjson = require "cjson"
local resty_md5 = require "resty.md5"
local resty_string = require "resty.string"

ngx.header['Content-Type'] = "application/json"

local chunk_size = 4096
local form, err = upload:new(chunk_size)
if not form then
    ngx.log(ngx.ERR, "failed to new upload: ", err)
    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
form:set_timeout(1000)
-- 字符串 split 分割
string.split = function(s, p)
    local rt= {}
    string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end )
    return rt
end
-- 支持字符串前后 trim
string.trim = function(s)
    return (s:gsub("^%s*(.-)%s*$", "%1"))
end
-- 文件保存的根路径
local saveRootPath = ngx.var.store_dir
-- 保存的文件对象
local fileToSave
--文件是否成功保存
local ret_save = false

local response = {}

local md5 = resty_md5:new()

while true do
    local typ, res, err = form:read()
    if not typ then
        ngx.say("failed to read: ", err)
        return
    end
    if typ == "header" then
        -- 开始读取 http header
        -- 解析出本次上传的文件名
        local key = res[1]
        local value = res[2]
        if key == "Content-Disposition" then
            -- 解析出本次上传的文件名
            -- form-data; name="testFileName"; filename="testfile.txt"
            local kvlist = string.split(value, ';')
            for _, kv in ipairs(kvlist) do
                local seg = string.trim(kv)
                if seg:find("filename") then
                    local kvfile = string.split(seg, "=")
                    local filename = string.sub(kvfile[2], 2, -2)
                    if filename then
                        response.path = saveRootPath .. filename
                        fileToSave = io.open(saveRootPath .. filename, "w+")
                        if not fileToSave then
                            ngx.say("failed to open file ", filename)
                            return
                        end
                        break
                    end
                end
            end
        end
    elseif typ == "body" then
        -- 开始读取 http body
        if fileToSave then
            fileToSave:write(res)
            md5:update(res)
        end
    elseif typ == "part_end" then
        -- 文件写结束,关闭文件
        if fileToSave then
            response.size= fileToSave:seek("end")
            fileToSave:close()
            fileToSave = nil
        end
        -- md5
        local digest = md5:final()
        md5:reset()
        response.md5 = resty_string.to_hex(digest)
        ret_save = true
    elseif typ == "eof" then
        -- 文件读取结束
        break
    else
        ngx.log(ngx.INFO, "do other things")
    end
end
if ret_save then
    response.msg = "success"
    local json = cjson.encode(response)
    ngx.say(json)
    ngx.log(ngx.ERR, "response:", json)
end

oss

lua-resty-oss

# nginx.conf
location /upload/oss {
    content_by_lua_file conf/lua/upload-oss.lua;

}
-- upload-oss.lua
--==========================================
-- 文件上传 阿里云 OSS
--==========================================
local upload = require "resty.upload"
local oss = require "resty.oss"
local cjson = require "cjson"
-- 获取上传的文件
function readFile()
    local chunk_size = 4096
    local form, err = upload:new(chunk_size)
    form:set_timeout(20000)
    local file = {}
    if not err then
        while true do
            local typ, res, err2 = form:read()
            if not typ then
                err = err2
                print("failed to read: ", err2)
                break
            end
            if typ == 'header' and res[1] == 'Content-Disposition' then
                local filename = string.match(res[2], 'filename="(.*)"')
                file.name = filename
            end
            if typ == 'header' and res[1] == 'Content-Type' then
                file['type'] = res[2]
            end
            if typ == 'body' and file then
                file[typ] = (file[typ] or '') .. res
            end
            if typ == "eof" then
                break
            end
        end
    end
    return file, err
end


local file, err = readFile()


ngx.log(ngx.ERR, "file.type".. file.type)


local oss_config = {
    accessKey =   "access" ,
    secretKey =   "secret" ,
    bucket    =   "bucket" ,
    endpoint  =   "oss-cn-shenzhen.aliyuncs.com"
}
local client = oss.new(oss_config)
local url,object_name,body = client:put_object(file.body, file.type, file.name)
ngx.say(cjson.encode(url))

redis

openresty使用Lua连接Redis集群(包括单机版redis)

LuaJIT bytecode

# nginx.conf 中使用ljbc字节码文件
/opt/openresty/luajit/bin/luajit -b upload-local.lua upload-local.ljbc

nginx 集成 lua

集成

# luajit
wget http://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz
tar zxvf LuaJIT-2.1.0-beta3
cd LuaJIT-2.1.0-beta3
make & make install PREFIX=/usr/local/luajit

# /etc/profile
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
source /etc/profile

# ldconfig
echo "/usr/local/luajit/lib" >> /etc/ld.so.conf
ldconfig


# ngx_devel_kit
wget https://github.com/vision5/ngx_devel_kit/archive/refs/tags/v0.3.1.tar.gz
tar zxvf v0.3.1
mv v0.3.1 ngx_devel_kit

# lua_ngx_module
wget https://github.com/openresty/lua-nginx-module/archive/refs/tags/v0.10.19.tar.gz
tar zxvf v0.10.19
mv v0.10.19 lua-nginx-module

# nginx
./configure  --prefix=/usr --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-http_stub_status_module --add-module=/usr/local/nginx/nginx-rtmp-module-master --with-stream --with-stream_ssl_module --with-ld-opt=-Wl,-E,-rpath,/usr/local/luajit/lib --add-module=/opt/nginx/ngx_devel_kit --add-module=/opt/nginx/lua-nginx-module

make

objs/nginx -V

需要注意的点

  • 在nginx的http模块中配置第三方lualib
http {
    # lua模块
    lua_package_path '/usr/local/lualib/?.lua;;';
    # so模块
    lua_package_cpath '/usr/local/lualib/?.so;;';
}
# 报错信息
[root@localhost lualib]# nginx -c /etc/nginx/nginx.conf
nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
nginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: module 'resty.core' not found:
    no field package.preload['resty.core']
    no file './resty/core.lua'
    no file '/usr/local/luajit/share/luajit-2.0.5/resty/core.lua'
    no file '/usr/local/share/lua/5.1/resty/core.lua'
    no file '/usr/local/share/lua/5.1/resty/core/init.lua'
    no file '/usr/local/luajit/share/lua/5.1/resty/core.lua'
    no file '/usr/local/luajit/share/lua/5.1/resty/core/init.lua'
    no file './resty/core.so'
    no file '/usr/local/lib/lua/5.1/resty/core.so'
    no file '/usr/local/luajit/lib/lua/5.1/resty/core.so'
    no file '/usr/local/lib/lua/5.1/loadall.so'
    no file './resty.so'
    no file '/usr/local/lib/lua/5.1/resty.so'
    no file '/usr/local/luajit/lib/lua/5.1/resty.so'
    no file '/usr/local/lib/lua/5.1/loadall.so') in /etc/nginx/nginx.conf:131
  • error while loading shared libraries: libluajit-5.1.so.2
# make完毕后检查
[root@localhost nginx-1.20.1]# objs/nginx -V
objs/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory

# 链接l'l
ln -s /usr/local/luajit/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2

  • require module 'xxx' not found.
# 将第三方lib放入 lualib 路径下,目录层级按照引用方式自定义
#
resty/core
resty/lrucache
ngx
resty/string.lua
resty/md5.lua

cjson.so
...

# 报错日志
2021/05/30 10:58:48 [error] 8408#8408: *12 lua entry thread aborted: runtime error: /etc/nginx/lua/upload-local.lua:5: module 'resty.upload' not found:
        no field package.preload['resty.upload']
        no file '/usr/local/lualib/resty/upload.lua'
        no file '/usr/local/lualib/resty/upload.so'
        no file '/usr/local/lualib/resty.so'
stack traceback:
coroutine 0:
        [C]: in function 'require'
        /etc/nginx/lua/upload-local.lua:5: in function </etc/nginx/lua/upload-local.lua:1>, client: 192.168.1.11, server: localhost, request: "POST /upload/local HTTP/1.1", host: "192.168.1.7"
2021/05/30 11:02:48 [error] 8408#8408: *13 lua entry thread aborted: runtime error: /etc/nginx/lua/upload-local.lua:6: module 'cjson' not found:
        no field package.preload['cjson']
        no file '/usr/local/lualib/cjson.lua'
        no file '/usr/local/lualib/cjson.so'
stack traceback:
coroutine 0:
        [C]: in function 'require'
        /etc/nginx/lua/upload-local.lua:6: in function </etc/nginx/lua/upload-local.lua:1>, client: 192.168.1.11, server: localhost, request: "POST /upload/local HTTP/1.1", host: "192.168.1.7"
2021/05/30 11:06:10 [error] 8408#8408: *14 lua entry thread aborted: runtime error: /etc/nginx/lua/upload-local.lua:7: module 'resty.md5' not found:
        no field package.preload['resty.md5']
        no file '/usr/local/lualib/resty/md5.lua'
        no file '/usr/local/lualib/resty/md5.so'
        no file '/usr/local/lualib/resty.so'
stack traceback:
coroutine 0:
        [C]: in function 'require'
        /etc/nginx/lua/upload-local.lua:7: in function </etc/nginx/lua/upload-local.lua:1>, client: 192.168.1.11, server: localhost, request: "POST /upload/local HTTP/1.1", host: "192.168.1.7"
2021/05/30 11:07:54 [error] 8408#8408: *15 lua entry thread aborted: runtime error: /etc/nginx/lua/upload-local.lua:90: attempt to concatenate field 'proxy_url' (a nil value)
stack traceback:
coroutine 0:
        /etc/nginx/lua/upload-local.lua: in function </etc/nginx/lua/upload-local.lua:1>, client: 192.168.1.11, server: localhost, request: "POST /upload/local HTTP/1.1", host: "192.168.1.7"

  • 配置了一堆,越看越懵

./configure --prefix=/usr --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-module=/opt/nginx/nginx-rtmp-module-1.2.1 --with-ld-opt=-Wl,-E,-rpath,/usr/local/luajit/lib --add-module=/opt/nginx/ngx_devel_kit-0.3.1 --add-module=/opt/nginx/lua-nginx-module-0.10.20rc1 --add-module=/opt/nginx/nginx-rtmp-module-1.2.1

  • 核心

./configure --prefix=/usr --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --user=nginx --group=nginx --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_stub_status_module --http-client-body-temp-path=/var/tmp/nginx/proxy --http-proxy-temp-path=/var/tmp/nginx/temp --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-http_stub_status_module --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/opt/nginx/nginx-rtmp-module-1.2.1 --add-module=/opt/nginx/ngx_devel_kit-0.3.1 --add-module=/opt/nginx/lua-nginx-module-0.10.20rc1

posted @ 2021-06-27 14:40  ggutap  阅读(670)  评论(0编辑  收藏  举报