基於HAProxy的高性能HTTP緩存服務器和RESTful NoSQL緩存服務器

NuSTER

Wiki | English | 中文 | 日本語css

基於HAProxy的高性能HTTP緩存服務器和RESTful NoSQL緩存服務器。html

中文版更新可能不及時,最新版請參照英文版http://www.javashuo.com/tag/readme.md前端

目錄

介紹

NuSTER是一個基於HAProxy的高性能HTTP緩存服務器和RESTful NoSQL緩存服務器,徹底兼容HAProxy,而且利用HAProxy的ACL功能來提供很是細緻的緩存規則。python

特性

HTTP/TCP負載均衡器

NuSTER能夠做爲HTTP/TCP負載均衡器使用。mysql

  • 繼承了HAProxy的全部特性,徹底兼容HAProxy
  • 負載均衡
  • 前端後端HTTPS
  • HTTP壓縮
  • HTTP重寫重定向
  • HTTP信息增刪改
  • HTTP2
  • 監控
  • 粘性
  • 訪問控制
  • 內容切換

HTTP緩存服務器

NuSTER也能夠用做相似Varnish或者Nginx那樣的HTTP緩存服務器,來緩存動態或者靜態的HTTP資源。linux

  • 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
  • 緩存管理
  • 緩存清除
  • 緩存統計信息
  • 緩存生存時間

RESTful NoSQL緩存服務器

NuSTER也能夠用做RESTful NoSQL緩存服務器, 用HTTP POST/GET/DELETE 來 添加/取得/刪除 Key/Value.nginx

能夠像Memcached或者Redis那樣放在應用和數據庫之間做爲內部KV緩存使用,也能夠放在用戶和應用之間做爲面向用戶的NoSQL使用。 支持header, cookie等等,因此能夠將不一樣的用戶數據存到相同的路勁。git

  • HAProxy的全部特性(HTTPS, HTTP/2, ACL, etc)
  • 有條件的緩存
  • 內部KV緩存
  • 面向用戶緩存
  • 支持任何類型的數據
  • 支持全部編程語言,不須要特定的庫,只需HTTP支持

性能

很是快, 單進程模式下是nginx的3倍,多進程下nginx的2倍,varnish的3倍。github

詳見benchmarkweb

入門指南

下載

生產環境的話從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

具體能夠參考HAProxy README

配置文件

準備一個配置文件: 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秒。

啓動

/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
複製代碼

使用方法

NuSTER基於HAProxy, 支持全部的HAProxy指令。

基本

配置文件裏有四個基本的sections: global, defaults, frontend and backend

  • global
    • 定義全局指令
    • 須要定義nuster cache on or nuster nosql on,不然cache和nosql沒法使用
  • defaults
    • 定義frontend, backend的默認參數
    • 能夠在frontend or backend section從新定義
  • frontend
    • 定義監聽端口等等面向用戶的設置
  • bankend
    • 定義後端服務器等等設置
    • 須要設置nuster cache on or nuster nosql on, 不然該backend沒有nosql或者nosql功能
    • 須要設置nuster rule

能夠定義多個frontend or backend . 若是定義了nuster cache|nosql off或者沒有nuster cache|nosql on|off, nuster就是一個HAProxy。

具體參考/doc下的HAProxy文檔, 或者在線HAProxy文檔

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
複製代碼

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
複製代碼

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
複製代碼

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
複製代碼

指令

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

控制是否開啓cache或者nosql。

會分配一塊data-size + dict-size的共享內存來存儲HTTP頭,數據,key等等,臨時數據從系統內存池分配。 若是沒有足夠內存,新的請求不會被緩存直到有內存被釋放。

data-size

dict-size一塊兒決定內存塊的大小。

可使用m, M, gG. 默認是1MB,同時也是最小值。

dict-size

決定hash table的大小.

可使用m, M, gG. 默認是1MB,同時也是最小值。

這個決定hash table buckets的大小,並不是key的大小,key存在共享內存中。

dict-size(bucket數) 不等於 key數. 就算key的數量超過了dict-size,只要整個共享內存有空間,新的key仍然能夠被添加。

不過若是key數超過dict-size(bucket數)性能也許會降低. dict-size能夠設爲大概的最大key數乘以8。

未來版本會刪除dict-size, 像初版本那樣自動伸縮

purge-method [cache only]

自定義PURGE用的HTTP method,最大14個字符,默認是 PURGE.

uri [cache only]

定義並開啓cache manager/stats API

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

cache manager/stats默認是關閉的. 若是開啓了,主義開啓訪問控制(see FAQ).

具體請參考緩存管理緩存統計.

proxy: nuster cache|nosql

syntax:

nuster cache [on|off]

nuster nosql [on|off]

default: on

context: backend, listen

決定是否在這個backend開啓cache/nosql。 若是這個section有filter,記得放在最後。

