Lua tech talk
-
Upload
locaweb -
Category
Technology
-
view
247 -
download
1
description
Transcript of Lua tech talk
Modulos Nginx usando Lua Rachad Honein
NGINX
¤ HTTP server with High Performance
¤ Events based architecture
¤ Small footprint on memory and processing
¤ Declarative Configuration
¤ Like Apache natively extensible through C modules
Market Share
Nginx Configuration Directives
1 location /hello { 2 set_unescape_uri $name $arg_name; 3 set_if_empty $name "Anonymous"; 4 echo "Hello, $name!"; 5 }
Lua
Lua
Lua
¤ Open-Source (MIT License)
¤ Brazilian scripting language created in1993 - PUC-Rio
¤ Interpreted Language
¤ Modular Language / Embedded / Portable
¤ Extremely fast scripting language
¤ Dynamically typed
¤ Functional language
¤ Prototype based language => Object Oriented
¤ Looks and feels like Javascript
Who uses Lua? ¤ Very popular in Games Engines and much more
¤ World of Warcraft ¤ Angry Birds ¤ Netflix ¤ Globo ¤ Cloudflare ¤ Redis ¤ Adobe Photoshop Lightroom ¤ Apache HTTP Server ¤ Apache Traffic Server ¤ Firefox ¤ MediaWiki ¤ MySQL Proxy ¤ MySQL Workbench ¤ PL/Lua for PostgreSQL
¤ Cisco ¤ Internet of things https://sites.google.com/site/marbux/home/where-lua-is-used
Lua
¤ Fast language:
Comparison with other scripting languages
Lua Nginx module
¤ The Power of Lua in Nginx
¤ "Light threads" based on Lua coroutines
¤ Acts on all phases inside the Nginx process ¤ Rewrite Phase ¤ Access Phase ¤ Content Phase ¤ Log Phase
¤ Exposes all the Nginx environment to Lua via an API http://wiki.nginx.org/HttpLuaModule
¤ Provides a synchronous yet non-blocking API to Nginx
¤ Very fast, if compiled with --luajit
Use cases of Nginx + Lua
¤ Smart Programmable Router
¤ Proxy
¤ Load Balancer
¤ A/B Testing
¤ Complex Caching
¤ Advanced logging
¤ API Aggregator
¤ Authentication Services
¤ And much more…
HttpLuaModule Directives ngx_lua Nginx Phase Context
init_by_lua loading-config http
init_worker_by_lua starting-worker http
set_by_lua rewrite server, server if, location, location if
rewrite_by_lua rewrite tail http, server, location, location if
access_by_lua access tail http, server, location, location if
content_by_lua content location, location if
header_filter_by_lua output-header-filter http, server, location, location if
body_filter_by_lua output-body-filter http, server, location, location if
log_by_lua log http, server, location, location if
Where lua module acts on? server Write
find config
rewrite
post rewrite
pre-access
access
post-access
try-files
content
logging
req
ue
st
Re
qu
est
Life
time
insid
e N
GIN
X
content_by_lua
*_by_lua_file
1 location /hellolua { 2 content_by_lua ' 3 local name = ngx.var.arg_name or "Anonymous" 4 ngx.say("Hello, ", name, "!") 5 '; 6 }
1 location /hellolua { 2 content_by_lua_file 'path/to/file.lua’ 3 }
1 location /hello { 2 set_unescape_uri $name $arg_name; 3 set_if_empty $name "Anonymous"; 4 echo "Hello, $name!"; 5 }
Result
1 location /hellolua { 2 default_type 'text/plain’; 3 content_by_lua ' 4 local name = ngx.var.arg_name or "Anonymous" 5 ngx.say("Hello, ", name, "!") 6 '; 7 }
What will we see today?
¤ lua_shared_dict ¤ Declares a shared memory zone
¤ log_by_lua ¤ Acts on the log phase
¤ Sub-requests ¤ Calls subrequests URIs
¤ Cosockets ¤ Send and receive on TCP or Unix domain sockets
¤ Use Cases / Demo
Shared Data
1 http { 2 lua_shared_dict dogs 10m; 3 server { 4 location /set { 5 content_by_lua ' 6 local dogs = ngx.shared.dogs 7 dogs:set("Jim", 8) 8 ngx.say("STORED") 9 '; 10 } 11 location /get { 12 content_by_lua ' 13 local dogs = ngx.shared.dogs 14 ngx.say(dogs:get("Jim")) 15 '; 16 } 17 } 18 }
Counter: Shared Data
1 http { 2 lua_shared_dict count10m; 3 server { 4 location /counter { 5 content_by_lua ' 6 ngx.shared.count:incr("hits", 1) 7 ngx.say(ngx.shared.count:get("hits")) 8 '; 9 } 10 } 11 }
log_by_lua
1 location / { 2 proxy_pass http://mybackend;
3 log_by_lua ' 4 if tonumber(ngx.var.upstream_response_time) >= 5 then 5 ngx.log(ngx.WARN, "[SLOW] Ngx upstream response time: " .. ngx.var.upstream_response_time ..
"s from " .. ngx.var.upstream_addr); 6 end 7 '; 8 }
Log slow requests >5 seconds
1 location /{ 2 log_by_lua ’ 3 if ngx.status >= 500 then 4 send_email… 5 end'; 6 }
Tell me about 500 error
Sub-requests
¤ Issues a synchronous but still non-blocking Nginx Subrequest using uri.
¤ Subrequests just mimic the HTTP interface. ¤ There is no extra HTTP/TCP traffic involved.
¤ Everything works internally, efficiently, on the C level.
¤ Subrequests issued by ngx.location.capture inherit all the request headers of the current request
ngx.location.capture
¤ Subrequests ¤ Example: Deprecated Route
1 location /old_api { 2 content_by_lua ' 3 local res = ngx.location.capture(”/new_api") 4 if res.status >= 500 then 5 ngx.exit(res.status) 6 end 7 ngx.status = res.status 8 ngx.say("This is coming from another request") 9 ngx.say(res.body) 10 '; 11 }
ngx.location.capture_multi
¤ Multi Subrequests ¤ Example: Cheating on a chatty REST API
1 location /mobile/home { 2 content_by_lua ’ 3 res1, res2, res3 = ngx.location.capture_multi{ 4 { "/categories"}, 5 { "/popular"}, 6 { "/movies", 16}, 7 { "/movies", 19}, 8 } 9 ngx.say(cjson.encode(res1, res2, res3)) 10 '; 11 }
cosockets
¤ Send and receive on TCP or Unix domain sockets.
¤ API compatible with LuaSocket, yet non-blocking to Nginx.
¤ Has a keepalive mechanism to avoid connect/close for each request.
cosockets examples
1 local sock = ngx.socket.tcp() 2 local ok, err = sock:connect("127.0.0.1", 1234) 3 local bytes, err = sock:send("hello") 4 local data, err = sock:receive("*l")
1 local sock = ngx.socket.udp() 2 local ok, err = sock:setpeer("127.0.0.1", 5432) 3 local bytes, err = sock:send("my query") 4 local dgram, err = sock:receive()
Connect, bind, receive, send, close ….
cosocket based libraries
¤ lua-resty-memcached
¤ lua-resty-redis
¤ lua-resty-mysql
¤ Lua-resty-upload
Courtesy of OpenResty
Non Blocking I/O lua-resty-memcached
1 location /memcached { 2 content_by_lua ' 3 local memcached = require "resty.memcached" 4 local memc = memcached:new() 5 local ok, err = memc:connect("127.0.0.1", 11211)
6 local ok, err = memc:set("foo", "bar", 3600) 7 if ok then 8 ngx.say("STORED") 9 end
10 memc:set_keepalive() 11 '; 12 }
Cases
¤ Load Balancer
¤ Inject Javascript tags into HTML
¤ Authentication Module
Case: Dead Simple Load Balancer 1 upstream instance1 { 2 server privatehost1:3000; 3 }
4 upstream instance2 { 5 server privatehost2:3000; 6 }
7 server { 8 listen 80;
9 set $root /var/www; 10 set $backend http://instance1;
11 rewrite_by_lua ' 12 if (ngx.var.user_id % 2 == 0) then 13 ngx.var.backend = http://instance2 14 end 15 ';
16 proxy_pass $backend; 17 }
Case: Inject Google Analytics Code
1 location / { 2 proxy_pass http://mybackend; 3 body_filter_by_lua ‘ 4 local chunk, eof = ngx.arg[1], ngx.arg[2] 5 local google_code = "<script type="text/javascript”> 6 var _gaq = _gaq || [];_gaq.push(['_setAccount', 'UA-XXXXXXXX-1']); 7 .... Google script code …..
8 </script></body>"
9 string.gsub(chunk,"</body>",google_code)
10 '; 11 }
Case: CAS Auth Lua Module
Nginx Lua Auth Mod
Authorize
/panel
Apps
Demo App
Thank you!