Tools OpenResty Lead image: Lead Image © Kirill Kurashov, 123RF.com
Lead Image © Kirill Kurashov, 123RF.com
 

The OpenResty distribution for Nginx

Secret Agent's Suitcase

Event-based request processing makes Nginx an agile web server. With the OpenResty packages, it becomes a fast application server based on the Lua scripting language. By Oliver Frommel

OpenResty [1] is the Nginx server [2] bundled with many useful modules. Developed almost single-handedly by Yichun "agentzh" Zhang while living and working in Beijing, China, then San Francisco, California, OpenResty converts Nginx into a superfast web application server.

The majority of OpenResty comprises modules for the Lua scripting language, which is popular as an embedded language because of its low resource consumption and good performance. The Apache web server has also added Mod-Lua to its core distribution [3].

The OpenResty modules make it possible to use Lua instructions in the configuration files. This allows for complex and dynamic configurations, which can be used, say, to implement web services. The distribution includes some modules for integrating memcache and databases such as MySQL/Drizzle, PostgreSQL, and Redis.

Lua Included

With OpenResty, Lua scripts can intervene in all stages of processing and editing an HTTP request, creating responses, and modifying headers. The combination of Lua and Nginx and the event-based request processing characteristic of Nginx places OpenResty high in TechEmpower's web framework benchmarks (Figure 1) [4], and it is even faster with the Lua just-in-time compiler (LuaJIT) included with OpenResty.

OpenResty ranked among the top in TechEmpower benchmarks.
Figure 1: OpenResty ranked among the top in TechEmpower benchmarks.

OpenResty is not included with the popular Linux distributions; in other words, you need to build it from the source code. To do this, you also need to install some packages and libraries: Perl 5.6.1 or later, libreadline, libpcre, and libssl. Then, download the source package from the OpenResty site, unzip it and run ./configure, preferably with the --with-luajit option.

By default, the modules for the Drizzle, PostgreSQL, and Iconv databases are also disabled. You can enable them with the appropriate configure options if need be;

./configure --help

reveals more details. Although the binaries and modules are built with make, OpenResty has no make install, which is why it is advisable to get the checkinstall package and then install OpenResty using:

checkinstall make install

The installed files can then be removed, if not needed, using your distribution's package manager.

Manual Installation

By default, the Nginx files are installed in /usr/local/openresty. If you do not want this, you can choose a different directory using the --prefix configure option. However, the default setting is not bad, because it does not collide with any Nginx packages installed by your Linux distribution. The last task is to run the Nginx server at boot time, which the two configuration files in Listing 1 (Upstart) and Listing 2 (systemd) do for you. A call to nginx -t checks the configuration before the server process starts. If an error occurs, nginx -V gives you an overview of the existing modules.

Listing 1: /etc/init/openresty.conf (Upstart)

01 # openresty
02
03 description "nginx openresty stack"
04 author "Oliver Frommel <ofrommel@gmail.com>"
05
06 start on (filesystem and net-device-up IFACE=lo)
07 stop on runlevel [!2345]
08
09 env DAEMON=/usr/local/openresty/nginx/sbin/nginx
10 env PID=/var/run/nginx.pid
11
12 expect fork
13 respawn
14 respawn limit 10 5
15
16 pre-start script
17         $DAEMON -t
18         if [ $? -ne 0 ]
19                 then exit $?
20         fi
21 end script
22
23 exec $DAEMON

Listing 2: /lib/systemd/system/nginx.service (systemd)

01 [Unit]
02 Description=OpenResty Stack for Nginx
03 After=syslog.target network.target remote-fs.target nss-lookup.target
04
05 [Service]
06 Type=forking
07 PIDFile=/var/run/nginx.pid
08 ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t
09 ExecStart=/usr/local/openresty/nginx/sbin/nginx
10 ExecReload=/bin/kill -s HUP $MAINPID
11 ExecStop=/bin/kill -s QUIT $MAINPID
12 PrivateTmp=true
13
14 [Install]
15 WantedBy=multi-user.target

By the way, modules for well-known configuration management software are also available that help you deploy OpenResty on servers. For example, GitHub has some modules for Puppet [5], a Chef recipe can be found directly on the Opscode site [6]. The Chef module is well maintained and was last updated in early November 2013.

In the simplest case, it is now possible to embed Lua code directly in the configuration files using the content_by_lua keyword:

content_by_lua '
   ngx.say("test")
';

