The Wiki | English | Chinese | Japan

High-performance HTTP cache server and RESTful NoSQL cache server based on HAProxy.

Chinese version may not be updated in time, please refer to English version readme.md for the latest version

directory

introduce

NuSTER is a high-performance HAProxy-based HTTP cache server and RESTful NoSQL cache server that is fully compatible with HAProxy and utilizes HAProxy’s ACL function to provide very detailed cache rules.

features

HTTP/TCP load balancer

NuSTER can be used as an HTTP/TCP load balancer.

  • Inheriting all features of HAProxy, fully compatible with HAProxy
  • Load balancing
  • HTTPS on the front and back ends
  • HTTP compression
  • HTTP rewrite redirection
  • Add or delete HTTP messages
  • HTTP2
  • monitoring
  • viscous
  • Access control
  • Content switch

HTTP cache server

NuSTER can also be used as an HTTP cache server such as Varnish or Nginx to cache dynamic or static HTTP resources.

  • All features of HAProxy (HTTPS, HTTP/2, ACL, etc)
  • Very fast
  • Powerful dynamic caching
    • 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
  • The cache to clear
  • Cache statistics
  • Cache lifetime

RESTful NoSQL cache server

NuSTER can also be used as a RESTful NoSQL cache server to add /GET/DELETE keys/values using HTTP POST/GET/DELETE.

It can be used between applications and databases as an internal KV cache, like Memcached or Redis, or between users and applications as user-facing NoSQL. Supports headers, cookies, etc., so you can store different user data in the same way.

  • All features of HAProxy (HTTPS, HTTP/2, ACL, etc)
  • Conditional caching
  • Internal KV cache
  • User-oriented caching
  • Supports any type of data
  • Support for all programming languages, no specific libraries required, just HTTP support

performance

Very fast, 3 times as fast as Nginx in single-process mode, 2 times as fast as Nginx in multi-process mode, and 3 times as fast as Varnish.

See the benchmark

Getting started guide

download

For production environments, Download the latest stable version from Download and git Clone for other environments.

compile

Make TARGET=linux2628 USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1 make install PREFIX=/usr/local/nusterCopy the code

Add USE_PTHREAD_PSHARED=1 to use pthread

If no, delete USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1

For details, see HAProxy README.

The configuration file

Prepare a configuration file: nuster.cfg

global
    nuster cache on data-size 100m uri /_nuster
    nuster nosql on data-size 200m
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
Copy the code

