37
LuaNode Asynchronous I/O in Lua Ignacio Burgueño

LuaNode: Asynchronous I/O for Lua

Embed Size (px)

DESCRIPTION

This is the talk about LuaNode that was presented at the Lua Workshop 2013 [1]. The source code for the demo is available on Github [2]. LuaNode allows to write performant net servers or clients in Lua. [1]: http://www.lua.org/wshop13.html [2]: https://github.com/ignacio/lua_workshop_2013

Citation preview

Page 1: LuaNode: Asynchronous I/O for Lua

LuaNode

Asynchronous I/O in Lua

Ignacio Burgueño

Page 2: LuaNode: Asynchronous I/O for Lua

About Me

Ignacio Burgueño

Software Developer at inConcert

@iburgueno

https://github.com/ignacio

Page 3: LuaNode: Asynchronous I/O for Lua

Agenda

● What is Asynchronous I/O?● What is LuaNode?● Demo● Guidelines● Future Improvements

Page 4: LuaNode: Asynchronous I/O for Lua

What does Asynchronous I/O mean?

Page 5: LuaNode: Asynchronous I/O for Lua

Asynchronous I/O

It is not only:● Nonblocking operations

Page 6: LuaNode: Asynchronous I/O for Lua

Asynchronous I/O

It is not only:● Nonblocking operations● Readyness

Page 7: LuaNode: Asynchronous I/O for Lua

Asynchronous I/O

It is not only:● Nonblocking operations● Readyness

It is:● Notification on operation completion

Page 8: LuaNode: Asynchronous I/O for Lua

What is LuaNode?

Page 9: LuaNode: Asynchronous I/O for Lua

What is LuaNode?

● Event driven, asynchronous IO model. (Like Node.js, nginx)

● Runs Lua code (5.1.5)● Similar to Node.js, EventMachine (Ruby),

Twisted (Python)

https://github.com/ignacio/luanode

Page 10: LuaNode: Asynchronous I/O for Lua

JavaScript (v8) + C++ + libuv = Node.js

Lua + C++ + Boost::ASIO = LuaNode

What is LuaNode?

Page 11: LuaNode: Asynchronous I/O for Lua

Boost::Asio

C++

Application Code (Lua)

Lua

Kernel

Page 12: LuaNode: Asynchronous I/O for Lua

Supported platforms

● Windows (7, 8)● Linux● OSX

Page 13: LuaNode: Asynchronous I/O for Lua

A taste of LuaNode

local function handle_request (server, request, response)

response:writeHead(200, {["Content-Type"] = "text/plain"})

response:finish("Hello World!"))

end

luanode.http.createServer(handle_request):listen(8124)

console.log("Server running at http://127.0.0.1:8124/")

process:loop()

Page 14: LuaNode: Asynchronous I/O for Lua

An example of synchronous IO

local socket = require "socket"

local function get (host, file)

local c = assert(socket.connect(host, 80))

c:send("GET " .. file .. " HTTP/1.0\r\n\r\n")

local s = c:receive("*a")

