少し前になりますが、4/8 にさくらのクラウドの高機能ロードバランサーサービスである エンハンスドロードバランサ にレスポンスボディのGZIP圧縮機能を追加しました。
エンハンスドロードバランサのコントールパネルやAPIで、GZIP圧縮を有効にすることで、手軽にWebサイトの表示にかかる時間を短くすることができますので、お試しいただければと思います。
この記事にあるとおり、エンハンスドロードバランサはソフトウェアとしてHAProxyを使っています。
今回、レスポンスのGZIP圧縮対応にあたり、HAProxyにlibslzという圧縮ライブラリを組み込んでおります。GZIP圧縮といえばzlibがもっとも使われると思いますが、事前に比較検証を行った上でlibslzを選択しているので、その紹介です。
ライブラリとベンチマークの環境
libslzはほぼ聞いたことがない圧縮ライブラリでしhaproxyの作者と同じ方がつくっている、省メモリ、CPUコストの低いGZIP互換の圧縮用ライブラリになります。(解凍の機能はありません)
このlibslzとzlibに加え、ちょうど安定版(2.0.0)がでたzlib-ngとlibslzでベンチマークを行い比較を行いました。
zlib-ngはzlibと互換のAPIを提供しながら、新しめのCPUの命令を使うなどして高速化を行ったライブラリです。また Cloudflare-zlibやintelの最適化も取り込んでいます。
ベンチマーク環境は、さくらのクラウドにて、CPU 12コア/メモリ 128GBのサーバをたて、ローカルスイッチににて接続しています。(さくらのクラウドではサーバの搭載するメモリ量によって使える帯域が変わりますが、128GBでは5Gbpsの通信が可能になります)
3台のサーバはそれぞれ、
- Go app (http-dump-request)
- haporxy: Aにreverse proxy
- benchmark (wrk): Bに対してベンチマーク実行
としました。
haproxy サーバのセットアップ
まず zlib-ngのインストール
この記事を書いている現在の最新は、2.0.2ですが、テストした時は2.0.0でしたので、2.0.0を使っております。
# wget https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.0.tar.gz # tar zxf 2.0.0.tar.gz # cd zlib-ng-2.0.0 # ./configure --zlib-compat --prefix=/opt/zlib-ng # make # make test # make install # ll /opt/zlib-ng/lib total 312 -rw-r--r-- 1 root root 184986 Mar 17 09:15 libz.a lrwxrwxrwx 1 root root 22 Mar 17 09:15 libz.so -> libz.so.1.2.11.zlib-ng lrwxrwxrwx 1 root root 22 Mar 17 09:15 libz.so.1 -> libz.so.1.2.11.zlib-ng -rwxr-xr-x 1 root root 126736 Mar 17 09:15 libz.so.1.2.11.zlib-ng drwxr-xr-x 2 root root 4096 Mar 17 09:15 pkgconfig
haproxyのインストール。libslzを有効にしたものと、GZIPを有効にしたバイナリをビルドします。 libslzはyumでインストールしました
yum install -y libslz-devel wget http://www.haproxy.org/download/x/src/haproxy-$HAPROXY_VERSION.tar.gz tar xvfz haproxy-$HAPROXY_VERSION.tar.gz cd haproxy-$HAPROXY_VERSION # USE_SLZ=1を指定すると、libslzが有効 make TARGET=linux-glibc USE_THREAD=1 USE_SLZ=1 USE_OPENSSL=1 SSL_INC=/usr/local/include/openssl SSL_LIB=/usr/local/lib64 make install mv /usr/local/sbin/haproxy /usr/local/sbin/haproxy_slz cd .. rm -rf haproxy-$HAPROXY_VERSION tar xvfz haproxy-$HAPROXY_VERSION.tar.gz cd haproxy-$HAPROXY_VERSION # USE_ZLIB=1を指定すると、zlibが有効 make TARGET=linux-glibc USE_THREAD=1 USE_ZLIB=1 USE_OPENSSL=1 SSL_INC=/usr/local/include/openssl SSL_LIB=/usr/local/lib64 make install
zlib-ngを有効にするときは、LD_PRELOADを使います
# /usr/local/sbin/haproxy -vv|grep zlib Built with zlib version : 1.2.7 Running on zlib version : 1.2.7 # LD_PRELOAD=/opt/zlib-ng/lib/libz.so /usr/local/sbin/haproxy -vv|grep zlib Built with zlib version : 1.2.7 Running on zlib version : 1.2.11.zlib-ng
haproxyの設定は、実際の環境に近づけるためエンハンスドロードバランサの開発環境からコピー・変更しています。また、httpsを有効にし、ベンチマークもhttpsにて行っています。
関係ありそうなところだけ抜き出すとこうなります。
frontend test-163.43.241.14:443 mode http bind 0.0.0.0:443 ssl crt /path/to/test.pem alpn h2,http/1.1 tls-ticket-keys /path/to/test-tls-ticket-keys.txt default_backend test-backend-default compression algo gzip compression type text/html text/plain text/plain text/css text/javascript application/x-javascript application/javascript application/json text/js text/xml application/xml application/xml+rss image/svg+xml use_backend test-backend-group1 if { path_reg ^/.*$ } backend test-backend-group1 mode http balance leastconn retries 3 option tcp-check server 192.168.0.101:3000 192.168.0.101:3000 check inter 10s
haproxyは次のように起動しました。
zlib
# /usr/local/sbin/haproxy -f /path/to/proxy.cfg
zlib-ng
# LD_PRELOAD=/opt/zlib-ng/lib/libz.so /usr/local/sbin/haproxy -f /path/to/proxy.cfg
libslz
# /usr/local/sbin/haproxy_slz -f /path/to/proxy.cfg
ベンチマーク
まず、wrkを使い9KBぐらいのデータが返るURLに対してベンチマークをしました。
無圧縮
$ wrk -d 30 'https://192.168.0.102/nogzip/source?plain' Running 30s test @ https://192.168.0.102/nogzip/source?plain 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 596.21us 231.33us 8.14ms 91.47% Req/Sec 8.49k 1.50k 10.88k 59.47% 508831 requests in 30.10s, 4.40GB read Requests/sec: 16904.68 Transfer/sec: 149.66MB
zlib
$ wrk -d 30 -H 'Accept-Encoding: deflate, gzip, br' 'https://192.168.0.102/nogzip/source?plain' Running 30s test @ https://192.168.0.102/nogzip/source?plain 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 832.53us 315.55us 10.56ms 87.28% Req/Sec 6.11k 690.37 7.61k 64.45% 365934 requests in 30.10s, 1.10GB read Requests/sec: 12157.29 Transfer/sec: 37.49MB
zlib-ng
$ wrk -d 30 -H 'Accept-Encoding: deflate, gzip, br' 'https://192.168.0.102/nogzip/source?plain' Running 30s test @ https://192.168.0.102/nogzip/source?plain 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 705.03us 371.54us 11.29ms 92.63% Req/Sec 7.37k 702.16 9.36k 74.04% 440795 requests in 30.10s, 1.62GB read Requests/sec: 14644.69 Transfer/sec: 55.07MB
libslz
$ wrk -d 30 -H 'Accept-Encoding: deflate, gzip, br' 'https://192.168.0.102/nogzip/source?plain' Running 30s test @ https://192.168.0.102/nogzip/source?plain 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 550.74us 213.55us 10.69ms 93.44% Req/Sec 9.24k 1.04k 11.72k 61.56% 552642 requests in 30.10s, 2.11GB read Requests/sec: 18360.29 Transfer/sec: 71.94MB
無圧縮で 16904.68req/secでていたのものが、zlibで圧縮を行うようにすると、12157.29req/secまで下がります。zlib-ngになると、14644.69req/secまであがります。そしてlibslzでは 18360.29req/secとさらにあがり、無圧縮よりスループットがでるようになっています。
この際のhaproxyサーバのcpu使用率(user:vmstatで計測)ですが、無圧縮では15%前後、zlibでは44%前後に上昇、zlib-ngは35%まで下がります。libslzは37%とzlib-ngより若干高くなるようですが、25%スループットがよいのでその影響もあるでしょう。
コンテンツのサイズを、140byteほどのSmall、3KBのMedium、6KBほどのLargeとしてベンチマーク結果をまとめたのが次になります。
もっともレスポンスのサイズが小さくなるのはzlibになりますが、CPU使用率・スループットへの影響が大きくなります。それに対して、zlib-ngはレスポンスサイズはzlibより大きくなりますが、CPU使用率がさがり、スループットも改善します。ただ、小さいサイズではzlibよりもCPU使用率があがってしまうことがあるようです。libslzでは、zlib-ngよりも若干レスポンスのサイズは増えるものの、CPU使用率はより低くできるようでした。
まとめ
以上のようなベンチマークの結果や、yumでインストールが可能という入手のしやすさ、また、エンハンスドLBにおいては転送量課金ではなくCPS(秒間の新規コネクション数)なので、圧縮率が多少悪くても問題になりにくいことなどを考慮にいれ、libslzを選択し、haproxyに組み込んだ上でエンハンスドロードバランサにてGZIP圧縮オプションの提供を開始しております。
エンハンスドロードバランサをはじめ、今後もさまざまなサービスの機能追加、改善を行っていきますので、よろしくお願いします。