Nuster listens on port 8080 and accepts HTTP requests. Requests starting with /_kv/ are allocated to backend BE2. HTTP POST, GET, or DELETE can be sent to /_kv or any_key to add, obtain, or DELETE keys or values. Other requests are allocated to Backend be1 and are forwarded to servers S1 or S2. The /img/* request is cached for 1 day, and/API /some/ API is cached for 30 seconds.

Start the

/usr/local/nuster/sbin/nuster -f nuster.cfg

Docker

docker pull nuster/nuster
docker run -d -v /path/to/nuster.cfg:/etc/nuster/nuster.cfg:ro -p 8080:8080 nuster/nuster
Copy the code

Method of use

NuSTER is based on HAProxy and supports all HAProxy directives.

basic

The configuration file has four basic sections: Global, defaults, frontend, and Backend.

  • global
    • Define global directives
    • You need to definenuster cache on or nuster nosql onOtherwise, cache and nosql cannot be used
  • defaults
    • definefrontend.backendDefault argument to
    • Can be found infrontend or backendSection redefinition
  • frontend
    • Define listening ports and other user-oriented Settings
  • bankend
    • Define backend servers and so on
    • You need to set upnuster cache on or nuster nosql onOtherwise, Backend does not have noSQL or noSQL functions
    • You need to set upnuster rule

Can define multiple frontend or backend. If defines nuster cache | no off or no nuster cache | no on | off, nuster is a HAProxy.

For details, see the HAProxy documentation under /doc or online

As TCP loader balancer

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
Copy the code

As HTTP/HTTPS loader balancer

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
Copy the code

As HTTP cache server

global
    nuster cache on data-size 200m
frontend fe
    bind *:8080
    default_backend be
backend be
    nuster cache on
    nuster rule all
    server s1 127.0.0.1:8081
Copy the code

As RESTful NoSQL cache server

global
    nuster nosql on data-size 200m
frontend fe
    bind *:8080
    default_backend be
backend be
    nuster nosql on
    nuster rule r1 ttl 3600
Copy the code

instruction

global: nuster cache|nosql

syntax:

nuster cache on|off [data-size size] [dict-size size] [purge-method method] [uri uri]

nuster nosql on|off [data-size size] [dict-size size]

default: none

context: global

Controls whether cache or noSQL is enabled.

A data-size + dict-size shared memory is allocated to store HTTP headers, data, keys, etc. Temporary data is allocated from the system memory pool. If there is not enough memory, new requests are not cached until memory is freed.

data-size

Together with dict-size determines the size of the memory block.

You can use m, m, G, and g. The default is 1MB, which is also the minimum.

dict-size

Determines the size of the Hash table.

You can use m, m, G, and g. The default is 1MB, which is also the minimum.

This determines the size of the hash table buckets, not the key, which is stored in shared memory.

Dict-size is different from the number of keys. Even if the number of keys exceeds dict-size, new keys can be added as long as there is space in the entire shared memory.

However, performance may deteriorate if the number of keys exceeds dict-size(bucket number). Dict-size can be set to the maximum number of keys multiplied by 8.

Dict-size will be removed in future versions and will scale automatically like the first version

purge-method [cache only]

The HTTP method used to customize PURGE is a maximum of 14 characters. The default is PURGE.

uri [cache only]

Define and enable the Cache Manager/Stats API

nuster cache on uri /_my/_unique/_/_cache/_uri

Cache Manager/STATS is off by default. If yes, access control (SEE FAQ) is enabled.

For details, see Cache Management and Cache Statistics.

proxy: nuster cache|nosql

syntax:

nuster cache [on|off]

nuster nosql [on|off]

default: on

context: backend, listen

Determines whether to enable cache/ noSQL in this backend. If this section has a filter, put it at the end.

nuster rule

syntax: nuster rule name [key KEY] [ttl TTL] [code CODE] [if|unless condition]

default: none

context: backend, listen

To define the effective conditions of cache/ NOSQL, you must define at least one rule.

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
Copy the code

Multiple rules can be defined and matched in the order they are defined.

acl pathA path /a.html
nuster cache on
nuster rule all ttl 3600
nuster rule path01 ttl 60 if pathA
Copy the code

Rule Path01 will never be matched.

name

Define the name of the rule.

When used in the Cache Manager API, different rules need not be unique but different names are recommended; otherwise, rules with the same name are considered the same.

key KEY

Defines the cache/ noSQL key, supplemented by the following keywords. composition

  • 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 CACHE key is method.scheme.host.uri, and the default NoSQL key is get.scheme.host. uri.

Example

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;Copy the code

Generation:

  • 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)

The default GET.http.www.example.com./q?name=X&type=Y. key, And the key method. The scheme. Host. Path. Header_ASDF. Cookie_user. Param_type GET.http.www.example.com./q.Z.nuster.Y.. is generated

Requests with the same key are directly returned to the cache.

ttl TTL

Set the cache lifetime, after which the cache will be deleted. You can use D, H, M and S. The default is 3600 seconds. Set to 0 if you don’t want to fail

code CODE1,CODE2…

By default, only 200 responses are cached. If you need to cache others, you can add them. All will cache any status code.

Cache-rule only200 cache-rule 200and404 code 200,404 cache-rule all code allCopy the code

if|unless condition

Refer to HAProxy Configuration 7. Using ACLs and fetching samples to define ACL conditions

Cache

NuSTER can also be used as an HTTP cache server such as Varnish or Nginx to cache dynamic or static HTTP resources. HAProxy provides SSL, HTTP, HTTP2, rewrite redirection, add, delete, change Header, and so on, as well as the following functions.

Cache management

Caching can be managed by defining an endpoint through a URI and sending HTTP requests.

Define and enable

nuster cache on uri /nuster/cache
Copy the code

Basic usage

The curl -x POST - H "X: Y" http://127.0.0.1/nuster/cache

Remember to use access control

Cache on/off

A rule can be dynamically enabled or disabled through the Manager URI. The disabled rule will not be matched.

headers

header value description
state enable enable rule
disable disable rule
name rule NAME the rule to be enabled/disabled
proxy NAME all rules belong to proxy NAME
* all rules

All rules with the same name are enabled or disabled.

Examples

  • Close the rule r1

    The curl -x POST "name: r1" - H - H "state: disable" http://127.0.0.1/nuster/cache

  • None Example Disable all rules of Backend APP1b

    The curl -x POST "name: app1b" - H - H "state: disable" http://127.0.0.1/nuster/cache

  • Enable all rules

    The curl -x POST "name: *" - H - H "state: enable" http://127.0.0.1/nuster/cache

Cache lifetime

Changing the cache TTL only affects subsequent caches, not existing caches.

headers

header value description
ttl new TTL see ttl in nuster rule
name rule NAME the rule to be changed
proxy NAME all rules belong to proxy NAME
* all rules

Examples

Curl -x POST "name: r1" - H - H "TTL: 0" http://127.0.0.1/nuster/cache curl -x POST "name: r2 - H - H TTL: 2 h "http://127.0.0.1/nuster/cacheCopy the code

Set both state and TTL

Set both state and TTL

Curl -x POST "name: r1" - H - H "TTL: 0 -" H "state: enabled" http://127.0.0.1/nuster/cacheCopy the code

The cache to clear

There are several ways to purge cache by making HTTP PURGE requests to the manager uri defined by uri.

You can define customized http method using purge-method MYPURGE other than the default PURGE in case you need to forward PURGE to backend servers.

Deletes a specific URL

The curl - XPURGE https://127.0.0.1/imgs/test.jpg

Generate the key get.scheme.host. uri and delete that key.

The default key contains Host. If http://example.com/test is used in the cache, the Host header is required:

Curl -xpurge -h "Host: example.com" http://127.0.0.1/test

Delete by name

You can PURGE by including the Name header

headers

header value description
name nuster rule NAME caches belong to rule ${NAME} will be purged
proxy NAME caches belong to proxy ${NAME}
* all caches

Examples

# remove all cache curl -x PURGE -h "name: *" http://127.0.0.1/nuster/cache # delete backend applb all cache curl -x PURGE - H "name: App1b "http://127.0.0.1/nuster/cache # delete all rule r1 generated cache curl -x PURGE - H" name: r1 "http://127.0.0.1/nuster/cacheCopy the code

Delete by host

Delete all caches belonging to this host by wearing the X-Hostheader.

headers

header value description
x-host HOST the ${HOST}

Examples

The curl -x PURGE -h "X - host: 127.0.0.1:8080" http://127.0.0.1/nuster/cacheCopy the code

Delete by path

By default, the Query part is also included in the key, so different queries with the same path will produce different caches.

For example, nuster rule imgs if {path_beg /imgs/}, then request

The curl curl https://127.0.0.1/imgs/test.jpg?w=180&h=180 https://127.0.0.1/imgs/test.jpg?w=120&h=120Copy the code

Two caches are generated because the Query is different.

If you want to delete these caches, yes

If you know all the Queries, you can delete them one by one

The curl curl - XPURGE XPURGE https://127.0.0.1/imgs/test.jpg?w=120&h=120 https://127.0.0.1/imgs/test.jpg?w=180&h=180Copy the code

In most cases, you don’t know all of the Queries

If the query part is not important, you can remove the query from the key

Nuster rule imgs key method.scheme.host.path if {path_beg /imgs} if {path_beg /imgs}, only one cache will be generated

The curl - XPURGE https://127.0.0.1/imgs/test.jpg

Query is required in most cases

Delete by rule name

Name: curl -x PURGE -h "imgs" http://127.0.0.1/nuster/cache

If the rule is defined as nuster rule static if {path_beg /imgs/ / CSS /}, the imgs cannot be deleted

Therefore, deletion can be done through path

headers

header value description
path PATH caches with ${PATH} will be purged
x-host HOST and host is ${HOST}

Examples

Curl -x PURGE -h "path: /imgs/test.jpg / imgs/test. JPG "http://127.0.0.1/nuster/cache # delete all path is/imgs/test. The JPG and host 127.0.0.1:8080 cache curl -x PURGE - H" path: / imgs/test. JPG "-h" x - host: 127.0.0.1:8080 "http://127.0.0.1/nuster/cacheCopy the code

Delete by re

It can also be deleted by re, and all caches that match the re are deleted.

headers

header value description
regex REGEX caches which path match with ${REGEX} will be purged
x-host HOST and host is ${HOST}

Examples

Curl -x PURGE -h "regex: ^ / imgs /. * \. JPG $" http://127.0.0.1/nuster/cache # delete all caches which path starts with/imgs and ends with the. JPG and Belongs to 127.0.0.1:8080 curl -x PURGE -h "regex: ^ / imgs /. * \. JPG $" -h" 127.0.0.1:8080 "http://127.0.0.1/nuster/cacheCopy the code

PURGE Considerations

  1. Enabling Access Control

  2. If there are multiple headers, process them in the order name, path & host, path, regex & Host, regex, and host

    curl -XPURGE -H "name: rule1" -H "path: /imgs/a.jpg": purge by name

  3. If there are duplicate headers, process the first one

    curl -XPURGE -H "name: rule1" -H "name: rule2": purge by rule1

  4. The regex isn’t glob

    For example, the.jpg file under /imgs is ^/imgs/.*\.jpg$instead of /imgs/*.jpg

Cache statistics

Cache statistics can be obtained via the endpoint defined by the GET URI.

Eanble and define the endpoint

nuster cache on uri /nuster/cache
Copy the code

Usage

The curl http://127.0.0.1/nuster/cache

Output

  • Used_mem: memory used by the HTTP cache, not including overhead
  • Req_total: indicates the total number of requests from all backend systems with cache enabled, excluding requests from backend systems that do not have cache
  • Req_hit: indicates the number of cache hits
  • Req_fetch: Fetch the quantity from the back end
  • Req_abort: Abort request

NoSQL

NuSTER can also be used as a RESTful NoSQL cache server to add /GET/DELETE keys/values using HTTP POST/GET/DELETE.

Basic operation

Set

Curl -v - POST - d value1 curl http://127.0.0.1:8080/key1 - v - X X POST - data - binary @ icon. The JPG http://127.0.0.1:8080/imgs/icon.jpgCopy the code

Get

The curl -v http://127.0.0.1:8080/key1

Delete

The curl -v -x DELETE http://127.0.0.1:8080/key1

Response

Check status code.

  • 200 OK
    • POST/GET: success
    • Always DELETE:
  • 400 Bad request
    • A null value
    • Incorrect ACL, rules, etc
  • 404 Not Found
    • POST: Rule tests fail
    • GET: not found
  • 405 Method Not Allowed
    • The methods of the other
  • 500 Internal Server Error
    • Unknown error occurred
  • 507 Insufficient Storage
    • More than data – the size

Data by user

By adding headers, cookies, and so on to the key, you can store different user data in the same path.

nuster rule r1 key method.scheme.host.uri.header_userId if { path /mypoint }
nuster rule r2 key method.scheme.host.uri.cookie_sessionId if { path /mydata }
Copy the code

Set

Curl -v - X POST - d "333" H "userId: 1000" curl http://127.0.0.1:8080/mypoint - v - X POST - d "555" - H "userId: 1001 "http://127.0.0.1:8080/mypoint curl -v - X POST - d" userA data "-- cookies" sessionId: Ijsf023xe "http://127.0.0.1:8080/mydata curl -v - X POST - d" userB data "-- cookies" sessionId: Rosre329x "http://127.0.0.1:8080/mydataCopy the code

Get

Curl -v http://127.0.0.1:8080/mypoint < 404 Not Found curl -v - H "userId: 1000 "http://127.0.0.1:8080/mypoint < 200 OK 333 curl -v - cookies" sessionId: Ijsf023xe "http://127.0.0.1:8080/mydata < 200 OK userA dataCopy the code

The client

Support any CLIENT that supports HTTP, libraries: curl, Postman, Python requests, go net/ HTTP, etc.

FAQ

How to debug?

Add debug in global, or start haProxy with -d

Cache-related debugging information starts with [CACHE]

How do I cache POST requests?

Add a option HTTP – buffer – the request

Use the body keyword if you have a custom key

The request body may be incomplete, as described in the Option HTTP-Buffer-Request section of HAProxy Configuration

You can also set up a separate back end for POST requests

How do I do access control?

similar

Acl network_allowed SRC 127.0.0.1 ACL purge_method method PURGE http-request deny if purge_method! network_allowedCopy the code

How do I start HTTP2?

Bind :443 SSL CRT pub.pem alpn h2, HTTP /1.1Copy the code

Example

global nuster cache on data-size 100m nuster nosql on data-size 100m #daemon ## to debug cache #debug defaults retries 3  option redispatch timeout client 30s timeout connect 30s timeout server 30s frontend web1 bind *:8080 mode http acl pathPost path /search use_backend app1a if pathPost default_backend app1b backend app1a balance roundrobin # mode must be http mode http # http-buffer-request must be enabled to cache post request option http-buffer-request acl pathPost path /search # enable cache for this proxy nuster cache # cache /search for 120 seconds. Only works when POST/PUT nuster Rule rpost key method. The scheme. Host. Uri. The body TTL 120 if pathPost server s1 10.0.0.10:8080 backend app1b balance roundrobin mode http nuster cache on # cache /a.jpg, not expire acl pathA path /a.jpg nuster rule r1 ttl 0 if pathA # cache /mypage, key contains cookie[userId], so it will be cached per user acl pathB path /mypage nuster rule r2 key method.scheme.host.path.delimiter.query.cookie_userId ttl 60 if pathB # cache /a.html if response's header[cache] is yes  http-request set-var(txn.pathC) path acl pathC var(txn.pathC) -m str /a.html acl resHdrCache1 res.hdr(cache) yes nuster  rule r3 if pathC resHdrCache1 # cache /heavy for 100 seconds if be_conn greater than 10 acl heavypage path /heavy acl tooFast be_conn ge 100 nuster rule heavy ttl 100 if heavypage tooFast # cache all if response's header[asdf] is fdsa acl ResHdrCache2 res. HDR (ASDF) fdsa nuster rule resCache TTL 0 if resHdrCache1 server s1 10.0.0.10:8080 frontend web2 bind *:8081 mode http default_backend app2 backend app2 balance roundrobin mode http # disable cache on this proxy nuster Cache off nuster rule All Server S2 10.0.0.11:8080 listen web3 Bind *:8082 mode HTTP nuster cache nuster rule everything Server S3 10.0.0.12.8080 frontend noSQL_fe bind *:9090 default_backend nosql_be backend nosql_be nuster noSQL on nuster  rule r1 ttl 3600Copy the code

Conventions

  1. Files with same name: those with .md extension belong to NuSTER, otherwise HAProxy

Contributing

  • Join the development
  • Give feedback
  • Report issues
  • Send pull requests
  • Spread nuster

License

Copyright (C) 2017-2018, Jiang Wenyuan, < koubunen AT gmail DOT com >

All rights reserved.

Licensed under GPL, the same as HAProxy

HAProxy and other sources license notices: see relevant individual files.