美文网首页转载部分
生产环境中 Ngx_lua 使用技巧和应用的范例

生产环境中 Ngx_lua 使用技巧和应用的范例

作者: 顶尖少爷 | 来源:发表于2019-02-21 10:36 被阅读37次

    Nginx_lua的适用场景

    网络I/O 阻塞时间远高于CPU 计算占用时间、同时上游资源非瓶颈(可伸缩)的网络应用,如高性能网络中间层、HTTP REST 接口服务等;
    期望简化系统架构,让服务向Nginx 同质化的Web 站点;

    优势:

    同步非阻塞I/O 形式直观易懂,并发服务能力强
    CPU、内存运行开销低
    同Nginx 结合度高,可方便粘合现有Nginx 模块功能

    劣势:

    属于新技术方案,Lua 相比于PHP、Ruby 等广泛使用的开发
    语言,周边附属设施尚不够健全,需要时间积累

    安装就简单过一遍,其实大家用openresty就行啦。。。 作者已经做了很多的调优。。。
    还是推荐大家用 openresty。。。 最少在测试环境下用这个,可以省去很多找模块,折腾模块的时间。。。

    1.下载nginx
    wget http://nginx.org/download/nginx-1.2.2.tar.gz
    2.安装gcc
    sudo apt-get install gcc
    3.下载LuaJIT
    wget http://luajit.org/download/LuaJIT-2.0.0-beta10.tar.gz
    4. 安装LuaJIT
    tar -xzvf  LuaJIT-2.0.0-beta10.tar.gz
    cd LuaJIT-2.0.0-beta10
    make && sudo make install
    5.下载 ngx_devel_kit(在这个页面找:https://github.com/simpl/ngx_devel_kit/tags)
    wget https://github.com/simpl/ngx_devel_kit/tarball/master -O simpl-ngx_devel_kit.tar.gz
    6.下载最新的 lua-nginx-module(在这个页面找:https://github.com/chaoslawful/lua-nginx-module/tags)
     wget https://github.com/chaoslawful/lua-nginx-module/tarball/master -O lua-nginx-module.tar.gz
    7.下载pcre
    wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.31.tar.gz
    tar -xzvf pcre-8.31.tar.gz
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
     ./configure && make(如果报“compile: unrecognized option `-DHAVE_CONFIG_H'”,请安装sudo apt-get install build-essential)
    sudo make install
    8.下载echo模块
    wget https://github.com/agentzh/echo-nginx-module/tarball/master -O echo-nginx-module.tar.gz
     tar -xzvf echo-nginx-module.tar.gz
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
    7. 解压nginx,ngx_devel_kit, lua-nginx-module
    tar -xzvf nginx-1.2.2.tar.gz
    tar -xzvf simpl-ngx_devel_kit.tar.gz
     tar -xzvf lua-nginx-module.tar.gz
    8.安装
    sudo apt-get install openssl libssl-dev
    sudo apt-get install libtool
    cd  nginx-1.2.2
    export LUAJIT_LIB=/usr/local/lib/
    export LUAJIT_INC=/usr/local/include/luajit-2.0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
    ./configure --user=www-data --group=www-data --with-debug --with-http_gzip_static_module --with-http_ssl_module  --with-http_stub_status_module --with-http_realip_module \
    --prefix=/usr/local/nginx \
        --add-module=../simpl-ngx_devel_kit-4192ba6/ \
      --add-module=../chaoslawful-lua-nginx-module-b771a2e/\
        --add-module=../agentzh-echo-nginx-module-8042c62/
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
    make -j2
    sudo make install
    

    一定要注意他的执行顺序:

    1.Rewrite phase.
    2.Access phase.
    3.Content phase.

    详细的步骤:

    1.init_by_lua  上下文http  ngx启动时执行
    2. set_by_lua  上下文 server, server if, location, location if
    3.rewrite_by_lua 上下文  http, server, location, location if
    4.access_by_lua 上下文 http, server, location, location if
    5.content_by_lua 上下文   location, location if
    6.header_filter_by_lua 上下文   http, server, location, location if
    7.body_filter_by_lua 上下文 http, server, location, location if
    8.log_by_lua 上下文 http, server, location, location if
    

    咱们再过滤post、get请求或者是触发了某个access、rewrite,如果发现恶意和违规的侵入的话,可以发邮件报警,好让我们第一时间收到邮件的信息。。。

    location = /smtp {
            default_type "text/plain";
            content_by_lua '
                local smtp = require("socket.smtp")
                local from = "<ruifengyunceshi@163.com>"
                local  rcpt = {"",}
                local   mesgt = {
                headers = {
                to = "", -- 收件人
                subject = "This is Mail Title"
                },
            body = "This is  Mail Content."
        }
         local  r, e = smtp.send{
            server="smtp.163.com",
            user="",
            password="",
            from = from,
            rcpt = rcpt,
            source = smtp.message(mesgt)
          }
        if not r then
            ngx.say(e)
        else
            ngx.say("send ok!")
        end
        ';
        }
    

    lua这东西挺怪的,他的双引号和单引号是有很大区别的,我到现在也没搞明白,啥区别,反正用双引号就对了。。。有事error.log报错的话,改成单引号试试。。
    好点的方法是 先在lua的环境中跑一边,ok后,在放到ngx_lua里面。

    Lua有丰富的接口的方案,不只是给别人提供的接口,还有他自己访问别的接口所用的模块。

    location /cosocket {
            default_type "text/plain";
            content_by_lua '
            local sock = ngx.socket.tcp()
            sock:settimeout(1000)
            local ok, err = sock:connect("127.0.0.1", 12000)
            if not ok then
                ngx.say("failed to connect: ", err)
                return
            end
            local bytes, err = sock:send("flush_all")
            ngx.say(bytes,err)
            if not bytes then
                ngx.say("failed to send query: ", err)
                return
            end
           local line, err = sock:receive()
            if not line then
                ngx.say("failed to receive a line: ", err)
                return
            end
            ngx.say("result: ", line)
            ';
          }
                                                                                                                                                                                                                                                                                                                                                                                          
        }
    }
    

    对于给别人的mysql查询,给账号密码不合适,和一个小权限的账号密码也不合适。

    这种情况,我们要是求高性能的话,可以用lua配置cjson做成rest接口。

    location /select2 {
    content_by_lua '
    local mysql = require "resty.mysql"
    local db,err = mysql:new()
    if not db then
    ngx.say("failed to instantiate mysql: ",err)
    return
    end
    db:set_timeout(1000)
    local ok,err,errno,sqlstate = db:connect{
    host = "127.0.0.1",
    port = 3306,
    database = "niubi",
    user = "ruifengyun",
    password = "",
    max_package_size = 1024
    }
    if not ok then
    ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
    return
    end
    ngx.say("connected to mysql.")
    res,err,errno,sqlstate = db:query("select username,password from users where id="..ngx.var.arg_id)
    if not res then
    ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
    return
    end
    local cjson = require "cjson"
    ngx.say("result: “,cjson.encode(res))
    ';
    }
    

    咱们既然知道了 lua的强大之处, 可以从lua里面搞负载均衡。

    往redis里面 扔两个key 比如 web1 8.8.8.111 web2 8.8.8.222

    server {
      listen 80;
      server_name _;
      server_name_in_redirect off;
      port_in_redirect off;
      root /root/html;
      location / {
        set $upstream "";
        rewrite_by_lua '
          local routes = _G.routes
          -- setup routes cache if empty
          if routes == nil then
            routes = {}
            ngx.log(ngx.ALERT, "Route cache is empty.")
          end
          -- try cached route first      local route = routes[ngx.var.http_host]
          if route == nil then
            local redis  = require "redis"
            local client = redis.connect("localhost", 6379)
            route        = client:get(ngx.var.http_host)
          end
          if route ~= nil then
            ngx.var.upstream = route
            routes[ngx.var.http_host] = route
            _G.routes = routes
          else
            ngx.exit(ngx.HTTP_NOT_FOUND)
          end
        ';
        proxy_buffering             off;
        proxy_set_header            Host $host;
        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect              off;
        proxy_connect_timeout       10;
        proxy_send_timeout          30;
        proxy_read_timeout          30;
        proxy_pass                  http://$upstream;
      }
    }
    

    用lua 对cookie的控制

    header_filter_by_lua '
            t = {}
            if ngx.var.http_cookie then
                s = ngx.var.http_cookie
                for k, v in string.gmatch(s, "(%w+)=([%w%/%.=_-]+)") do
                    t[k] = v
                end
            end
                                                      
            p = ngx.req.get_uri_args()
                                                      
            if not t.uid and p.uid then
                expires = ngx.cookie_time(4523969511)
                ngx.header["Set-Cookie"] = {"uid=" .. p.uid .."; expires=" .. expires .. ";
            end
                                                      
    ';
    

    相关文章

      网友评论

        本文标题:生产环境中 Ngx_lua 使用技巧和应用的范例

        本文链接:https://www.haomeiwen.com/subject/xlzlyqtx.html