Skip to content

OpenResty

参考资料

用做网关,openresty的配置

从以下网页来看,可配置access_by_lua

https://blog.csdn.net/Long_xu/article/details/128501575

找了一下此配置

lua
    location / {
        root   /usr/local/openresty/nginx/html;
        index  index.html index.htm;

        access_by_lua '
            local args = ngx.req.get_uri_args()
            local salt = args.param
        
            if salt == "auth" then
                return
            else
                ngx.exit(ngx.HTTP_FORBIDDEN)
            end
        ';
    }

docker openresty 目录

  • /usr/local/openresty/nginx/conf/nginx.conf
  • /etc/nginx/conf.d

OpenResty入门

快速入门

http://openresty.org/en/getting-started.html#prepare-the-nginxconf-config-file

  • /etc/nginx/conf.d/default.conf
nginx
server {
    listen 80;
    server_name localhost;
    lua_code_cache off;

    location / {
        root /usr/local/openresty/nginx/html;
        index index.html index.htm;
    }

    location /hello {
        default_type text/html;
        content_by_lua_block {
            ngx.say("<p>hello, world</p>")
        }
    }
}

执行lua文件

  • /etc/nginx/conf.d/default.conf
nginx
server {
    listen 80;
    server_name localhost;
    lua_code_cache off;

    location / {
        root /usr/local/openresty/nginx/html;
        index index.html index.htm;
    }

    location /hello {
        default_type text/html;
        content_by_lua_file lua/hello.lua;
    }
}
  • /usr/local/openresty/nginx/lua/hello.lua
lua
ngx.say("Hello World!!!")

关闭nginx缓存

修改lua代码之后,nginx执行的还是原来的代码,原因是默认nginx将缓存开启了

可使用lua_code_cache指令关闭缓存,可在以下位置配置

  • http
  • server
  • location
  • location if

案例

根据盐值,生成随机md5

  • /etc/nginx/conf.d/default.conf
nginx
server {
    listen 80;
    server_name localhost;
    lua_code_cache off;

    location / {
        root /usr/local/openresty/nginx/html;
        index index.html index.htm;
    }

    location /get_random_string {
        default_type text/html;
        content_by_lua_file lua/get_random_string.lua;
    }
}
  • /usr/local/openresty/nginx/lua/get_random_string.lua
lua
local args = ngx.req.get_uri_args()
local salt = args.salt

if not salt then
    ngx.exit(ngx.HTTP_BAD_REQUEST)
end

local string = ngx.md5(ngx.time() .. salt)
ngx.say(string)

案例

客户端发送base64,服务器解析后,响应json

nginx lua module 具备 40 多个指令和 120 多个 API

  • /etc/nginx/conf.d/default.conf
nginx
server {
    listen 80;
    server_name localhost;
    lua_code_cache off;

    location / {
        root /usr/local/openresty/nginx/html;
        index index.html index.htm;
    }

    location /decode_info {
        default_type text/html;
        content_by_lua_file lua/decode_info.lua;
    }
}
  • /usr/local/openresty/nginx/lua/decode_info.lua
lua
local json = require "cjson"

ngx.req.read_body()
local args = ngx.req.get_post_args()

if not args or not args.info then
    ngx.exit(ngx.HTTP_BAD_REQUEST)
end

local client_ip = ngx.var.remote_addr
local user_agent = ngx.req.get_headers()['user-agent'] or ''
local info = ngx.decode_base64(args.info)

local response = {}
response.info = info
response.ip = client_ip
response.user_agent = user_agent

ngx.say(json.encode(response))
  • bash
bash
curl -i --data 'info=5L2g5aW9' http://localhost/decode_info

连接数据库

  • 连接redis

在以下页面搜redis,进入lua-resty-redis

https://github.com/openresty/lua-nginx-module/blob/master/README.markdown

进入 https://github.com/openresty/lua-resty-redis#synopsis

nginx
server {
    listen 80;
    server_name localhost;
    lua_code_cache off;

    location /test {
        # need to specify the resolver to resolve the hostname
        resolver 8.8.8.8;

        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()

            red:set_timeouts(1000, 1000, 1000) -- 1 sec

            -- or connect to a unix domain socket file listened
            -- by a redis server:
            --     local ok, err = red:connect("unix:/path/to/redis.sock")

            -- connect via ip address directly
            local ok, err = red:connect("127.0.0.1", 6379)

            -- or connect via hostname, need to specify resolver just like above
            local ok, err = red:connect("redis.openresty.com", 6379)

            if not ok then
                ngx.say("failed to connect: ", err)
                return
            end

            ok, err = red:set("dog", "an animal")
            if not ok then
                ngx.say("failed to set dog: ", err)
                return
            end

            ngx.say("set result: ", ok)

            local res, err = red:get("dog")
            if not res then
                ngx.say("failed to get dog: ", err)
                return
            end

            if res == ngx.null then
                ngx.say("dog not found.")
                return
            end

            ngx.say("dog: ", res)

            red:init_pipeline()
            red:set("cat", "Marry")
            red:set("horse", "Bob")
            red:get("cat")
            red:get("horse")
            local results, err = red:commit_pipeline()
            if not results then
                ngx.say("failed to commit the pipelined requests: ", err)
                return
            end

            for i, res in ipairs(results) do
                if type(res) == "table" then
                    if res[1] == false then
                        ngx.say("failed to run command ", i, ": ", res[2])
                    else
                        -- process the table value
                    end
                else
                    -- process the scalar value
                end
            end

            -- put it into the connection pool of size 100,
            -- with 10 seconds max idle time
            local ok, err = red:set_keepalive(10000, 100)
            if not ok then
                ngx.say("failed to set keepalive: ", err)
                return
            end

            -- or just close the connection right away:
            -- local ok, err = red:close()
            -- if not ok then
            --     ngx.say("failed to close: ", err)
            --     return
            -- end
        }
    }
}

OpenResty缓存

shared_dict

多worker共享,线程不安全

  1. 定义
  • nginx.conf
nginx
# 指定shared_dict名字为my_cache,大小为128m
lua_shared_dict cache_ngx 128m;
  1. 使用
lua
function get_from_cache(key)
    local cache_ngx = ngx.shared.cache_ngx
    local value = cache_ngx:get(key)
    return value
end

lua_resty_lrucache

  • 不预设内存大小,只预存key个数
  • 每个worker单独占用,线程安全,内存占用翻倍
  • lurcache API只有get、set、delete
  • shared_dict还可以addreplaceincrget_keysget_stake

案例

lua
local red = redis:new()

function set_to_cache(key, value, exptime)
    if not exptime then
        exptime = 0
    end
    local cache_ngx = ngx.shared.cache_ngx
    local succ, err, forcible = cache_ngx:set(key, value, exptime)
    return succ
end

function get_from_cache(key)
    local cache_ngx = ngx.shared.cache_ngx
    local value = cache_ngx:get(key)
    if not value then
        value = get_from_redis(key)
        set_to_cache(key, value)
    end
    return value
end

function get_from_redis(key)
    local res, err = red:get("dog)
    if res then
        return 'yes'
    else
        return 'no'
    end
end

local res = get_from_cache('dog)
ngx.say(res)
bash
# 用100个终端,模拟100000次请求,查看qps
ab -n 100000 -c 100 -k http://localhost/get_value

lua-resty-casbin

参考以下链接安装,但需要注意的是,安装lua-resty-casbin时,文档中是使用url安装,实测装不上

https://github.com/casbin-lua/lua-resty-casbin/

安装casbin的系统依赖

bash
apt update
apt install make wget unzip zip gcc libpcre3 libpcre3-dev git

安装luarocks

bash
wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
tar zxpf luarocks-3.9.2.tar.gz
cd luarocks-3.9.2

# 以下的jit版本号: 2.1.0-beta3,可参考以下目录修改
# /usr/local/openresty/luajit/bin
./configure --prefix=/usr/local/openresty/luajit \
--with-lua=/usr/local/openresty/luajit/ \
--lua-suffix=jit-2.1.0-beta3 \
--with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1

make
make install

安装casbin

bash
/usr/local/openresty/luajit/bin/luarocks install casbin

安装lua-resty-casbin

bash
/usr/local/openresty/luajit/bin/luarocks install lua-resty-casbin

干预-prefix参数的几种方式

  1. 在Dockerfile上看

https://github.com/openresty/docker-openresty/blob/master/centos/Dockerfile

发现有这样的一行

CMD ["/usr/bin/openresty", "-g", "daemon off;"]

可以在docker-compose.yml文件上改

说明并没有设置-p参数

进入容器,使用openresty -h命令,提示出以下信息

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/local/openresty/nginx/)
  -e filename   : set error log file (default: logs/error.log)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

说明-p参数的默认值是/usr/local/openresty/nginx

  1. 使用nginx指令lua_package_pathlua_package_path "$prefix/lua/?.lua;$prefix/lua/vendor/?.lua;;";

注意是两个分号

其中prefix就是启动时的-p参数