The OpenResty distribution for Nginx
Secret Agent's Suitcase
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 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.
Table 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.
Infos
- OpenResty: http://openresty.org/
- "Nginx" by Jeremy Garcia, Linux Pro Magazine , issue 107, October 2009, pg. 28: http://www.linuxpromagazine.com/Issues/2009/107/Nginx
- "Lua for Apache" by Tim Schürmann, ADMIN , issue 09, pg. 42: http://www.admin-magazine.com/Articles/Lua-for-Apache/
- TechEmpower benchmarks: http://www.techempower.com/benchmarks/
- Puppet module for OpenResty: https://github.com/propertybase/puppet-openresty
- Chef cookbook for OpenResty: http://community.opscode.com/cookbooks/openresty
- Simple API with Nginx and PostgreSQL: http://rny.io/nginx/postgresql/2013/07/26/simple-api-with-nginx-and-postgresql.html
- Nginx WebSockets: http://nginx.org/en/docs/http/websocket.html
- WebSockets with OpenResty: https://medium.com/p/1778601c9e05