本文共 6650 字,大约阅读时间需要 22 分钟。
Lua的性能超牛的,这个不需要再啰嗦了。。。
Nginx_lua的适用场景
网络I/O 阻塞时间远高于CPU 计算占用时间、同时上游资源非瓶颈(可伸缩)的网络应用,如高性能网络中间层、HTTP REST 接口服务等;
期望简化系统架构,让服务向Nginx 同质化的Web 站点;
优势:
同步非阻塞I/O 形式直观易懂,并发服务能力强
CPU、内存运行开销低
同Nginx 结合度高,可方便粘合现有Nginx 模块功能
劣势:
属于新技术方案,Lua 相比于PHP、Ruby 等广泛使用的开发
语言,周边附属设施尚不够健全,需要时间积累
安装就简单过一遍,其实大家用openresty就行啦。。。 作者已经做了很多的调优。。。
还是推荐大家用 openresty。。。 最少在测试环境下用这个,可以省去很多找模块,折腾模块的时间。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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 |
一定要注意他的执行顺序:
Rewrite phase.
Access phase.
Content phase.
详细的步骤:
1 2 3 4 5 6 7 8 | 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,如果发现恶意和违规的侵入的话,可以发邮件报警,好让我们第一时间收到邮件的信息。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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有丰富的接口的方案,不只是给别人提供的接口,还有他自己访问别的接口所用的模块。
如果你的同事那边已经有个高性能的socket接口,那你就别麻烦他改成rest模式了。。。 毕竟socket对socket速度很快的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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的控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 '; |