./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-upload
lua-resty-string
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-redis
resty-redis-cluster
headers-more-nginx-module
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
# 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