Wiki | English | 中文 | 日本語
基于HAProxy的高性能HTTP缓存服务器和RESTful NoSQL缓存服务器。
中文版更新可能不及时,最新版请参照英文版README.md
介绍
性能
入门指南
使用方法
指令
Cache
管理
开启关闭
生存时间
清除
统计
NoSQL
Set
Get
Delete
FAQ
nuster是一个基于HAProxy的高性能HTTP缓存服务器和RESTful NoSQL缓存服务器,完全兼容HAProxy,并且利用HAProxy的ACL功能来提供非常细致的缓存规则。
nuster可以作为HTTP/TCP负载均衡器使用。
继承了HAProxy的所有特性,完全兼容HAProxy
负载均衡
前端后端HTTPS
HTTP压缩
HTTP重写重定向
HTTP信息增删改
HTTP2
监控
粘性
访问控制
内容切换
nuster也可以用作类似Varnish或者Nginx那样的HTTP缓存服务器,来缓存动态或者静态的HTTP资源。
HAProxy的所有特性(HTTPS, HTTP/2, ACL, etc)
非常快
强大的动态缓存功能
基于HTTP method, URI, path, query, header, cookies, etc
基于HTTP request or response contents, etc
基于environment variables, server state, etc
基于SSL version, SNI, etc
基于connection rate, number, byte, etc
缓存管理
缓存清除
缓存统计信息
缓存生存时间
nuster也可以用作RESTful NoSQL缓存服务器, 用HTTP POST/GET/DELETE 来 添加/取得/删除 Key/Value.
POST/GET/DELETE
可以像Memcached或者Redis那样放在应用和数据库之间作为内部KV缓存使用,也可以放在用户和应用之间作为面向用户的NoSQL使用。 支持header, cookie等等,所以可以将不同的用户数据存到相同的路劲。
有条件的缓存
内部KV缓存
面向用户缓存
支持任何类型的数据
支持所有编程语言,不需要特定的库,只需HTTP支持
非常快, 单进程模式下是nginx的3倍,多进程下nginx的2倍,varnish的3倍。
详见benchmark
生产环境的话从Download下载最新稳定版, 其他情况可以git clone。
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/nuster
添加USE_PTHREAD_PSHARED=1使用pthread 如果不需要可以删除USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1
添加USE_PTHREAD_PSHARED=1使用pthread
USE_PTHREAD_PSHARED=1
如果不需要可以删除USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1
USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1
具体可以参考HAProxy README。
准备一个配置文件: nuster.cfg
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
nuster监听8080端口,接受HTTP请求。 /_kv/开头的请求分配到backend be2, 可以发送HTTP POST/GET/DELETE到/_kv/any_key 来 添加/取得/删除 Key/Value. 其他的请求都被分配到backend be1, 并且会被转发到服务器s1 or s2. 其中/img/*请求会被缓存1天,而/api/some/api会被缓存30秒。
/_kv/
be2
/_kv/any_key
be1
s1
s2
/img/*
/api/some/api
/usr/local/nuster/sbin/nuster -f nuster.cfg
docker pull nuster/nuster docker run -d -v /path/to/nuster.cfg:/etc/nuster/nuster.cfg:ro -p 8080:8080 nuster/nuster
nuster基于HAProxy, 支持所有的HAProxy指令。
配置文件里有四个基本的sections: global, defaults, frontend and backend。
section
global
defaults
frontend
backend
定义全局指令
需要定义nuster cache on or nuster nosql on,否则cache和nosql无法使用
nuster cache on
nuster nosql on
定义frontend, backend的默认参数
可以在frontend or backend section重新定义
bankend
定义后端服务器等等设置
需要设置nuster cache on or nuster nosql on, 否则该backend没有nosql或者nosql功能
需要设置nuster rule
nuster rule
可以定义多个frontend or backend . 如果定义了nuster cache|nosql off或者没有nuster cache|nosql on|off, nuster就是一个HAProxy。
nuster cache|nosql off
nuster cache|nosql on|off
无法在listen里定义nuster。
listen
具体参考/doc下的HAProxy文档, 或者在线HAProxy文档
/doc
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
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
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
global nuster nosql on data-size 200m frontend fe bind *:8080 default_backend be backend be nuster nosql on nuster rule r1 ttl 3600
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
控制是否开启cache或者nosql。
会分配一块data-size + dict-size的共享内存来存储HTTP头,数据,key等等,临时数据从系统内存池分配。 如果没有足够内存,新的请求不会被缓存直到有内存被释放。
data-size + dict-size
和dict-size一起决定内存块的大小。
dict-size
可以使用m, M, g 和 G. 默认是1MB,同时也是最小值。
m
M
g
G
决定hash table的大小.
这个决定hash table buckets的大小,并非key的大小,key存在共享内存中。
dict-size(bucket数) 不等于 key数. 就算key的数量超过了dict- size,只要整个共享内存有空间,新的key仍然可以被添加。
不过如果key数超过dict-size(bucket数)性能也许会下降. dict-size可以设为大概的最大key数乘以8。
将来版本会删除dict-size, 像第一版本那样自动伸缩
自定义PURGE用的HTTP method,最大14个字符,默认是 PURGE.
PURGE
定义并开启cache manager/stats API
nuster cache on uri /_my/_unique/_/_cache/_uri
cache manager/stats默认是关闭的. 如果开启了,主义开启访问控制(see FAQ).
具体请参考缓存管理 和 缓存统计.
nuster cache [on|off]
nuster nosql [on|off]
default: on
context: backend
决定是否在这个backend开启cache/nosql。 如果这个section有filter,记得放在最后。
syntax: nuster rule name [key KEY] [ttl TTL] [code CODE] [if|unless condition]
定义cache/nosql的生效条件,需要定义至少一个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
可以定义多个rule,按定义顺序先后匹配。
acl pathA path /a.html nuster cache on nuster rule all ttl 3600 nuster rule path01 ttl 60 if pathA
rule path01永远不会被匹配。
path01
定义rule的name。
在cache manager API中使用, 不必唯一但是建议不同的rule用不同的name,否则相同name的rule视作一样。
定义cache/nosql的key, 由下列关键字加.组成
.
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
NAME
cookie_NAME: the value of cookie NAME
param_NAME: the value of query NAME
body: the body of the request
CACHE的默认key是 method.scheme.host.uri, NoSQL的默认key是 GET.scheme.host.uri.
method.scheme.host.uri
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;
生成:
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)
默认key产生GET.http.www.example.com./q?name=X&type=Y., 而key method.scheme.host.path.header_ASDF.cookie_user.param_type 则生成 GET.http.www.example.com./q.Z.nuster.Y..
GET.http.www.example.com./q?name=X&type=Y.
key method.scheme.host.path.header_ASDF.cookie_user.param_type
GET.http.www.example.com./q.Z.nuster.Y.
相同key的请求则会直接返回cache给客户端。
设置缓存生存时间,过期后缓存会被删除。 可以使用 d, h, m and s。默认0秒. 如果不希望失效则设为0
d
h
s
0
默认只缓存200的响应,如果需要缓存其他的则可以添加,all会缓存任何状态码。
all
cache-rule only200 cache-rule 200and404 code 200,404 cache-rule all code all
定义ACL条件 详见HAProxy configuration的 7. Using ACLs and fetching samples
nuster也可以用作类似Varnish或者Nginx那样的HTTP缓存服务器,来缓存动态或者静态的HTTP资源。 出了HAProxy的SSL, HTTP, HTTP2, 重写重定向,增删改Header等等,还提供了下面的功能。
缓存可以通过uri定义一个endpoint并发送HTTP请求来进行管理。
uri
定义并且开启
nuster cache on uri /nuster/cache
基本用法
curl -X POST -H "X: Y" http://127.0.0.1/nuster/cache
记得进行访问控制
rule可以通过manager uri动态开启关闭,关闭的rule不会再进行匹配。
_ headers_
相同name的rule都会被开启关闭。
_ Examples_
curl -X POST -H "name: r1" -H "state: disable" http://127.0.0.1/nuster/cache
curl -X POST -H "name: app1b" -H "state: disable" http://127.0.0.1/nuster/cache
curl -X POST -H "name: *" -H "state: enable" http://127.0.0.1/nuster/cache
更改缓存TTL,只会影响后续的新缓存,不会影响已经存在的缓存。
curl -X POST -H "name: r1" -H "ttl: 0" http://127.0.0.1/nuster/cache curl -X POST -H "name: r2" -H "ttl: 2h" http://127.0.0.1/nuster/cache
同时设置state和ttl
curl -X POST -H "name: r1" -H "ttl: 0" -H "state: enabled" http://127.0.0.1/nuster/cache
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.
purge-method MYPURGE
curl -XPURGE https://127.0.0.1/imgs/test.jpg
生成key GET.scheme.host.uri, 并删除那个key。
默认key 包含Host, 如果缓存时用了http://example.com/test 而在localhost删除是需要Host header:
Host
http://example.com/test
curl -XPURGE -H "Host: example.com" http://127.0.0.1/test
可以通过带上name header来 PURGE
name
# 删除所有缓存 curl -X PURGE -H "name: *" http://127.0.0.1/nuster/cache # 删除backend applb的所有缓存 curl -X PURGE -H "name: app1b" http://127.0.0.1/nuster/cache # 删除所有rule r1生成的缓存 curl -X PURGE -H "name: r1" http://127.0.0.1/nuster/cache
通过带上x-hostheader来删除所有属于这个host的缓存。
x-host
curl -X PURGE -H "x-host: 127.0.0.1:8080" http://127.0.0.1/nuster/cache
默认情况下,query部分也包含在key中,所以相同的path不同的query会产生不同的缓存。
比如nuster rule imgs if { path_beg /imgs/ }, 然后请求
nuster rule imgs if { path_beg /imgs/ }
curl https://127.0.0.1/imgs/test.jpg?w=120&h=120 curl https://127.0.0.1/imgs/test.jpg?w=180&h=180
会生成两个缓存,因为query不一样。
如果要删除这些缓存,可以
_ 如果知道所有的query,那么可以一个一个删除_
curl -XPURGE https://127.0.0.1/imgs/test.jpg?w=120&h=120 curl -XPURGE https://127.0.0.1/imgs/test.jpg?w=180&h=180
大多数情况下不知道所有的query
_ 如果query部分不重要,则可以从key里面删除query_
定义nuster rule imgs key method.scheme.host.path if { path_beg /imgs }, 这样的话只会生成一个缓存,那么就可以不用query删除缓存
nuster rule imgs key method.scheme.host.path if { path_beg /imgs }
大多数情况需要query
_ 通过rule name删除_
curl -X PURGE -H "name: imgs" http://127.0.0.1/nuster/cache
但是如果rule被定义成了 nuster rule static if { path_beg /imgs/ /css/ },则无法只删除imgs
nuster rule static if { path_beg /imgs/ /css/ }
因此,可以通过path删除
# 删除所有path是/imgs/test.jpg的缓存 curl -X PURGE -H "path: /imgs/test.jpg" http://127.0.0.1/nuster/cache # 删除所有path是/imgs/test.jpg 并且host是127.0.0.1:8080的缓存 curl -X PURGE -H "path: /imgs/test.jpg" -H "x-host: 127.0.0.1:8080" http://127.0.0.1/nuster/cache
也可以通过正则删除,所有匹配正则的缓存将被删除。
# 删除所有 /imgs 开头 .jpg结尾的缓存 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 .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/cache
PURGE 注意事项
开启访问控制
如果有多个header,按照name, path & host, path, regex & host, regex, host的顺序处理
path & host
path
regex & host
regex
host
curl -XPURGE -H "name: rule1" -H "path: /imgs/a.jpg": purge by name
curl -XPURGE -H "name: rule1" -H "path: /imgs/a.jpg"
curl -XPURGE -H "name: rule1" -H "name: rule2": purge by rule1
curl -XPURGE -H "name: rule1" -H "name: rule2"
rule1
比如 /imgs下的.jpg文件是^/imgs/.*\.jpg$ 而不是 /imgs/*.jpg
^/imgs/.*\.jpg$
/imgs/*.jpg
可以通过GET uri定义的endpoint来获取缓存统计信息。
curl http://127.0.0.1/nuster/cache
used_mem: http缓存使用的内存,不包括overhead
req_total: 开启了cache的所有的backend的总请求数,不包含那些没有cache的backend的请求数
req_hit: cache击中数
req_fetch: 从后端取得数量
req_abort: 中断的请求
curl -v -X POST -d value1 http://127.0.0.1:8080/key1 curl -v -X POST --data-binary @icon.jpg http://127.0.0.1:8080/imgs/icon.jpg
curl -v http://127.0.0.1:8080/key1
curl -v -X DELETE http://127.0.0.1:8080/key1
Check status code.
200 OK
POST/GET: 成功
DELETE: 总是
400 Bad request
空值
不正确的acl, rules, etc
404 Not Found
POST: rule tests失败
GET: not found
405 Method Not Allowed
500 Internal Server Error
507 Insufficient Storage
通过在key里加入header, cookie等等,可以将不同的用户数据存到相同的路劲。
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 }
curl -v -X POST -d "333" -H "userId: 1000" http://127.0.0.1:8080/mypoint curl -v -X POST -d "555" -H "userId: 1001" http://127.0.0.1:8080/mypoint curl -v -X POST -d "userA data" --cookie "sessionId: ijsf023xe" http://127.0.0.1:8080/mydata curl -v -X POST -d "userB data" --cookie "sessionId: rosre329x" http://127.0.0.1:8080/mydata
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 --cookie "sessionId: ijsf023xe" http://127.0.0.1:8080/mydata < 200 OK userA data
支持任何支持HTTP的客户端,库: curl, postman, python requests, go net/http, etc.
curl
postman
requests
net/http
在global添加debug, 或者带-d启动haproxy
debug
-d
haproxy
缓存相关的调试信息以[CACHE]开头
[CACHE]
添加option http-buffer-request
option http-buffer-request
如果自定义了key的话需要使用body关键字
body
请求body可能不完整,详见HAProxy configuration 的 option http-buffer-request 小节
另外可以为post请求单独设置一个后端
类似
acl network_allowed src 127.0.0.1 acl purge_method method PURGE http-request deny if purge_method !network_allowed
bind :443 ssl crt pub.pem alpn h2,http/1.1
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.scheme.host.uri.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 frontend nosql_fe bind *:9090 default_backend nosql_be backend nosql_be nuster nosql on nuster rule r1 ttl 3600
.md
Join the development
Give feedback
Report issues
Send pull requests
Spread nuster
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.