キャッシュサーバーnusterを紹介


https://github.com/jiangwenyuan/nuster

Nusterは高速なキャッシュサーバー。

仕様は変更されるかもしれないので、最新のものは[https://github.com/jiangwenyuan/nuster/blob/master/README.md](https://github.com/jiangwenyuan/nuster/blob/master/README.md)を参照してください。


紹介
====

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

 * HAProxyのすべての機能や特徴がサポート、100%互換性
 * 動的キャッシング機能
   * HTTP method, URI, path, query, header, cookiesなどでキャッシング
   * HTTP request or response contentsなどでキャッシング
   * environment variables, server stateなどでキャッシング
   * SSL version, SNI　などでキャッシング
   * connection rate, number, byte　などでキャッシング
 * スーパー速い
 * キャッシュ purging
 * フロントエンドとバックエンド両方HTTPS
 * HTTP圧縮
 * HTTPリライトやリダイレクト
 * などなど


性能
===========

スーパー早い

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

詳細は[こちら](https://github.com/jiangwenyuan/nuster/wiki/Web-cache-server-performance-benchmark:-nuster-vs-nginx-vs-varnish-vs-squid)。

インストール
============

```
make TARGET=linux2628
make install
```

[HAProxy README](README)参照 


使い方
=====

**global**セクションに`nuster cache on`を定義して、**backend**や**listen**セクションに
nuster-ruleも定義する 

ディレクティブ
=============

cache
-----

**syntax:** nuster cache on|off [share on|off] [data-size size] [dict-size size] [purge-method method]

**default:** *none*

**context:** *global*

キャッシュを使うかどうかを決める。

単位`m`, `M`, `g` and `G`で**data-size**で最大キャッシュサイズが設定できる。

ディフォルトは1MBで、最小値も1MBである。 リスポンス内容だけが計算される。

nuster cache
------------

**syntax:** nuster cache [on|off]

**default:** *on*

**context:** *backend*, *listen*

cache filterを定義する。 `cache-rule` も定義する必要がある。

on,offで単独でコントロールできる。

複数のfilterがある場合、cache filterは最後におくこと。

nuster-rule
----------

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

**default:** *none*

**context:** *backend*, *listen*

cache ruleを定義する。複数のルールがある場合は順序を注意して定義すること。
マッチングできたら止まるので。

```
acl pathA path /a.html
nuster cache
nuster-rule all ttl 3600
nuster-rule path01 ttl 60 if pathA
```

allが全てのリクエストをキャッシュしたので、`path01`は実行されない

### name

名前を定義する

### key KEY

下記のキーワードで`.`で繋いでkeyを定義する。

 * method:       http method, GET/POST...
 * scheme:       http or https
 * host:         the host in the request
 * path:         the URL path of the request
 * 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

ディフォルトkeyは`method.scheme.host.path.query.body`

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
 * path:         /q
 * query:        name=X&type=Y
 * header\_ASDF: Z
 * cookie\_user: nuster
 * param\_type:  Y
 * body:         (empty)

ので、ディフォルトkeyは`GEThttpwww.example.com/qname=X&type=Y`で、
`key method.scheme.host.path.header_ASDF.cookie_user.param_type`は
`GEThttpwww.example.com/qZnusterY`になる。

キャッシュにリクエストと同じなkeyがあったら、キャッシュを返す。

### ttl TTL

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

### code CODE1,CODE2...

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

```
nuster-rule only200
nuster-rule 200and404 code 200,404
nuster-rule all code all
```

### if|unless condition

HAProxy ACLを使う。
See **7. Using ACLs and fetching samples** section in [HAProxy configuration](doc/configuration.txt)

FAQ
===

debug方法?
------------------------
`global`に`debug`を設定か, `haproxy`を`-d`で起動する。

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

どうやってPOSTリクエストをキャッシュする?
------------------------
`option http-buffer-request`を設定

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

POST bodyは不完全な可能性があるので、**option http-buffer-request**
section in [HAProxy configuration](doc/configuration.txt) を参照

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

Example
=======

```
global
    nuster cache 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 on

    # cache /search for 120 seconds. Only works when POST/PUT
    nuster-rule rpost 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.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

```

* [ウェブキャッシュサーバnuster入門-1(基本)](https://qiita.com/kbe/items/d366d7a387de3d18fb96) 
* [ウェブキャッシュサーバnuster入門-2(Purge)](https://qiita.com/kbe/items/f51e50b2df78fcca4379)
* [ウェブキャッシュサーバnuster入門-3(管理)](https://qiita.com/kbe/items/54a4a7235558492469cc)