nuster
Wiki | English | 中文 | 日本語
A high-performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy.
Table of Contents
Introduction
Performance
Getting Started
Usage
Directives
Cache
NoSQL
Manager
Stats
Enable disable rules
Update ttl
Purging
Store
Sample fetches
FAQ
Introduction
nuster is a high-performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy. It is 100% compatible with HAProxy and takes full advantage of the ACL functionality of HAProxy to provide fine-grained caching policy based on the content of request, response or server status.
Features
As HTTP/TCP loader balancer
nuster can be used as an HTTP/TCP load balancer just like HAProxy.
All features of HAProxy are inherited, 100% compatible with HAProxy
Load balancing
HTTPS supports on both frontend and backend
HTTP compression
HTTP rewriting and redirection
HTTP fixing
HTTP2
Monitoring
Stickiness
ACLs and conditions
Content switching
As HTTP cache server
nuster can also be used as an HTTP proxy cache server like Varnish or Nginx to cache dynamic and static HTTP response.
All features from HAProxy(HTTPS, HTTP/2, ACL, etc)
Extremely fast
Powerful dynamic cache ability
Based on HTTP method, URI, path, query, header, cookies, etc
Based on HTTP request or response contents, etc
Based on environment variables, server state, etc
Based on SSL version, SNI, etc
Based on connection rate, number, byte, etc
Cache management
Cache purging
Cache stats
Cache TTL
Disk persistence
As RESTful NoSQL cache server
nuster can also be used as a RESTful NoSQL cache server, using HTTP POST/GET/DELETE to set/get/delete Key/Value object.
It can be used as an internal NoSQL cache sits between your application and database like Memcached or Redis as well as a user-facing NoSQL cache that sits between end-user and your application. It supports headers, cookies, so you can store per-user data to the same endpoint.
All features from HAProxy(HTTPS, HTTP/2, ACL, etc)
Conditional cache
Internal KV cache
User facing RESTful cache
Support any kind of data
Support all programming languages as long as HTTP is supported
Disk persistence
Performance
nuster is very fast, some test shows nuster is almost three times faster than nginx when both using single core, and nearly two times faster than nginx and three times faster than varnish when using all cores.
See detailed benchmark
Getting Started
Download
Download stable version from Download page for production use, otherwise git clone the source code.
Build
- ``` sh
- make TARGET=linux-glibc USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1
- make install PREFIX=/usr/local/nuster
- ```
use USE_PTHREAD_PSHARED=1 to use pthread lib
omit USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1 if unnecessary
See HAProxy INSTALL for details.
Create a config file
A minimal config file: nuster.cfg
- ``` sh
- global
- nuster cache on data-size 100m
- nuster nosql on data-size 200m
- master-worker # since v3
- defaults
- mode http
- frontend fe
- bind *:8080
- #bind *:4433 ssl crt example.com.pem alpn h2,http/1.1
- use_backend be2 if { path_beg /_kv/ }
- default_backend be1
- backend be1
- nuster cache on
- nuster rule img ttl 1d if { path_beg /img/ }
- nuster rule api ttl 30s if { path /api/some/api }
- server s1 127.0.0.1:8081
- server s2 127.0.0.1:8082
- backend be2
- nuster nosql on
- nuster rule r1 ttl 3600
- ```
nuster listens on port 8080 and accepts HTTP requests. Requests start with /_kv/ go to backend be2, you can make POST/GET/DELETE requests to /_kv/any_key to set/get/delete K/V object. Other requests go to backend be1, and will be passed to servers s1 or s2. Among those requests, /img/* will be cached for 1 day and /api/some/api will be cached for 30 seconds.
Start
/usr/local/nuster/sbin/nuster -f nuster.cfg
Docker
- ``` sh
- docker pull nuster/nuster
- docker run -d -v /path/to/nuster.cfg:/etc/nuster/nuster.cfg:ro -p 8080:8080 nuster/nuster
- ```
Usage
nuster is based on HAProxy, all directives from HAProxy are supported in nuster.
Basic
There are four basic section s: global, defaults, frontend and backend as you can find out in the above config file.
global
defines process-wide and often OS-specific parameters
nuster cache on or nuster nosql on must be declared in this section in order to use cache or nosql functionality
defaults
defines default parameters for all other frontend, backend sections
and can be overwritten in specific frontend or backend section
frontend
describes a set of listening sockets accepting client connections
backend
describes a set of servers to which the proxy will connect to forward incoming connections
nuster cache on or nuster nosql on must be declared in this section
nuster rule must be declared here
You can define multiple frontend or backend sections. If nuster cache|nosql off is declared or no nuster cache|nosql on|off declared, nuster acts just like HAProxy, as a TCP and HTTP load balancer.
Although listen is a complete proxy with its frontend and backend parts combined in one section, you cannot use nuster in listen, use frontend and backend pairs.
You can find HAProxy documentation in /doc, and Online HAProxy Documentation
As TCP loader balancer
- ``` sh
- frontend mysql-lb
- bind *:3306
- mode tcp
- default_backend mysql-cluster
- backend mysql-cluster
- balance roundrobin
- mode tcp
- server s1 10.0.0.101:3306
- server s2 10.0.0.102:3306
- server s3 10.0.0.103:3306
- ```
As HTTP/HTTPS loader balancer
- ``` sh
- frontend web-lb
- bind *:80
- #bind *:443 ssl crt XXX.pem
- mode http
- default_backend apps
- backend apps
- balance roundrobin
- mode http
- server s1 10.0.0.101:8080
- server s2 10.0.0.102:8080
- server s3 10.0.0.103:8080
- #server s4 10.0.0.101:8443 ssl verify none
- ```
As HTTP cache server
- ``` sh
- global
- nuster cache on data-size 200m
- frontend fe
- bind *:8080
- mode http
- default_backend be
- backend be
- mode http
- nuster cache on
- nuster rule all
- server s1 127.0.0.1:8081
- ```
As RESTful NoSQL cache server
- ``` sh
- global
- nuster nosql on data-size 200m
- frontend fe
- bind *:8080
- mode http
- default_backend be
- backend be
- nuster nosql on
- mode http
- nuster rule r1 ttl 3600
- ```
Directives
global: nuster manager
syntax:
nuster manager on|off [uri URI] [purge-method method]
default:off
context:global
Enable manager/stats/purge API, define the endpoint and purge method.
By default, it is disabled. When it is enabled, remember to restrict the access(see FAQ ).
See Manager for details.
uri
Define endpoint URI, /nuster by default.
purge-method
Define a customized HTTP method to purge, it is PURGE by default.
global: nuster cache|nosql
syntax:
nuster cache on|off [data-size size] [dict-size size] [dir DIR] [dict-cleaner n] [data-cleaner n] [disk-cleaner n] [disk-loader n] [disk-saver n] [clean-temp on|off] [always-check-disk on|off]
nuster nosql on|off [data-size size] [dict-size size] [dir DIR] [dict-cleaner n] [data-cleaner n] [disk-cleaner n] [disk-loader n] [disk-saver n] [clean-temp on|off] [always-check-disk on|off]
default:none
context:global
Determines whether to use cache/nosql or not.
A memory zone with a size of data-size + dict-size will be created.
Except for temporary data created and destroyed within a request, all cache related data including HTTP response data, keys and overheads are stored in this memory zone and shared between all processes. If no more memory can be allocated from this memory zone, new requests that should be cached according to defined rules will not be cached unless some memory is freed. Temporary data are stored in a memory pool which allocates memory dynamically from system in case there is no available memory in the pool. A global internal counter monitors the memory usage of all HTTP response data across all processes, new requests will not be cached if the counter exceeds data-size.
data-size
Determines the size of the memory zone along with dict-size.
It accepts units like m, M, g and G. By default, the size is 1024 * 1024 bytes, which is also the minimal size.
dict-size
Determines the size of memory used by the hash table.
It accepts units like m, M, g and G. By default, the size is 1024 * 1024 bytes, which is also the minimal size.
Note that it only decides the memory used by hash table buckets, not keys. In fact, keys are stored in the memory zone which is limited by data-size.
dict-size(number of buckets)is different from number of keys. New keys can still be added to the hash table even if the number of keys exceeds dict-size(number of buckets) as long as there is enough memory.
Nevertheless, it may lead to a potential performance drop if number of keys is greater than dict-size(number of buckets). An approximate number of keys multiplied by 8 (normally) as dict-size should be fine. Basically, the bigger the better.
Enable stats API and check following stats:
- ``` sh
- dict.nosql.length: 131072
- dict.nosql.used: 0
- ```
If dict.nosql.used is greater than dict.nosql.length, then increase dict-size would be a good idea.
dict-size will be removed in a future release, automatically resizing the hash table in the first version will be added back.
dir
Specify the root directory of the disk persistence. This has to be set in order to use disk persistence.
If chroot is also set, the real directory is chroot+dir. For example
- ``` sh
- chroot /data
- nuster cache on dir /cache
- ```
Cache is saved to /data/cache
dict-cleaner
Prior to v2.x, manager tasks like removing invalid cache data, resetting dict entries are executed in iterations in each HTTP request. Corresponding indicators or pointers are increased or advanced in each iteration.
In v3.x these tasks are moved to the master process and also done in iterations, and these parameters can be set to control the number of times of certain task during one iteration.
During one iteration no more than dict-cleaner entries are checked, invalid entries will be deleted (by default, 1000).
data-cleaner
During one iteration no more than data-cleaner data are checked, invalid data will be deleted (by default, 1000).
When the invalid data ratio is greater than 20%, an internal mechanism will speed up the clean process, so it is recommended not to change this from the default value.
disk-cleaner
If disk persistence is enabled, data are stored in files. These files are checked by master process and will be deleted if invalid, for example, expired.
During one iteration no more than disk-cleaner files are checked, invalid files will be deleted (by default, 100).
disk-loader
After the start of nuster, master process will load information about data previously stored on disk into memory.
During one iteration no more than disk-loader files are loaded(by default, 100).
If USE_THREAD is used, a separate thread will be created to load disk files and this parameter is ignored.
disk-saver
Master process will save disk sync cache data periodically.
During one iteration no more than disk-saver data are checked and saved to disk if necessary (by default, 100).
See Store for details.
clean-temp on|off
Under the directory defined by dir, a temporary directory .tmp will be created to store temporary files.
Use this option to determine whether or not to remove those temporary files on startup.
By default, it is off.
always-check-disk on|off
The initial load of cached data on disk only happens on startup and has such if running in a scenario where the disk is shared across multiple instances, it can lead to missed cache calls. Using this option, the disk is always checked for the cached data.
By default, it is off.
proxy: nuster cache|nosql
syntax:
nuster cache [on|off]
nuster nosql [on|off]
default:on
context:backend
Determines whether or not to use cache/nosql on this proxy, additional nuster rule should be defined. If there are filters on this proxy, put this directive after all other filters.
proxy: nuster rule
syntax:
nuster rule name [key KEY] [ttl auto|TTL] [extend EXTEND] [wait on|off|TIME] [use-stale on|off|TIME] [inactive off|TIME] [code CODE] [memory on|off] [disk on|off|sync] [etag on|off] [last-modified on|off] [if|unless condition]
default:none
context:backend
Define rule to specify cache/nosql creating conditions, properties. At least one rule should be defined.
- ``` sh
- nuster cache on
- # cache request `/asdf` for 30 seconds
- nuster rule asdf ttl 30 if { path /asdf }
- # cache if the request path begins with /img/
- nuster rule img if { path_beg /img/ }
- # cache if the response header `cache` is `yes`
- acl resHdrCache res.hdr(cache) yes
- nuster rule r1 if resHdrCache
- ```
It is possible and recommended to declare multiple rules in the same section. The order is important because the matching process stops on the first match.
- ``` sh
- acl pathA path /a.html
- nuster cache on
- nuster rule all ttl 3600
- nuster rule path01 ttl 60 if pathA
- ```
rule path01 will never match because the first rule will cache everything.
name
Define a name for this rule. Must be globally unique since v5.
key KEY
Define the key for cache/nosql, it takes a string combined by following keywords with . separator:
method: http method, GET/POST...
scheme: http or https
host: the host in the request
uri: first slash to end of the url
path: the URL path of the request
delimiter: '?' if query exists otherwise empty
query: the whole query string of the request
header_NAME: the value of header NAME
cookie_NAME: the value of cookie NAME
param_NAME: the value of query NAME
body: the body of the request
The default key of CACHE is method.scheme.host.uri, and default key of NoSQL is GET.scheme.host.uri.
Example
- ``` sh
- GET http://www.example.com/q?name=X&type=Y
- http header:
- GET /q?name=X&type=Y HTTP/1.1
- Host: www.example.com
- ASDF: Z
- Cookie: logged_in=yes; user=nuster;
- ```
Should result:
method: GET
scheme: http
host: www.example.com
uri: /q?name=X&type=Y
path: /q
delimiter: ?
query: name=X&type=Y
header_ASDF: Z
cookie_user: nuster
param_type: Y
body: (empty)
So default key produces GET\0http\0www.example.com\0/q?name=X&type=Y\0, and `key method.scheme.h