Unit 1.26.0 release
Valentin V. Bartenev
vbart at nginx.com
Fri Nov 19 22:27:28 UTC 2021
Hi,
I'm glad to announce a new release of NGINX Unit.
Please read this letter to the end, as it explains some significant changes in
the latest version. But first, I have great news for the PHP users: now the
interpreter's OPcache is shared between the processes of an app.
In previous versions, due to an architecture limitation (which imposed strong
isolation, much stronger than was sometimes needed), each PHP process had
a separate OPcache memory. As a result, with some workloads (especially
involving many dynamic processes), performance could degrade because each
new process had to warm up the cache after starting. Also, it required more
memory because the bytecode of same PHP scripts was duplicated in each process.
Now, all these flaws are finally gone.
Next, we noticed that more and more users use Unit to serve static files,
if only because it's efficient and easy to configure. Modern apps are all
dynamic, yes, but at the same time, almost all apps and websites have static
resources like images, scripts, styles, fonts, and media files. It's very
important to supply these resources as fast as possible without any delays
to smoothen the overall user experience. We take this aspect seriously and
continue improving Unit capabilities as a generic static media web server.
This time, all changes are about configuration flexibility. You may know that
nginx has a number of different directives that control static file serving:
- root
- alias
- try_files
Some of these are mutually exclusive, some can be combined, some work
differently depending on the location type. That gives the configuration
a lot of flexibility but may look a bit complicated. Users kept asking us
to provide the same functionality in Unit, but instead of just repeating
these, we thought about how we can improve this experience to make it easier
to understand without losing flexibility.
Finally, we came up with a solution. In previous versions, we introduced the
"share" directive, very similar to the "root" directive in nginx:
{
"share": "/path/to/dir/"
}
Basically, it specified the so-called document root directory. To determine
a file to serve, Unit appended the URI from the request to this "share" path.
For this request:
GET /some/file.html
The above configuration served "/path/to/dir/some/file.html".
In simple times, that's exactly what you want. Still, there are plenty of
cases when a different file needs to be served and the requested URI doesn't
match a path. More, you may want to serve a single file for any requests;
the so-called one-page apps often utilize such a scheme.
Such border cases call for a finer degree of control over the full path to
a file. As a result, we kept receiving suggestions like:
{
"share_file": "/path/to/a/file.html"
}
The idea was to specify the full path to the file instead of the document root
part only.
In parallel, we work variable support so we thought about introducing variable
paths; for instance, you may want to serve different files depending on the
normalized Host header:
{
"share_file": "/www/data/$host/app.html"
}
Sneak peek ahead: we have plans for ways to create custom variables that
extract various parts of the request using regular expressions.
Still, look at the suggested configuration:
{
"share_file": "/www/data/$uri"
}
And compare it to what we had:
{
"share": "/www/data/"
}
These configurations are essentially equal; why bother with another option
at all? Figuring in the maxim that says that explicit is often better than
implicit, this value:
"/www/data/$uri"
Is better and more self-descriptive than:
"/www/data/"
The latter only shows a part of the path, so you need to remind yourself that
the URI is appended to it. Keeping this in mind and striving to have a cleaner
configuration with fewer options to read about and to choose from, we finally
decided to alter the behaviour of the "share" option.
Starting with Unit 1.26.0, the "share" option specifies the *entire* path to a
shared file rather than just the document root. And yes, the option supports
variables, so you can write:
{
"share": "/www/data/$uri"
}
There won't be a separate "share_file" option. I used it only to illustrate
the initial idea and the resulting change; the "share" option assumes all
relevant functionality instead.
If you run previous versions of Unit and use "share" in your configurations,
an update to Unit 1.26+ will automatically append "$uri" to all your "share"
values to preserve the expected behavior.
Configurations like this:
{
"share": "/www/data/"
}
Are automatically rewritten as follows:
{
"share": "/www/data/$uri"
}
This occurs only once, after the version update. If you manage your
configurations using some scripts and store them somewhere else,
make sure to adjust the "share" values there accordingly.
Note that Unit won't fix your "share" values that you upload in reconfiguration
requests over the control socket API.
To read more about the new share behavior, check the documentation:
- https://unit.nginx.org/configuration/#static-files
I hope this transition will be easy and as hassle-free as possible for our
existing users. For new users, there is nothing to care about, just mind
that blog posts or other sources about previous Unit versions can use
configurations that rely on the discontinued "share" behavior, so make
the necessary adjustments before copying them. All docs and howtos
at the official Unit website were already updated:
- https://unit.nginx.org/howto/
Are you with me? That's not the end of news about "share". Here's one more,
and it's pretty exciting. Earlier, to implement a "try_files"-like behavior,
you had to use something like this:
{
"share": "path1"
"fallback": {
"share": "path2"
"fallback": {
"pass": "application/blog"
}
}
}
This snippet tries to serve a file using "path1"; if it doesn't exist or is
inaccessible, it falls back to "path2", and then passes the request further,
to the blog app.
Now it's much easier to configure:
{
"share": [ "path1", "path2" ]
"fallback": {
"pass": "application/blog"
}
}
The "share" directive now can accept an array of paths, trying them one by one
until a file is found. If there is no file to serve, the "fallback" action
occurs; if no fallback is defined, the result of the last try is returned.
And yes, all these paths can contain variables:
{
"share": [
"/www/$host$uri",
"/www/static$uri",
"/www/app.html"
]
}
For more examples and detailed explanations:
- https://unit.nginx.org/configuration/#static-files
In future releases, we'll introduce more variables and the ability to extract
various parts of requests and save them into your custom variables, which will
provide essentially endless flexibility to manipulate file paths.
There are some more notable features in this release as well:
1. Variables support in the "chroot" option to accompany variable-based paths
in "share" during static media serving.
Learn more about Unit's ability to chroot while serving static assets:
- https://unit.nginx.org/configuration/#path-restrictions
2. The "query" matching option to filter and route requests by arbitrary query
string values.
We already had the "arguments" option that enabled filtering and routing
requests by particular key-value pairs of query string arguments, but the query
string doesn't always fit this format. So, now you can also use regexps and
wildcard matching to work on the full query string value.
Learn more about our very flexible and elaborate request filtering and routing:
- https://unit.nginx.org/configuration/#routes
The complete change log for this release is below:
Changes with Unit 1.26.0 18 Nov 2021
*) Change: the "share" option now specifies the entire path to the files
it serves, rather than a document root directory to be prepended to
the request URI.
*) Feature: automatic adjustment of existing configurations to the new
"share" behavior when updating from previous versions.
*) Feature: variables support in the "share" option.
*) Feature: multiple paths in the "share" option.
*) Feature: variables support in the "chroot" option.
*) Feature: PHP opcache is shared between application processes.
*) Feature: request routing by the query string.
*) Bugfix: the router and app processes could crash when the requests
limit was reached by asynchronous or multithreaded apps.
*) Bugfix: established WebSocket connections could stop reading frames
from the client after the corresponding listener had been
reconfigured.
*) Bugfix: fixed building with glibc 2.34, notably Fedora 35.
Other major features that we are preparing for the next release include:
- basic statistics API for monitoring Unit instances
- various variables for different aspects of request and connection data
- customization of access log format with variables
- custom variables out of regexp captures on various request parameters
- simple request rewrite using variables
- command-line tool to simplify the use of Unit's control socket API
There probably will be even more.
To participate, share your ideas, or discuss new features, you're welcome
to visit Unit's issue tracker on GitHub:
- https://github.com/nginx/unit/issues
Stay tuned!
wbr, Valentin V. Bartenev
More information about the unit
mailing list