Lua also handles request rewrites or authentication with rewrite_by_lua: Similarly, rewrite_by_lua_file and content_by_lua_file load Lua code from a file. In this case, the web server normally loads the Lua code only once, which clearly reduces overhead. To disable this behavior (e.g., if you are developing scripts), set lua_code_cache to off.

You can achieve similar results without Lua code, as an example by Richard Nyström shows [7]; it implements a web service with SQL statements in the Nginx configuration.

For example, the following snippet from the configuration returns all the articles in a database for a GET request:

postgres_query  HEAD GET "SELECT * FROM articles";

Often the interesting data does not reside directly on the web server but is outsourced to other computers that run a directory service, a database, or the like.

OpenResty supports such service-oriented architectures (SOAs) by means of subrequests. Thus, an incoming HTTP request triggers further requests that obtain the missing data, either from other computers or services on a server that is running Nginx. An example of this is the Auth-Request module, which uses subrequests for authentication.

This approach allows a modular access protection design and combinations of various services:

location /private/ {
  auth_request /auth;
   ...
}

Even parallel subrequests can be issued if you call capture_multi. At a lower level, an interface equivalent to the Lua TCP API works directly with network sockets, but it is non-blocking by default.

Real-time web applications are no problem with OpenResty. They can be used, for example, with WebSocket support – the stable version [8] of which (v1.4.0) was added to Nginx. However, this downgrades Nginx to a WebSocket proxy. Something else has to process the data. With OpenResty, a Lua module could handle this. Because socket programming is relatively uncomplicated, you can achieve this with a few lines of code. Aapo Talvensaari demonstrates how to do this in his blog [9].

An interesting module, ngx_echo, is well suited for debugging or developing web applications or services. It extends the configuration vocabulary to include shell-like instructions such as echo, sleep, time, and exec. This means you can set up URLs to test clients without needing to write error-prone code on the server, as in this example application:

location /echodelay {
        echo hello;
        echo_flush;
        echo_sleep 2.5;
        echo world;
      }

First, the block of code returns the hello string, which immediately becomes visible after flushing the output buffer echo_flush. The server then waits 2.5 seconds before it continues to output world.

Describing the many opportunities OpenResty offers for programming with Lua is well beyond the scope of this article; however, you can gain an overview of all the supplied modules in Table 1.

Tabelle 1: OpenResty Modules

Module

Function

ArrayVarNginxModule

Array variables for Nginx configuration files

AuthRequestNginxModule

Authentication with subrequests

CoolkitNginx

Module collection with small Nginx add-ons

DrizzleNginx

Connector for Drizzle and MySQL databases

EchoNginxModule

Shell-style utilities for debugging

EncryptedSessionNginxModule

Encrypted session data

FormInputNginxModule

Processing of forms in the Nginx configuration

HeadersMoreNginxModule

Advanced header processing

IconvNginxModule

Conversion of character sets

StandardLuaInterpreter

Standard Lua interpreter

MemcNginxModule

Memcached protocol

Nginx

Nginx distribution

NginxDevelKit

Nginx SDK

LuaCjsonLibrary

Fast JSON module for Lua

LuaJIT

Just-in-time compiler for Lua

LuaNginxModule

Lua module for Nginx

LuaRdsParserLibrary

Parser for Resty DBD stream in database modules

LuaRedisParserLibrary

Parser for Redis responses

LuaRestyDNSLibrary

DNS library

LuaRestyLockLibrary

Nonblocking mutex locks

LuaRestyMemcachedLibrary

Driver for memcached

LuaRestyMySQLLibrary

Driver for MySQL

LuaRestyRedisLibrary

Driver for Redis

LuaRestyStringLibrary

String library

LuaRestyUploadLibrary

Library for HTTP uploads

LuaRestyWebSocketLibrary

Library for WebSockets

PostgresNginxModule

Connector for PostgreSQL

RdsCsvNginxModule

Converts Resty-DBD streams to CSV format

RdsJsonNginxModule

Converts Resty-DBD streams to JSON

RedisNginxModule

Redis module; provides processed responses

Redis2NginxModule

Redis module; provides unprocessed responses

SetMiscNginxModule

Various settings (MD5, JSON, etc.)

SrcacheNginxModule

Transparent caching

XssNginxModule

Support for cross-site Ajax requests

Conclusions

If you already use Nginx or are thinking about switching horses, you should definitely take a look at OpenResty.

It not only contains the standard modules, but also a number of useful extensions – mostly with the Lua scripting language – that can be learned easily. This means that even complicated web service setups are no problem, and high performance is guaranteed.