5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

nuster: 高性能のHTTPキャッシュサーバーとRESTful NoSQLサーバー

Last updated at Posted at 2018-07-09

nuster

Wiki | English | 中文 | 日本語

高性能のHTTPキャッシュサーバーとRESTful NoSQLサーバー。

最近版は英語のREADME.md を参照ください

目次

紹介

nusterはHAProxyを元に開発したHTTPキャッシュサーバーとRESTful NoSQLサーバーで、HAProxyと互換性がある。
そしてHAProxyのACLを利用して細かいキャッシュルールを定義できる。

特徴

HTTP/TCPロードバランサ

nusterはHAProxyのようにHTTP/TCPロードバランサとして使える。

  • HAProxyのすべての機能を持ち、HAProxyと互換性がある
  • ロード・バランシング
  • フロントエンドとバックエンド両方HTTPSサポート
  • HTTP圧縮
  • HTTPリライトとリダイレクト
  • HTTP修正
  • HTTP2
  • モニタリング
  • 粘り
  • アクセス制御
  • コンテンツスイッチング

HTTPキャッシュサーバー

nusterはVarnishやNginxのように動的や静的なHTTPコンテンツをキャッシュするキャッシュサーバーとしても使える。

  • HAProxyのすべての機能(HTTPS, HTTP/2, ACL, etc)
  • とっても速い
  • 優れた動的キャッシュ機能
    • 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
  • キャッシュ管理
  • キャッシュ削除
  • キャッシュ統計
  • キャッシュ生存期間

RESTful NoSQLキャッシュサーバー

nusterはRESTful NoSQLキャッシュサーバーとしても使える、 HTTP POST/GET/DELETE でKey/Valueを登録・取得・削除する。

MemcachedやRedisのようにアプリとデータベースの間に配置する内部KVキャッシュサーバーとして使えるし、アプリとユーザーの間に配置するユーザー向けのRESTful NoSQLキャッシュサーバーとしても使える。
headerやcookieなど識別できるので、同じエンドポイントにユーザー毎のデータを保存することができる。

  • HAProxyのすべての機能(HTTPS, HTTP/2, ACL, etc)
  • 条件付きキャッシュ
  • 内部KVキャッシュ
  • ユーザー向けRESTfulキャッシュ
  • あらゆる種類のデータをサポート
  • すべてHTTPができるプログラミング言語をサポート

性能

スーパー速い

シングルコアでnginxより3倍、マルチコアでnginxより2倍varnishより3倍のテスト結果があった。

詳細はbenchmark

入門

Download

本番環境はDownloadから, ほかはgit cloneで。

Build

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 requestsを受け取る.
/_kv/のリクエストはbackend be2に行き, /_kv/any_keyにHTTP POST/GET/DELETEを送信すればK/Vオブジェクトを登録・取得・削除できる。
他のリクエストは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のすべての機能をサポートする。

Basic

4つの基本sections: global, defaults, frontend and backend.

  • global
    • globalなパラメータを設定
    • nuster cache on or nuster nosql on は入れないとcacheやnosqlの機能を使えない
  • defaults
    • 他のfrontend, backendのディフォルトパラメータを設定
    • frontend or backend で単独で再設定できる
  • frontend
    • クライアントからリクエストを受ける側についてを設定する
  • bankend
    • 受けたリクエストを振り分ける先のサーバについてを設定する
    • nuster cache on or nuster nosql onは設定する必要ある
    • nuster ruleを定義する必要がある

複数のfrontend or backend 定義できる. nuster cache off設定したり, nuster cache on|off入れなかったりすると, nusterは全くHAProxy同様にとして動く。

listenではnusterを使えない。

/docしたのドキュメントかオンラインの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を使うかどうかを決める。

HTTPデータやキーなどを保存する、data-size + dict-sizeの大きさの共有メモリゾンを生成する。
このメモリゾンにメモリが足りない場合は、新しいリクエストはキャッシュしない。一時的なデータはメモリプールから申請する。

data-size

dict-sizeと一緒に共有メモリゾンのサイズを決定する。

