8 Sep 2016

Simplify lua application inside nginx lua module

One solution to not-to-write additional applications as long as I can is, any common problem that can be solved by writing nginx module and/or nginx-lua, I will build an nginx module or a lua application for it, and re-use these module and application when it's possible

Another reason when moving to nginx instead of keep writing application then proxy_pass from nginx to it is: every engineer can install nginx within a minute in a way they compile any Linux application,  and nginx's configuration syntax is simple, straight forward and clean because of the way nginx developer designed its configuration style, now nginx supports dynamic module loading as well, once can write a module, compile .so module, give .so file to another one, load it into current nginx instance to use. 

Writing nginx module is a long story to tell and I will write about it later, but Lua module is something much simpler. Once can learn to write a simple business in Lua, plug it to nginx configuration within some minutes, like this one

And because it's simpler, one can write as many application as they can by copying and modify old source code, without re-use current existing code, even if these apps was made to solve the same problem.If we didn't manage development process, we would end-up having hundred applications with duplicated code serving the same or similar purpose. 

For example, we designed an application that processes user's request, examine its query parameters, check provided token again application policy then passing it to another backend to serve request/or return 403 Forbidden if those required conditions are not matched. It's written like this:

gearmanHost, gearmadPort, backendAddress, tokenParameter, and the next function getBucket were defined in the same source code, and it's ok so far. Next day, we need to make another application that has same function, serve the same purpose, but with different backendAddress and tokenParameter.

A not so careful guy will copy that lua script, modify values, and then configure nginx likes this:

and inside the conf/lua directory will be end-up like this:

Nginx lua modules provides 2 way to solve this problem: data sharing using Lua module model and lua_shared_dict. The difference between 2 is that the first one is memory sharing within nginx worker, that means if you have n nginx workers running, you have n copies of the same data. The latter is shared memory, which is shared among nginx workers, you can save memory by using it.

Choosing one of these solution will help you in some different situation. For example, for configuration you can choose the 1st, because configuration values wont take megabytes memory to store, and use the 2nd to store key-value runtime object, it's not persistent and will be reset once nginx restarted.

By using Lua Module model, we can rewrite the origin lua code to store configuration parameter and common function:

and whenever we need to read configuration, we just need to load conf file, and call its function

The final nginx configuration will be much more simpler:

inside app.lua you just have to determine which configuration to read based on $server_name as configuration key or some other specific nginx variable, depend on your application business logic.

No comments: