HTTP/1.1のリバースプロキシとして、EnvoyとNginxとの軽めのベンチマークを取りました.
しっかりとしたベンチマークとはいえませんが、少しは参考になる結果かもしれません.
TL; DR
- リバースプロキシコンテナは、CPU・Memoryともにリソースの制限をする
- リバースプロキシとサービスはHTTP/1.1でTCPソケットで通信する
wrk -t 10 -c 10 http://host
で出力結果を取る
- Nginxの方が約1msほど早かったが、はっきりいって誤差
- corrupt952/surveyに今回の記事の元となるコードを置いている
実行環境
- docker ... 18.09.0
- docker-compose ... 1.23.2
- wrk ... 4.1.0
準備
今回もdocker-composeを利用して環境を作ります.
コードは、corrupt952/surveyにあります.
docker-compose.yml
Envoy・Nginx・サービス代わりのNginxの3つを定義します
version: '3'
services:
envoy:
build:
context: .
dockerfile: dockerfiles/envoy/Dockerfile
expose:
- "80"
ports:
- "8000:80"
nginx:
build:
context: .
dockerfile: dockerfiles/nginx/Dockerfile
expose:
- "80"
ports:
- "8001:80"
service:
image: nginx:stable-alpine
expose:
- "80"
dockerfiles/envoy/Dockerfile
Envoyのサンプルコードを参考にしていますが、不要なコードは削除しました.
FROM envoyproxy/envoy-alpine:01d726a41bdd790c16765e1d321cb50590574eb0
COPY dockerfiles/envoy/front-envoy.yaml /etc/front-envoy.yaml
CMD ["/usr/local/bin/envoy", "-c", "/etc/front-envoy.yaml", "--service-cluster", "front-proxy"]
dockerfiles/envoy/front-envoy.yaml
Envoyのサンプルコードを参考にしてサービスへリダイレクトするようにしています.
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8001
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: HTTP1
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: service
http_filters:
- name: envoy.router
config: {}
clusters:
- name: service
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: service
port_value: 80
dockerfiles/nginx/Dockerfile
次に紹介するdefault.confをNginxが読み込める位置に定義しておきます.
FROM nginx:stable-alpine
COPY dockerfiles/nginx/default.conf /etc/nginx/default.conf
dockerfiles/nginx/default.conf
サービスへプロキシするように定義するだけなので特筆することはありません.
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://service/;
}
}
これで準備は終わりです.
wrkというツールを使い、簡易的にベンチマークを実行してみます.
コネクション数10,スレッド数10に設定にします.(これといって根拠はないです)
Envoy
$ wrk -t 10 -c 10 http://localhost:8000
Running 10s test @ http://localhost:8000
10 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.45ms 2.02ms 46.58ms 96.63%
Req/Sec 433.29 121.99 1.17k 82.34%
43501 requests in 10.10s, 35.39MB read
Requests/sec: 4305.17
Transfer/sec: 3.50MB
Nginx
$ wrk -t 10 -c 10 http://localhost:8001
Running 10s test @ http://localhost:8001
10 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.65ms 0.96ms 13.85ms 88.35%
Req/Sec 631.85 129.09 1.20k 66.53%
63373 requests in 10.10s, 51.37MB read
Requests/sec: 6271.63
Transfer/sec: 5.08MB
Nginxの方が約1ms早いという結果になりました.
ですが、実際この差は膨大なリクエストを捌く必要がある大規模なサービスでなければ誤差といえる範疇かと思います.
最後に
今回は、HTTP/1.1のFront Proxyという役割でやってみましたが、Nginx・Envoyともにサポートしている領域が他にもあります.
そういった点を踏まえながら最適なモノを選んでいくのが良いでしょう.