単位m, M, g and Gで、 ディフォルトは1MBで、最小値も1MBである。

dict-size

hash tableのサイズを決める.

単位m, M, g and Gで、 ディフォルトは1MBで、最小値も1MBである。

これはhast tableのkeyの数を決めるわけではなく、bucketsのサイズを決めるのである。keyは共有メモリにある。

dict-size(buckets数)はkeys数と違って、 keyの数がこの数を超えても、共有メモリに容量さえあれば、新しいkeyは追加できる。

でもkeyの数がdict-size(buckets数)を超えると、性能が落ちる可能性がある。dict-sizeは大体の最大key数かける8であれば十分。

将来のバージョンはdict-sizeを削除するかもしれない, 初版のような自動リサイズを戻す。

purge-method [cache only]

長さ14バイトのHTTP methodを定義する。ディフォルトは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

cache/nosqlの有効無効を決める。
他のfilterがある場合は、一番後ろ置く。

nuster rule

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

default: none

context: backend

cache/nosqlの有効条件を定義する、少なくとも1つは必要。

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 allはすべてをマッチングするので、rule path01は実行しない。

name

このruleのnameを定義する。

cache manager APIに使われる。唯一にする必要ないが、唯一にしたほうがおすすめ、同じnameのruleは同じとされる。

key KEY

cache/nosqlのkeyを定義する。下記のkeywordと.との組み合わせ。

  • 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_typeGET.http.www.example.com./q.Z.nuster.Y..

リクエストのkeyが同じなら、キャッシュを返す。

ttl TTL

生存期限を定義する。単位は d, h, msで、 ディフォルトは0秒。
0の場合は失効しない。

code CODE1,CODE2...

ディフォルトは200のリスポンスしかキャッシュしない、ほかのものをキャッシュしたい場合は
定義する。 allの場合は全てキャッシュする。

cache-rule only200
cache-rule 200and404 code 200,404
cache-rule all code all

if|unless condition

HAProxy ACLを使う。
See 7. Using ACLs and fetching samples section in HAProxy configuration

Cache

nusterはVarnishやNginxのように動的や静的なHTTPコンテンツをキャッシュするキャッシュサーバーとしても使える。

HAProxyのSSL, HTTP, HTTP2, リライト、リダイレクトなどの機能の他、nusterは下記も提供する。

キャッシュ管理

cacheはランタイムでAPIで管理できる。uriを定義して、このURIにたいしてHTTPを投げることで、管理できる。

Eanble and define the endpoint

nuster cache on uri /nuster/cache

Basic usage

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

REMEMBER to enable access restriction

キャッシュ有効無効

headers

header value description
state enable 有効にする
disable 無効にする
name rule NAME NAMEという名前のruleを有効無効にする
proxy NAME NAMEという名前のProxyのすべてのruleを
* すべてのrulesを

Examples

  • rule r1を無効にする

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

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

キャッシュ生存期間

cacheのTTLを変更する、既存のキャッシュは変更されない。

headers

header value description
ttl new TTL TTLに変更
name rule NAME NAMEという名前のruleのTTLを変更
proxy NAME NAMEという名前のProxyのすべてのruleを
* すべての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を同時に変更

curl -X POST -H "name: r1" -H "ttl: 0" -H "state: enabled" http://127.0.0.1/nuster/cache

キャッシュ削除

いくつかの方法でPurgeできる。Purge機能はディフォルトでOffなので、Onにする必要がある。

globalセクションで nuster cache on uri /nuster/cacheのようにPurge用のuriを設定することでPurgeを有効にする。uriはなんでもいい。

そしてディフォルトのPurgeメソッドはPURGEで、purge-method MYPURGEで別のメソッドも設定できる。

1つURLをPurge

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

GET /imgs/test.jpgで生成したキャッシュをPurgeする、HEADERなどは問わない。

nameでPurge

ruleのname、proxyのname、もしくは*でPurgeできる。

headers

header value description
name rule NAME rule ${NAME} で生成したキャッシュをPurge
proxy NAME proxy ${NAME}のキャッシュをPurge
* すべてのキャッシュをPurge

