Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Nginx and Lua (mixlr.com)
61 points by transmit101 on Sept 1, 2012 | hide | past | favorite | 26 comments



Different application area but we implemented Lua into a MUD (online RPG) as the scripting interface for all area builder development and it was probably the single most valuable change we ever made. Check out the 'lua coding' section on Aardwolf.com if you want to see some examples. Over 200,000 lines of lua now, millions of prog executions per hour and still as fast as ever.


Can you provide us with an idea of how much this improved performance or how many more requests it allowed you to handle? Were there time or cost savings compared to alternative approaches?


There's no single self-contained solution in the post really, it's more an illustration of a number of useful things that Lua can be used for. I might try to put another post together at some stage though.

For us our main goal is to prevent the majority of requests from even reaching the Rails stack. We've done this by introducing full page caching across the site, for both logged in and logged out users. This means that only a small percentage of requests at peak times need to touch Rails or any database at all - everything is served by Nginx.

This hasn't been without its challenges. The last section of this post might give a clue as to how we've solved the most difficult ones. I will think about a post tackling this whole subject but I need to think about how to get it across, it's not easy.


Yeah, we're using this to map hosts->upstream servers/redirects in a redis DB, and then there's no need for managing vhost files to add/remove/scale sites (or adding/swapping nginx servers). Writing code instead of config files is very powerful


It is non-blocking and executed within Nginx itself so it is supposed to be very fast. The Lua work has been done by Chinese engineers from Taobao and Weibo which obviously get a huge amount of traffic.


I didn't know about the Weibo connection.

It is a very fast module, and non-blocking, but just as importantly it provides the flexibility to avoid sending requests from Nginx to slow backend servers (Ruby, Python, whatever) at all. In real-life situations, this is the most important bit.

As I said in another thread, we've done some good work to tie this in with our Rails app. We now page cache almost every important request, even for logged in users. This means Rails and our databases are protected from most spikes of traffic. I would like to write a post describing this in more detail, I need to think how to get it across though.


There is an introductory talk (video and slides) from the London Lua meetup group on Nginx and Lua here http://www.londonlua.org/scripting_nginx_with_lua/index.html


This is a very good talk. Thanks for posting.


Is there any reason in principle why this has to be done with Lua and not with other interpreted languages?

Once you are writing interpreted code which reads request data and interacts with Redis you are not that far from what a normal Ruby or Python web app does anyway.


1. Lua is designed to be embedded, it is much easier than trying to embed Ruby or Python into a web server. 2. It is a way off an app as it runs in the same process as the web server. 3. Lua is very small and very fast, so it is fine to use it just for doing tiny things like reading cookies, there is no real overhead (most people use LuaJIT so it is compiled anyway). Remember that the point of many of these examples is to offload from Ruby as it is too slow...

Also, Lua is a very nice language, easy to learn (there is not much of it), and most of the functionality exposed is simply the built in functionality of nginx (async http), plus some libraries, so having the libraries that come with other languages is not that useful as you can't use anything blocking (like with Node) inside Nginx.


I don't question that Lua is a nice language, but it seems to be repeatedly implied in this thread that it is not possible to do this with other languages, although there doesn't appear to be any evidence for that.

Embedding Python in a web server is quite doable and has nothing to do with having libraries available.

I'm really not seeing why everyone should switch to Lua for these tasks. That is quite different from saying that people who like Lua shouldn't use it.


The libraries thing is just you dont need the libraries, which are the main advantage.

Python is a 3MB binary, while Lua is 175k, for a start. This is for Nginx which is 960k. Embedding something three times the size of the host is not really an embed...

Lua is embedded in all sorts of stuff, Nginx, Apache, Redis in web space for example. Python is a great language, but just not a good choice for that.

But feel free to give a Python embed a go.


Two reasons:

1. Lua is very easy to embed into C code. Python and Ruby, not even in the same ball park ... 2. This nginx+lua config is often implemented using LuaJIT. Luajit is the fastest dynamic language. it's speed is very close to Java's in many cases. So, very little performance penalty..


Are there real numbers showing that the Python interpreter's performance would be unsuitable for this purpose? (How about pypy's, since JIT seems to be one of the keywords here?)

Or has it been decided (as if a priori) that Lua is the only workable solution?


