From the start, our vision for Unit was versatility, speed, and reliability. Here’s how we tackle these goals.
- The entire configuration is managed dynamically over HTTP via a friendly RESTful JSON API.
- Updates to the configuration are performed granularly at runtime with zero interruption.
- Requests are routed between static content, upstream servers, and local apps.
- Request filtering and dispatching uses elaborate matching rules that allow regular expressions.
- Apps in multiple languages and language versions run side by side.
- Common language-specific APIs for all supported languages run seamlessly.
- Upstream server groups provide dynamic load balancing using a weighted round-robin method.
- Originating IP identification
X-Forwarded-Forand similar header fields.
- Requests are asynchronously processed in threads with efficient event loops (epoll, kqueue).
- Syscalls and data copy operations are kept to a necessary minimum.
- 10,000 inactive HTTP keep-alive connections take up only a few MBs of memory.
- Router and app processes rely on low-latency IPC built with lock-free queues over shared memory.
- Built-in statistics provide insights into Unit’s performance.
- The number of per-app processes is defined statically or scales preemptively within given limits.
- App and instance usage statistics are collected and exposed via the API.
- Multithreaded request processing is supported for Java, Perl, Python, and Ruby apps.
Security & Robustness§
- Client connections are handled by a separate non-privileged router process.
- Low-resource conditions (out of memory or descriptors) and app crashes are handled gracefully.
- SSL/TLS with SNI, session cache and tickets is integrated (OpenSSL 1.0.1 and later).
- Different apps are isolated in separate processes.
- Apps can be additionally containerized with namespace and file system isolation.
- Static file serving benefits from chrooting, symlink and mount point traversal restrictions.
Supported App Languages§
Unit interoperates with:
- Binary-compiled languages in general: using the embedded libunit library.
- Go: by overriding the http module.
- Java: by using the Servlet Specification 3.1 and WebSocket APIs.
- Perl: by using PSGI.
- PHP: by using a custom SAPI module.
- Python: by using WSGI or ASGI with WebSocket support.
- Ruby: by using the Rack API.