NGINX Plusでできることまとめ

NGINX Plusでできることをまとめてみた。

## NGINX Plusとは
NGINX Plusはみんな大好きオープンソースHTTPサーバであるNginxのサポート付き商用版である。Nginxを開発しているNginx Inc.が提供している。とはいえ、サポート付きというだけではなく次のような機能が増えている。なお、下3つについてはあまり興味がなかったので、今後説明がでてくることはない。

 - ステータス、レスポンスなどによる高機能なヘルスチェック - Application health checks
 - JSON/JSONPで取得できるステータス - Activity monitoring	
 - HTTP APIでノードを追加/削除できる - On-the-fly reconfiguration
 - HLS対応 - HTTP Live Streaming (HLS)
 - HDS対応 - HTTP Dynamic Streaming (HDS)

これらの機能はNginx Inc.が提供している[AMI](https://aws.amazon.com/marketplace/pp/B00A04GAG4/)で試すことができる。このイメージにはPlusが既にインストールされている状態で、比較的リーズナブルに検証が可能だ。

シフトキーを押すのがつらくなってきたので、ここから先ではNGINX PlusのことをPlusと表記する。

## NGINX AMIの使い方

AMI初心者なのでメモ程度に書いておく。

 - [AMI](https://aws.amazon.com/marketplace/pp/B00A04GAG4/)のページからごにょごにょするとインスタンスができる
 - インスタンスの初期ユーザーはubuntuで入ってsudoが使える
 - Nginxの設定ファイルは`/etc/nginx`
 - `/usr/share/nginx/html/nginx-modules-reference.pdf` に[nginx.org](http://nginx.org)よりちょっと詳しい説明が書かれたPDFがある

## Plusの初期構成

インストールされているはつぎのようなかんじだ。バージョンはstableではなく、mainlineの最新バージョンみたいだ。これ以外のmoduleを組み込んで使っている人もいるだろうけど、Plusの場合はどうやって組み込めば良いんだろうか。

```
$ nginx -V
nginx version: nginx/1.5.3
TLS SNI support enabled
configure arguments:
 --prefix=/etc/nginx
 --sbin-path=/usr/sbin/nginx
 --conf-path=/etc/nginx/nginx.conf
 --error-log-path=/var/log/nginx/error.log
 --http-log-path=/var/log/nginx/access.log
 --pid-path=/var/run/nginx.pid
 --lock-path=/var/run/nginx.lock
 --http-client-body-temp-path=/var/cache/nginx/client_temp
 --http-proxy-temp-path=/var/cache/nginx/proxy_temp
 --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
 --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
 --http-scgi-temp-path=/var/cache/nginx/scgi_temp
 --user=nginx
 --group=nginx
 --with-http_ssl_module
 --with-http_realip_module
 --with-http_addition_module
 --with-http_sub_module
 --with-http_dav_module
 --with-http_flv_module
 --with-http_mp4_module
 --with-http_f4f_module
 --with-http_hls_module
 --with-http_gunzip_module
 --with-http_gzip_static_module
 --with-http_random_index_module
 --with-http_secure_link_module
 --with-http_session_log_module
 --with-syslog
 --with-http_stub_status_module
 --with-mail
 --with-mail_ssl_module
 --with-file-aio
 --with-http_spdy_module
 --with-ipv6
```

```nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
```

## Application health checks

OSS版では、upstreamについてはユーザードリブンでの隔離機能がついているだけで、バックエンドのサーバをヘルスチェックする機能はなかった。この機能では指定した間隔でバックエンドサーバのヘルスチェックを行ってくれる。設定方法は次のようなかんじだ。

```conf.d/health_check_test.conf
# Ref: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#health_check

sever {
    ....
    location / {
        proxy_pass http://backend;
        health_check interval=5 fails=1 passes=1 uri=/;
    }
}
```

このような設定で5秒間隔で`/`のレスポンスをチェックしてバックエンドサーバのヘルスチェックを行ってくれる。

また、まだ未検証であるが、`match`ディレクティブを使うことで、より細かいヘルスチェックも実現可能なようだ。

```conf.d/health_check_test2.conf
http {
    server {
    ...
        location / {
            proxy_pass http://backend;
            health_check match=welcome;
        }
    }

    match welcome {
        status 200;
        header Content-Type = text/html;
        body ~ "Welcome to nginx!";
    }
}
```

上のように記述することで、response bodyに"Welcome to nginx!"という文字が含まれているかどうか、といった複雑な条件でヘルスチェックすることができる。バックエンドサーバにヘルスチェック用のURLを用意しておいて、それをたたくことで、バックエンドのヘルスチェックを行う、といったことが実現可能だ。

OSS版では、upstreamのリストが各ワーカープロセスごとに独立している。そのため、ユーザードリブンでエラーがわかっても全ワーカーから同時に振られなくなるわけではなかった。Plusではupstreamのリストをshared memoryに入れることで、ワーカー間で同期したupstreamリストを実現しているようだ。OSS版もこうなってほしい……

## On-the-fly reconfiguration

On-the-fly reconfigurationもshared memory化したupstreamリストを用いて実現されている機能だ。これはHTTP API経由で、動的にupstreamリストを変更できる強力な機能だ。まず、APIのエンドポイントを`upstream_conf`ディレクティブで指定する。次のような感じだ。

```conf.d/on_the_fly_test.conf
server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://backend;
        health_check;
    }

    location = /upstream_conf {
        upstream_conf;
        allow 127.0.0.1;
        deny all;
    }
}

upstream backend {
    zone backend 64k;
    server localhost:1081;
    server localhost:1082;
    server localhost:1083;
}
```

では、実際に使ってみよう。`/upstream_conf?upstream=backend`とするとバックエンドのサーバ一覧が取得できる。

```
$ curl "http://127.0.0.1/upstream_conf?upstream=backend"
server 127.0.0.1:1081; # id=0
server 127.0.0.1:1082; # id=1
server 127.0.0.1:1083; # id=2
# 35 primary servers free
```

リストの操作はidを使って行う。例えば`id=0`のサーバを外すのであれば、下のような感じだ。

```
$ curl "http://127.0.0.1/upstream_conf?remove=&upstream=backend&id=0"
server 127.0.0.1:1082; # id=1
server 127.0.0.1:1083; # id=2
# 36 primary servers free
```

このように`remove=`をクエリストリングに指定してアクセスするだけである。逆に追加するときは`add=`を使う。

```
curl "http://127.0.0.1/upstream_conf?add=&upstream=backend&server=127.0.0.1:1081"
server 127.0.0.1:1081; # id=0
```

もちろんweightなどのパラメータを指定することもできる。

```
curl "http://127.0.0.1/upstream_conf?add=&upstream=backend&server=127.0.0.1:1084&weight=2"
server 127.0.0.1:1084 weight=2; # id=4
```

このように動的にupstreamを変更することができる。これはかなり魅力的な機能ではないだろうか。

## Activity monitoring

Activity monitoringは高機能なstub_statusといったかんじで、JSON/JSONPでNginxの各種ステータスを取得できる。設定は次のようにエンドポイントを指定するだけである。

```
server {
    ....
    location = /status {
        status;
    }
}
```

レスポンスは次のようなかんじだ。

```json
{
	"version": 1,
	"nginx_version": "1.5.3",
	"address": "127.0.0.1",
	"timestamp": 1377263206961,
	"connections": {
		"accepted": 80399,
		"dropped": 0,
		"active": 1,
		"idle": 1
	},
	"requests": {
		"total": 80399,
		"current": 1
	},
	"upstreams":{
		"upstream_servers": [
			{
				"server": "127.0.0.1:1081",
				"state": "up",
				"weight": 1,
				"backup": false,
				"active": 0,
				"keepalive": 0,
				"requests": 470,
				"fails": 0,
				"unavail": 0,
				"downstart": 0,
				"sent": 78020,
				"received": 2350,
				"downtime": 0,
				"responses": {
					"1xx": 0,
					"2xx": 470,
					"3xx": 0,
					"4xx": 0,
					"5xx": 0,
					"total": 470
				},
				"health_checks": {
					"checks": 0,
					"fails": 0,
					"unhealthy": 0
				}
			},
		...
		],
	}
}
```

このようにupstreamの状態を詳しく見ることができる。

## まとめ

こんなかんじでNGINX Plusではupstreamまわりの機能が強化されていた（というか他の機能はよく調べてない）。これらの機能がOSSにならないのが残念である。なお、使う予定はいまのところない。