Examples

# すべてのキャッシュをPurge
curl -X PURGE -H "name: *" http://127.0.0.1/nuster/cache

# proxy app1bのすべてのキャッシュをPurge
curl -X PURGE -H "name: app1b" http://127.0.0.1/nuster/cache

# nuster-rule r1が生成したキャッシュをすべてPurgeする
# つまり /imgs/* のキャッシュをすべてPurgeする
# nuster-rule r1 imgs if { path_beg /imgs/ }
curl -X PURGE -H "name: r1" http://127.0.0.1/nuster/cache

HostでPurge

そのHostのすべてのキャッシュをPurgeできる。

headers

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

Examples

# 127.0.0.1:8080のすべてのキャッシュをPurge
curl -X PURGE -H "x-host: 127.0.0.1:8080" http://127.0.0.1/nuster/cache

pathでPurge

ディフォルトで同じ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

すると、2つのキャッシュが生成される。

pathでpurge以外は、いくつかの方法でPurgeできる。

一つずつ

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を使う

nuster rule imgs key method.scheme.host.path if { path_beg /imgs },すると1つのキャッシュしか生成されない。そして、queryなしでpurgeできる。

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

でもqueryが重要の場合はできない。

ruleでpurge

curl -X PURGE -H "name: imgs" http://127.0.0.1/nuster/cache

すると、 /imgs/test.jpgだけでなく、他の /imgs/*もPurgeされる。

なので、pathでPurge

headers

header value description
path PATH pathが${PATH}のキャッシュをpurge
x-host HOST そして host が ${HOST}

Examples

# pathが/imgs/test.jpg のキャッシュをPurge
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のキャッシュをPurge
curl -X PURGE -H "path: /imgs/test.jpg" -H "x-host: 127.0.0.1:8080" http://127.0.0.1/nuster/cache

regexでPurge

headers

header value description
regex REGEX pathが${REGEX} matchならPurge
x-host HOST そして host が ${HOST}

Examples

# /img下の.jpgファイルのキャッシュをPurge
curl -X PURGE -H "regex: ^/imgs/.*\.jpg$" http://127.0.0.1/nuster/cache

#/img下の.jpgファイルかつHostが 127.0.0.1:8080のキャッシュをPurge
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がある場合, 一番目のheaderを使う

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

  4. regexglob ではない

    /imgs配下のjpgファイルは /imgs/*.jpg ではなく、^/imgs/.*\.jpg$ である。

キャッシュ統計

uriで定義したエンドポイントにGETする

Eanble and define the endpoint

nuster cache on uri /nuster/cache

curl http://127.0.0.1/nuster/cache

Output

  • used_mem: HTTPリスポンスが使っているメモリ
  • req_total: トータルrequest数、cacheが有効にしてないproxyのrequestは含まない
  • req_hit: cache hitのrequest数
  • req_fetch: バックエンドから取得して返すrequest数
  • req_abort: abrotしたrequest数

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
    • 空のvalue
    • 違うacl, rules, etc
  • 404 Not Found
    • POST: rule tests失敗
    • GET: 存在しない
  • 405 Method Not Allowed
    • 他のmethods
  • 500 Internal Server Error
    • エラー発生
  • 507 Insufficient Storage
    • dict-size超え

userごとのdata

keyにheader や cookie を使えば、同じendpointにユーザーごとのデータを保存できる

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

Clients

あらゆるHTTPできるツールやライブラリ: curl, postman, python requests, go net/http, etc.

FAQ

debug方法?

globaldebugを設定か, haproxy-dで起動する。

キャッシュに関するメッセージは[CACHE]を含む。

どうやってPOSTリクエストをキャッシュする?

option http-buffer-requestを設定

カスタマイズしたkeyはbodyを入れること。

POST bodyは不完全な可能性があるので、option http-buffer-request section in HAProxy configuration を参照

単独でPOST用のbackendを設置した方がいいかもしれない

アクセス制御方法?

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

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.

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?