Is Python unsuitable? No, it can probably be made to work. It is just a question of performance, and effort needed to integrate it.

Will a Python implementation run slower and use more memory than a Lua one? Probably.

what other requirements were you thinking of that would be helped with a Python implementation?

You don't need to be afraid of Lua. It is a nice little language, kind of like a Scheme wrapped in a Python syntax.


Our main goal is to avoid passing requests upstream to Rails, which has massive performance penalties (TCP/IP, probably multiple database hits, web servers written in Ruby).

By keeping everything non-blocking and inside the Nginx event loop, and cutting the upstream out entirely, we are making a massive saving on each request. This definitely outweighs a small performance penalty incurred for using LuaJIT.


I'm no Ruby expert, but I think the massive performance penalties of Rails are mostly not in the Ruby interpreter itself. Rails is a huge project and it does a lot of work.

It is possible that Ruby is impracticably slow in itself, I guess.

Keeping things non-blocking and inside the Nginx event loop doesn't specifically mean you have to use Lua, does it?


I'm not really sure what point you're trying to make. Are you saying that it's not desirable to reduce the load on your backend web servers?

I'm neither a Lua expert nor an evangelist, but my clear impression is that Lua is much more suited to embedding in a web server than Ruby or Python. On the Lua website it is described as "a powerful, fast, lightweight, embeddable scripting language" - that's not a description I would ascribe to either Ruby or Python. I also know that Lua has a long history of being embedded in games, embedded systems and other servers like Redis. Perhaps somebody more experienced in Lua can help me out here though.

In this case there seems to be good evidence that Lua is the right tool for the job.

One minor point- in your first comment you talk about interpreted Lua code, but this is not accurate because Lua can be compiled down to byte code before being loaded into Nginx.

Finally - "Embedding Python in a web server is quite doable". I would be interested to read a blog post about your experiments in this area ;)


I love Ruby. It is my favourite language by far. And I strongly believe that it is possible to do a Ruby implementation that is fast enough for most uses.

But current implementations are slow. And there are a lot of things in the language that makes a fast implementation hard. For example the fact that class definitions are executable and can be re-opened at any time, including by passing a string to eval(). They combine to make it extremely hard to make method calls fast. And since pretty much everything is method calls in Ruby, that's not good.

As an example, a Ruby implementation has to be able to deal with code that might overload the + method for integers, so even basic stuff like integer additions can't be statically inlined without precautions to handle cases like that.

I'd say for what they're doing, with tiny little rewrites in Nginx, Lua might be better suited - the Lua implementation is known for being extremely fast.


So the idea is interesting, but I think adding something like this onto Nginx could lead to problems in the future.

For what you're trying to do, I feel like implementing your reverse proxy in Go may prove to be less prone to errors. Go has ReverseProxy stuff already built in: http://golang.org/pkg/net/http/httputil/#ReverseProxy

Go already has a pretty strong following doing near exactly what you are doing here with Nginx + Lua. But that would require learning a new language and screwing with infrastructure, which always is a giant pain.


Nginx is "battle tested" as one of the most used web servers, particularly as a reverse proxy. Lua is battle tested as an embedded language for just this type of thing.

In comparison, Go is a pretty much unknown quantity.

I'm curious as to what problems you think that this might lead to that aren't just as likely or more likely with a Go based implementation.


Go is the only other way I would try to do this type of thing. Nginx has the advantage that a lof of people already have it in their stack so adding some bits of Lua incrementally is easy, while with Go you would be adding another piece of infrastructure.

I don't think there are any problems, or that it is error prone. Most people are learning a new language with Lua, so take your choice.


I don't know anything about Go but your idea sounds feasible.

As another commenter says, there is a large Nginx community and we have a lot of investment in Nginx already. But for somebody starting from scratch it may be worth considering.


Bit off topic but you might want to 301 redirect to the right page instead of just disallowing search engines on your subdomains. This way if someone links to the wrong page you will still get the link juice.

I might have misunderstood that first bit though, since it looks like you do redirect anyway.


I can imagine a scenario where we wanted a sub-domain which didn't redirect, but also wasn't crawlable. But I agree the example is a little bit contrived ;)


It's nice to see how tight the lua integration into nginx is. It reminds me of Apache and mod_perl.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: