• Nginx 使用Lua脚本


    安装 Nginx Lua支持

    1. 安装系统依赖库
    yum install readline-devel pcre-devel openssl-devel gcc
    
    1. 安装LuaJIT
    $ wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz
    $ tar zxvf LuaJIT-2.0.5.tar.gz
    $ cd LuaJIT-2.0.5
    $ make install
    # 安装成功
    ==== Successfully installed LuaJIT 2.0.5 to /usr/local ====
    
    1. 设置LuaJIT环境变量
    $ export LUAJIT_LIB=/usr/local/lib
    $ export LUAJIT_INC=/usr/local/include/luajit-2.0
    $ echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
    $ ldconfig
    
    1. 下载相关模块

    ngx_devel_kit

    $ wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
    $ tar zxvf v0.3.0.tar.gz
    # 解压缩后目录名
    ngx_devel_kit-0.3.0
    

    lua-nginx-module

    $ wget https://github.com/openresty/lua-nginx-module/archive/v0.10.10.tar.gz
    $ tar zxvf v0.10.10.tar.gz
    # 解压缩后目录名
    lua-nginx-module-0.10.10
    
    1. 重新编译Nginx模块
    # 最好先查看下之前编译的
    ./sbin/nginx -V
    
    ./configure --prefix=/home/ifan/software/nginx 
        --with-http_ssl_module 
        --with-http_v2_module 
        --with-http_stub_status_module 
        --with-http_realip_module 
        --with-threads 
        --with-http_realip_module 
        --add-module=/home/ifan/lua-nginx-module-0.10.10 
        --add-module=/home/ifan/ngx_devel_kit-0.3.0
    
    make && make install
    
    1. 配置Nginx环境

    6.1 添加 Http lua 支持

    http {
        # 第三方库(cjson)地址luajit-2.0/lib
        lua_package_path './lua/?.lua;;';
        lua_package_cpath '/usr/local/include/luajit-2.0/lib/?.so;;';
    }
    

    6.2 添加一个Lua服务

    server {
        location /ip {
            # 正式环境需要去掉,现在加上方便调试lua脚本
    		lua_code_cache off;
    		default_type 'text/plain';
    
            # nginx下的相对路径
            content_by_lua_file lua/get_ip.lua;
    
    		# content_by_lua 'ngx.say("hello, lua")';
    
    		# content_by_lua_block {
    		#     ngx.say("hello lua")
    		# }
        }
    }
    

    6.3 添加nginx/lua/get_ip.lua

    local headers = ngx.req.get_headers()
    
    for k, v in pairs(headers) do
    	ngx.say(k,":", v)
    end
    
    ngx.say("X-REAL-IP", ":", headers["X-REAL-IP"])
    ngx.say("X_FORWARDED_FOR", ":", headers["X_FORWARDED_FOR"])
    ngx.say("remote_addr", ":", ngx.var.remote_addr)
    

    一些配置信息

    lua常用系统变量

    方法 类型 说明
    ngx.var 请求 如果要赋值如 ngx.var.b = 2,此变量必须提前声明;另外对于 nginx location 中使用 正则捕获的捕获组可以使用 ngx.var [捕获组数字]获取;
    ngx.req.get_headers 请求 获取请求头,默认只获取前100,如果想要获取所以可以调用ngx.req.get_header s(0);获取带中划线的请求头时请使用如 headers.user_agent 这种方式;如果一个请求头有多个值,则返回的 是 table;
    ngx.req.get_uri_args 请求 获取 url 请求参数,其用法和 get_headers 类似;
    ngx.req.get_post_args 请求 获取 post 请求内容体,其用法和 get_headers 类似,但是必须提前调用 ngx.req.r ead_body() 来读取 body 体(也可以选择在 nginx 配置文件使用lua_need_request_body on;开启读取 bod y 体,但是官方不推荐);
    ngx.req.raw_header 请求 未解析的请求头字符串;
    ngx.req.get_body_data 请求 为解析的请求 body 体内容字符串。
    ngx.req.get_method 请求 获取请求的大写字母形式的请求方式
    ngx.header 响应 通过ngx.header.header_name的形式获取或设置响应头信息。
    ngx.exit 响应 以某个状态码返回响应内容
    ngx.redirect 响应 重定向当前请求到新的 url
    ngx.log 其他 输出到log日志
    ngx.re.match 其他 正则匹配
    ngx.md5 其他 md5编码
    ngx.encode_base64 其他 base64解码
    ngx.decode_base64 其他 base64编码

    模块指令

    每个模块都有*_lua(指令)、*_lua_block(代码块)、*_lua_file(脚本文件)

    指令 所在阶段 使用范围 说明
    init_by_lua 加载配置文件 http 可以用于初始化全局配置
    set_by_lua rewrite server location location if 复杂逻辑的变量赋值,注意是阻塞的
    rewrite_by_lua rewrite http server location location if 实现复杂逻辑的转发或重定向
    content_by_lua content location location if 处理请求并输出响应
    header_filter_by_lua 响应头信息过滤 http server location location if 设置响应头信息
    body_filter_by_lua 输出过滤 http server location location if 对输出进行过滤或修改

    案例

    访问权限控制

    location / {
        set $allowed '115.171.226.212';
        access_by_lua_block {
            if ngx.re.match(ngx.req.get_method(), "PUT|POST|DELETE") and not ngx.re.match(ngx.var.request_uri, "_search") then
    			start, _ = string.find(ngx.var.allowed, ngx.var.remote_addr)
    			if not start then
    				ngx.exit(403)
    			end
    		end
        }
    	
        proxy_pass http://127.0.0.1:8000$request_uri;
    }
    

    访问频率控制

    在 Nginx 配置文件的 location 部分配置 Lua 脚本基本参数,并配置 Lua 模块指令:

    default_type "text/html";
    set rate_per 300
    access_by_lua_file lua/access.lua;
    

    Lua 脚本实现频率控制逻辑,使用 Redis 对单位时间内的访问次数做缓存,key 为访问 uri 拼接 token 后的 md5 值。具体内容如下:

    local redis = require "resty.redis"
    local red = redis:new()
    
    local limit = tonumber(ngx.var.rate_per) or 200
    local expire_time = tonumber(ngx.var.rate_expire) or 1000
    local key = "rate.limit:string:"
    
    red:set_timeout(500)
    local ok, err = red:connect("www.fanhaobai.com", 6379)
    if not ok then
        ngx.log(ngx.ERR, "failed to connect redis: " .. err)
        return
    end
    
    key = key .. ngx.md5(ngx.var.request_uri .. (ngx.req.get_uri_args()['token'] or ngx.req.get_post_args()['token']))
    local times, err = red:incr(key)
    if not times then
        ngx.log(ngx.ERR, "failed to exec incr: " .. err)
        return
    elseif times == 1 then
        ok, err = red:expire(key, expire_time)
        if not ok then
            ngx.log(ngx.ERR, "failed to exec expire: " .. err)
            return
        end
    end
    
    if times > limit then
        return ngx.exit(403)
    end
    
    return
    
  • 相关阅读:
    《孙子兵法》(前六篇)读书笔记
    写代码的指导思想:如何写出易测、清晰、健壮的牢固代码
    如何从业务代码中抽离出可复用的微组件
    碎碎念集萃二八
    订单同步工程标准化改造事记
    代码的味道
    批量导出51电子发票的pdf文件
    LODOP具体的分类的简短问答
    lodop打印透明图简短问答
    LODOP打印公章的白色透明2
  • 原文地址:https://www.cnblogs.com/iFanLiwei/p/13574968.html
Copyright © 2020-2023  润新知