当前位置: 代码迷 >> 综合 >> 生产环境中 Ngx_lua 使用技巧和应用的范例
  详细解决方案

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

热度:10   发布时间:2023-12-18 08:54:46.0

Nginx_lua的适用场景

 

  1. 网络I/O 阻塞时间远高于CPU 计算占用时间、同时上游资源非瓶颈(可伸缩)的网络应用,如高性能网络中间层、HTTP REST 接口服务等;

  2. 期望简化系统架构,让服务向Nginx 同质化的Web 站点;

 

淘宝人对于ngx_lua使用的总结:

 

优势:

  • 同步非阻塞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.gztar -xzvf echo-nginx-module.tar.gz7. 解压nginx,ngx_devel_kit, lua-nginx-module tar -xzvf nginx-1.2.2.tar.gz tar -xzvf simpl-ngx_devel_kit.tar.gztar -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 thenngx.say(e)elsengx.say("send ok!")end';}

lua这东西挺怪的,他的双引号和单引号是有很大区别的,我到现在也没搞明白,啥区别,反正用双引号就对了。。。有事error.log报错的话,改成单引号试试。。

好点的方法是  先在lua的环境中跑一边,ok后,在放到ngx_lua里面。

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

 

如果你的同事那边已经有个高性能的socket接口,那你就别麻烦他改成rest模式了。。。 毕竟socket对socket速度很快的。

 

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 thenngx.say("failed to connect: ", err)returnendlocal bytes, err = sock:send("flush_all")ngx.say(bytes,err)if not bytes thenngx.say("failed to send query: ", err)returnendlocal line, err = sock:receive()if not line thenngx.say("failed to receive a line: ", err)returnendngx.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 emptyif routes == nil thenroutes = {}ngx.log(ngx.ALERT, "Route cache is empty.")end-- try cached route first local route = routes[ngx.var.http_host]if route == nil thenlocal redis = require "redis"local client = redis.connect("localhost", 6379)route = client:get(ngx.var.http_host)endif route ~= nil thenngx.var.upstream = routeroutes[ngx.var.http_host] = route_G.routes = routeselsengx.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 thens = ngx.var.http_cookiefor k, v in string.gmatch(s, "(%w+)=([%w%/%.=_-]+)") dot[k] = vendendp = ngx.req.get_uri_args()if not t.uid and p.uid thenexpires = ngx.cookie_time(4523969511)ngx.header["Set-Cookie"] = {
      "uid=" .. p.uid .."; expires=" .. expires .. ";end ';