Nginx + Luaを用いた、ハイパフォーマンスで動的なプロキシサーバを考察中です。
そのための施策の一つとして
上流サーバへのアクセスをKeepAliveする という方法がありますが
その際、プロキシサーバにどの程度性能に変化があるのかを調査してみました。
リバースプロキシのkeepalive設定
前提条件として Nginx > 1.1.4 が必要。
upstreamに keepalive というattributeがあるのでそれを設定します。
それと同時に、プロキシヘッダーにHTTP/1.1設定などを行いましょう。
ちなみにproxy_passだけだとkeepaliveできないようです。upstream必須。
あと、もちろんバックエンドサーバ側もkeepalive設定しておきます。
upstream http_backend {
server oreore.micro.service;
# keepalive <connection> [single]
# connection: 持続する最大コネクション数
# single: 指定すると、複数ホスト時でも単一ホストとして扱う?
keepalive 128;
}
server {
...
location /http/ {
proxy_pass http://http_backend;
# HTTP 1.1を指定
proxy_http_version 1.1;
# Connectionヘッダーを指定
proxy_set_header Connection "";
...
}
}
性能検証
サーバ構成(EC2)
ロール | インスタンスタイプ |
---|---|
ベンチマークサーバ | t2.micro |
プロキシサーバ | t2.micro |
バックエンドサーバ(ダミーレスポンスを返すだけ) | t2.micro |
OS/ミドルウェアなど
- | - |
---|---|
OS | AmazonLinux 2014.09 |
プロキシサーバ | OpenResty 1.7.4.1 |
ざっくり構成
バックエンドサーバは外部ELB経由で、Webサーバへアクセスしています。
ベンチマークコマンド
# clients:100 requests:50000 keepalive
# クライアントは常にhttp
weighttp -c 100 -n 50000 -k http://xx.xx.xx.xx/
プロキシサーバのNginxコンフィグ
こんな感じ(イメージです)。
#user nobody;
worker_processes 1;
worker_rlimit_nofile 10000;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
use epoll;
worker_connections 10000;
multi_accept on;
}
http {
include mime.types;
default_type application/octet-stream;
server_tokens off;
#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 logs/access.log main;
keepalive_timeout 60;
# upstream
upstream http_backend {
server oreore.micro.service;
}
upstream http_keepalive_backend {
server oreore.micro.service;
keepalive 128;
}
upstream https_backend {
server oreore.micro.service:443;
}
upstream https_keepalive_backend {
server oreore.micro.service:443;
keepalive 128;
}
server {
listen 80;
server_name 0.0.0.0;
# match test(external http elb)
location ~ /ex-elb-http/(\w+)/ {
proxy_pass http://http_backend/?$args;
}
# match test(external elb https)
location ~ /ex-elb-https/(\w+)/ {
proxy_pass https://https_backend/?$args;
}
# match test(external http elb keepalive on)
location ~ /ex-elb-http-keepalive/(\w+)/ {
proxy_pass http://http_keepalive_backend/?$args;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
# match test(external https elb keepalive on)
location ~ /ex-elb-https-keepalive/(\w+)/ {
proxy_pass https://https_keepalive_backend/?$args;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
# ...
}
}
評価軸
- a) リバースプロキシ配下のバックエンドサーバがhttpでkeepaliveなし
- b) リバースプロキシ配下のバックエンドサーバがhttpでkeepaliveあり
- c) リバースプロキシ配下のバックエンドサーバがhttpsでkeepaliveなし
- d) リバースプロキシ配下のバックエンドサーバがhttpsでkeepaliveあり
結果
評価軸 | プロキシサーバ:CPU利用率 | ベンチマーク結果:req/s | CPU1%辺りで捌けるreq/s |
---|---|---|---|
a) http + off | 22% | 3400 | 154.54 |
b) http + on | 38% | 8060 | 212.11 |
c) https + off | 41% | 1746 | 42 |
d) https + on | 45% | 6375 | 141.67 |
※プロキシサーバのCPUを使い切れていないのはベンチマーククライアント限界です。
そのため、CPU1%辺りに捌いた数も表に入れています(ざっくり数値になってしまいますが)
まとめ
予想通り、keepalive時、特にhttps時のプロキシ負荷効率がだいぶ良くなりました。
プロキシサーバとバックエンドサーバ、双方の負荷軽減に
効果がありそうですね。
おまけ
upstreamでhttpsをバックエンドに置く場合、ポート指定を忘れずに!!!
Nginxでupstreamにhttpsなホストを設定する時の注意点