nuster rule

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

default: none

context: backend, listen

定義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永遠不會被匹配。

name

定義rule的name。

在cache manager API中使用, 沒必要惟一可是建議不一樣的rule用不一樣的name,不然相同name的rule視做同樣。

key KEY

定義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
  • 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.

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..

相同key的請求則會直接返回cache給客戶端。

ttl TTL

設置緩存生存時間,過時後緩存會被刪除。 可使用 d, h, m and s。默認3600秒. 若是不但願失效則設爲0

code CODE1,CODE2...

默認只緩存200的響應,若是須要緩存其餘的則能夠添加,all會緩存任何狀態碼。

cache-rule only200
cache-rule 200and404 code 200,404
cache-rule all code all
複製代碼

if|unless condition

定義ACL條件 詳見HAProxy configuration7. Using ACLs and fetching samples

Cache

NuSTER也能夠用做相似Varnish或者Nginx那樣的HTTP緩存服務器,來緩存動態或者靜態的HTTP資源。 出了HAProxy的SSL, HTTP, HTTP2, 重寫重定向,增刪改Header等等,還提供了下面的功能。

緩存管理

緩存能夠經過uri定義一個endpoint併發送HTTP請求來進行管理。

定義而且開啓

nuster cache on uri /nuster/cache
複製代碼

基本用法

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

記得進行訪問控制

緩存開啓關閉

rule能夠經過manager uri動態開啓關閉,關閉的rule不會再進行匹配。

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

相同name的rule都會被開啓關閉。

Examples

  • 關閉rule r1

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

  • 關閉backend app1b的全部rule

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

  • 開啓全部的rule

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

緩存生存時間

更改緩存TTL,只會影響後續的新緩存,不會影響已經存在的緩存。

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

同時設置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.

刪除一個特定URL

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:

curl -XPURGE -H "Host: example.com" http://127.0.0.1/test

經過name刪除

能夠經過帶上name header來 PURGE

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

# 刪除全部緩存
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
複製代碼

經過host刪除

經過帶上x-hostheader來刪除全部屬於這個host的緩存。

headers

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

Examples

curl -X PURGE -H "x-host: 127.0.0.1:8080" http://127.0.0.1/nuster/cache
複製代碼

經過path刪除

默認狀況下,query部分也包含在key中,因此相同的path不一樣的query會產生不一樣的緩存。

好比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刪除緩存

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

大多數狀況須要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

所以,能夠經過path刪除

headers

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

Examples

# 刪除全部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
複製代碼

經過正則刪除

也能夠經過正則刪除,全部匹配正則的緩存將被刪除。

headers

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

Examples

# 刪除全部 /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 注意事項

  1. 開啓訪問控制

  2. 若是有多個header,按照name, path & host, path, regex & host, regex, host的順序處理

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

  3. 若是有重複的header,處理第一個

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

  4. regex 不是 glob

    好比 /imgs下的.jpg文件是^/imgs/.*\.jpg$ 而不是 /imgs/*.jpg

緩存統計

能夠經過GET uri定義的endpoint來獲取緩存統計信息。

Eanble and define the endpoint

nuster cache on uri /nuster/cache
複製代碼

Usage

curl http://127.0.0.1/nuster/cache

Output

  • used_mem: http緩存使用的內存,不包括overhead
  • req_total: 開啓了cache的全部的backend的總請求數,不包含那些沒有cache的backend的請求數
  • req_hit: cache擊中數
  • req_fetch: 從後端取得數量
  • req_abort: 中斷的請求

NoSQL

NuSTER也能夠用做RESTful NoSQL緩存服務器, 用HTTP POST/GET/DELETE 來 添加/取得/刪除 Key/Value.

基本操做

Set

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
複製代碼

Get

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

Delete

curl -v -X DELETE http://127.0.0.1:8080/key1

Response

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
    • 其餘的methods
  • 500 Internal Server Error
    • 發生未知錯誤
  • 507 Insufficient Storage
    • 超過data-size

分用戶的data

經過在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 }
複製代碼

Set

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
複製代碼

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 --cookie "sessionId: ijsf023xe" http://127.0.0.1:8080/mydata
< 200 OK
userA data
複製代碼

客戶端

支持任何支持HTTP的客戶端,庫: curl, postman, python requests, go net/http, etc.

FAQ

如何調試?

global添加debug, 或者帶-d啓動haproxy

緩存相關的調試信息以[CACHE]開頭

如何緩存POST請求?

添加option http-buffer-request

若是自定義了key的話須要使用body關鍵字

請求body可能不完整,詳見HAProxy configurationoption 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
複製代碼

如何開啓HTTP2?

bind :443 ssl crt pub.pem alpn h2,http/1.1
複製代碼

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.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

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 3600
複製代碼

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.

相關文章
相關標籤/搜索