On December 28 of last year, we released the third beta version of NGINX Unit, our new dynamic web and application server. In this blog post, we discuss the latest changes in detail.
If you installed Unit 0.2 from our package repositories, use your package manager to upgrade. If you are performing a fresh installation, see the installation documentation at https://unit.nginx.org/installation/. (We now provide prebuilt packages for more operating systems.)
NGINX Unit is under active development. It’s likely that at the time you read this blog post, even more recent releases will be available. Check https://unit.nginx.org/CHANGES.txt for details on the latest release.
HTTP Keep-Alive
HTTP persistent connections, or HTTP keepalives, is the technology used to keep TCP connections open between requests. This reduces latency and improves website. NGINX Unit now uses keepalive connections by default (no configuration is necessary on the Unit side).
Keepalive functionality is managed by the HTTP headers Connection
and Keep-Alive
. Unit sets the keepalive timeout to 65 seconds. The value will become configurable in a future release.
When Unit is installed behind NGINX, to use HTTP keepalives you need to configure NGINX as shown below. Specifically, you need to:
- Add the
keepalive
directive in theupstream
block - Set
proxy_http_version
to1.1
so that HTTP/1.1 is used for proxying requests to the upstream servers, as required for keepalives - Remove any
Connection
headers that might be included in client requests
See the following short example of NGINX configuration with these directives in use.
http {
upstream unit {
server 127.0.0.1:8080;
keepalive 32;
}
server {
location / {
proxy_pass http://unit;
proxy_set_header Connection '';
proxy_http_version 1.1;
}
}
}
Python Virtual Environments
With Python, you can create isolated virtual environments for your applications. This feature is useful for creating multiple apps that use different versions of Python, different packages, and/or different libraries, and that need to run simultaneously on the same system. Running a virtual environment also, in many cases, eliminates the need for developers to have root
access to the system. With Unit 0.3, you can use virtual environments across multiple Python applications.
You can use the virtualenv tool to create a virtual environment. Once you create a virtual environment, you can define it with the Unit API, using the home
parameter of your application. If you did not configure PYTHONPATH
inside your virtual environment, you still need to set up the path
and home
parameters in the configuration of your application through the Unit API. They might refer to the same, or to different directories.
Here’s a sample Unit configuration:
{
"listeners": {
"*:8080": {
"application": "example-myblog"
}
},
"applications": {
"example-myblog": {
"type": "python 3",
"workers": 2,
"module": "wsgi",
"user": "nick",
"group": "nick",
"path": "/home/nick/myblog-virtualenv/scripts",
"home": "/home/nick/myblog-virtualenv"
}
}
}
This example shows how to configure the following environment:
- Unit listens on port 8080 for all IP addresses of the system
- The example-myblog application is created by the Unit administrator
- A virtual environment is created by user
nick
in the directory /home/nick/myblog-virtualenv - Python scripts are located in /home/nick/myblog-virtualenv/scripts
Alternatively, you can set both path
and home
relative to the value of working_directory
:
...
"working_directory": "/home/nick/myblog-virtualenv",
"path": "scripts",
"home": ".",
...
To change an existing application object to use virtual environments, use the Unit API to change one parameter directly. You don’t have to reload or restart the server. The current state of Unit is preserved automatically. Here’s an example:
$ curl -X PUT -d '"/home/nick/myblog-virtualenv"' --unix-socket /path/to/control.unit.sock http://localhost/applications/example-myblog/home
To display the current value of the home
parameter, send a GET
request to the API:
$ curl -X GET --unix-socket /path/to/control.unit.sock http://localhost/applications/example-myblog/home
Python atexit
The atexit module in Python defines a single function to register clean‑up functions. The functions run when an application process performs a normal shutdown. Unit now supports atexit behavior. You don’t have to change anything in the application or in Unit configuration in order to use atexit. See https://github.com/nginx/unit/issues/65 and https://github.com/nginx/unit/commit/be36cf52c8b092ebb688784a1c10626cac2138d7 for implementation details.
Go Package Changes
The Go package name for Unit has changed from unit to nginx/unit. This name is more consistent with other packages in the Go ecosystem. Prior to compiling your Go app for Unit, compile and install the package. For supported systems, you can install the unit-go package from our repositories. Then, in the source of the Go app, import the nginx/unit package, together with the net/http package:
import (
"fmt"
"net/http"
"nginx/unit"
)
Application Timeouts
Unit can now respond with an HTTP error to the client when workers exceed their execution timeout. With version 0.3, the application start time and time in the queue are no longer included in the timeout calculation.
To enable timeouts for workers, use the API to change the limits.timeout
property of the application.
$ curl -X PUT -d '{"timeout": 10}' --unix-socket http://localhost:8088/applications/example-myblog/limits
The timeout value is defined in seconds.
A full application object example with the timeout
value defined looks like the following.
{
"type": "python 3",
"workers": 2,
"module": "wsgi",
"user": "nick",
"group": "nick",
"path": "/home/nick/myblog-virtualenv/scripts",
"home": "/home/nick/myblog-virtualenv",
"limits": {
"timeout": 10
}
}
Timeouts can be enabled for all supported application languages: PHP, Python, and Go.
In larger deployments, various URLs, scripts, or workflows might need different timeout restrictions. In that case, define the different paths as different locations in the NGINX reverse proxy, then create several different applications in Unit. You can have different applications use the same directories and application files, or various directories and application files.
Number of Requests per Worker
Unit can now limit the number of requests executed in one worker process of the application. When the number is exceeded, it will restart the worker. This feature is particularly useful when applications tend to leak memory, or otherwise misbehave after too many requests.
To enable this, use the API to change the limits.requests
property of the application.
$ curl -X PUT -d '{"requests": 1000}' --unix-socket http://localhost:8088/applications/example-myblog/limits
A full application object example, with the number of requests per worker enabled, looks like the following.
{
"type": "python 3",
"workers": 2,
"module": "wsgi",
"user": "nick",
"group": "nick",
"path": "/home/nick/myblog-virtualenv/scripts",
"home": "/home/nick/myblog-virtualenv",
"limits": {
"timeout": 10,
"requests": 1000
}
}
This limit can be enabled for all supported application languages: PHP, Python, and Go.
Miscellaneous
In addition to the features described above, we added a number of smaller bug fixes and minor changes. These include:
- Precompiled packages for more operating systems in our repositories:
- CentOS 6
- CentOS 7
- Debian 8 (Jessie)
- Debian 9 (Stretch)
- Ubuntu 16.04
- Ubuntu 17.04
- Ubuntu 17.10
- Various Go package improvements that simplify the code and increase performance through better integration between Unit’s C code and the Go code.
- The Unit version is now verified in the Go package to avoid incompatible package usage.
- Improved application worker selection, request canceling, and request rescheduling. A new algorithm minimizes request‑processing latency.
- Addition of a new testing framework. With this release, Unit has a number of functionality tests that we run regularly. See them in the test directory in the repositories. We will be regularly adding more tests to improve test coverage in future.
If you want to see where the project is going and read the roadmap, take a look at the Progress and Next Steps blog post.
The full changelog for Unit development is available in the source code repositories https://hg.nginx.org/unit/file/tip/CHANGES, https://github.com/nginx/unit/blob/master/CHANGES, and the Unit documentation website: https://unit.nginx.org/CHANGES.txt.
Watch our code repository on GitHub and join the discussions and development: https://github.com/nginx/unit.
If you wish to become a full‑time engineer for NGINX, check our job board.