print("Received ".. #s .. " bytes.")

c:close()

end

local host = "www.w3.org"

get(host,"/TR/2002/REC-xhtml1-20020801/xhtml1.pdf")

get(host,"/TR/REC-html32.html")

Page 15: LuaNode: Asynchronous I/O for Lua

Asynchronous I/O example

local function get (host, file)

local c, l = luanode.net.createConnection(80, host), 0

c:on("connect", function()

c:on("data", function(self, data) l = l + #data end)

c:on("close", function()

console.log("Downloaded file '%s'. Received %d bytes.", file, l)

end)

c:write("GET " .. file .. " HTTP/1.0\r\n\r\n")

end)

end

get("www.w3.org","/TR/2002/REC-xhtml1-20020801/xhtml1.pdf")

get("www.w3.org","/TR/REC-html32.html")

process:loop()

Page 16: LuaNode: Asynchronous I/O for Lua

The Loop

● Provided by ASIO● Handles a queue● Completed operations are posted there● Dispatch associated callbacks

Page 17: LuaNode: Asynchronous I/O for Lua

Not only IO

Timers

setTimeout(function()

console.log("5 seconds have passed")

end, 5000)

Page 18: LuaNode: Asynchronous I/O for Lua

Not only IO

Timers

setInterval(function()

console.log("5 seconds have passed")

end, 5000)

Page 19: LuaNode: Asynchronous I/O for Lua

Not only IO

DNSluanode.dns.lookup("www.google.com",

function(ok, addrs, hostname)

console.log(luanode.utils.inspect(addrs))

end)

{ family => 4, port => 0, address => "200.40.0.90"}

Page 20: LuaNode: Asynchronous I/O for Lua

Not only IO

TTY

require "luanode.tty"

local stdin = luanode.tty.ReadStream(Stdio.stdinFD)

stdin:on("data", function(self, data)

console.log("data:", data)

end)

stdin:resume()

process:loop()

Page 21: LuaNode: Asynchronous I/O for Lua

Demo time!

Page 22: LuaNode: Asynchronous I/O for Lua

Server sent events

● Browser issue two requests that become a persistent one way connection

● The server pushes data to the browser from time to time

Page 23: LuaNode: Asynchronous I/O for Lua

Guidelines

● Stay close to Node.js● Similar API● Easy to adapt existing libraries

Page 24: LuaNode: Asynchronous I/O for Lua

What is available today?

● TCP● HTTP● HTTPS● TIMERS● TTY● REPL

Page 25: LuaNode: Asynchronous I/O for Lua

When to use?

● Stuff that is IO bound.● Simple webservers.● Test servers.● Mock services.● Exploratory programming (REPL)● Load testing.

Page 26: LuaNode: Asynchronous I/O for Lua

When not to use?

● Currently, with stuff that is CPU Bound● (Don't write servers to compute Fibonacci

numbers with it)

Page 27: LuaNode: Asynchronous I/O for Lua

Some available modules

● Redis (redis-luanode)● Socket.IO (LuaNode-Socket.IO)● OAuth (LuaOAuth)● Route66 (simple url routing, inspired by Orbit)

Page 28: LuaNode: Asynchronous I/O for Lua

Existing users (other than me :)

Moonwalk: a Swagger server implementation for Lua.

https://github.com/abadc0de/moonwalk

Xauxi: A reverse proxy

http://ia97lies.github.io/xauxi/

Page 29: LuaNode: Asynchronous I/O for Lua

Callback hell

Possible solutions?● Coroutines● Futures

Page 30: LuaNode: Asynchronous I/O for Lua

Coroutines

IssueHttpRequest(function(response)

-- deal with response

IssueDBQuery(function(result)

-- deal with result

setTimeout(function()

-- and we are done

end, 5000)

end)

end)

Page 31: LuaNode: Asynchronous I/O for Lua

Coroutines

-- makes a fake synchronous function

Sync(function(wait, yield)

IssueHttpRequest(wait)

local _, response = yield()

-- deal with response

IssueDBQuery(wait)

local result = yield()

-- deal with result

setTimeout(wait, 5000)

yield()

-- wait five seconds

--and we are done

end) -- end Sync function

Page 32: LuaNode: Asynchronous I/O for Lua

Coroutines

local function Sync(fn)

local function make_resumer(co)

return function(...)

return assert(coroutine.resume(co, ...))

end

end

local co = coroutine.create(fn)

assert( coroutine.resume(co, make_resumer(co), coroutine.yield ) )

end

Page 33: LuaNode: Asynchronous I/O for Lua

Future improvements

Page 34: LuaNode: Asynchronous I/O for Lua

Future improvements

● Documentation● Migrate to libuv● Better multicore support.● Proper File I/O● UDP support● Better coroutine integration● Multithreading

Page 35: LuaNode: Asynchronous I/O for Lua

LuaNode makes writing async code easy.

Page 36: LuaNode: Asynchronous I/O for Lua

Questions?

Page 37: LuaNode: Asynchronous I/O for Lua

Thanks!

Ignacio Burgueño - @iburgueno