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 _______________________________________________ nginx mailing list nginx@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx