今まではネイティブのクライアントへJsonでレスポンスを返していたのですが、新しいサービスを開発する際に、レスポンスをMessagePackにしてはどうかとクライアントサイドから提案があったので検証してみました。
ちなみにリクエストまでMessagePackにすると、リクエスト内容が簡単に参照できなくなってデバッグや問い合わせ時の調査が大変ということで、今回はレスポンスのみに使う想定です。
構成は下記の通りです。
- Nginx
- Passenger
- Ruby2.0
- Rails4
今回の検証はJson圧縮とMessagePack圧縮の比較です。アプリはRails4で実装します。また、JsonはデフォルトのJSONクラスよりもoj(Optimized JSON)が早いということなのでそちらを使用しています。MessagePackの方はMsgpackRailsを使います。Gemfileには下記を追加します。
(参考) JSONの替わりに使ったOJが速い
(参考) MsgpackRails
1 gem 'oj'
2 gem 'msgpack-rails', :git => 'git://github.com/nzifnab/msgpack-rails.git'
Controllerは下記のように実装しました。
1 class StaticPagesController < ApplicationController
2
3 require 'oj'
4
5 after_action :testcompress
6
7 respond_to :json, :mpac
8
9 SERIALIZE_TEST_RESPONSE = {(省略)}
10
11 def serialize_test
12 respond_to do |format|
13 format.json { render :json => SERIALIZE_TEST_RESPONSE }
14 format.mpac { render :text => SERIALIZE_TEST_RESPONSE.to_msgpack, :content_type => 'application/x-mpac' }
15 end
16 end
17
18 def testcompress
19 response.body = ActiveSupport::Gzip.compress(response.body)
20 end
21
22 end
- oj が追加されていると、MultiJSONによって自動的に oj が選択されるようです。
- シリアライズするHashデータを SERIALIZE_TEST_RESPONSE として定義しておきます。
- 処理内容としてはテスト用のデータをシリアライズして返すだけです。
- また、今回はシリアライズ+圧縮を試すのですが、Rails側で圧縮した場合と、Nginxで圧縮した場合も比較してみます。Rails側で圧縮する場合の処理を testcompress メソッドに定義しておいて、after_action で gzip 処理を行います。Nginx側で圧縮する場合は after_action をコメントアウトします。
検証方法としては、JMeterサーバを3つ用意して、100スレッドから上記APIへかけられるだけ負荷をかけてみるというやり方です。Nginxで圧縮するケースではHTTPヘッダマネージャでAccept-Encodingヘッダを設定する必要があります。また、Nginxの設定ファイルで下記の設定を有効にします。
1 gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/x-mpac;
デフォルトでは application/x-mpac 以外が設定された状態でコメントアウトされていますので、コメントアウトを解除して application/x-mpac を追加してあります。
検証結果は下記の通りです。
検証結果
種別 | 圧縮 | サンプル数 | 平均 | 中央値 | 90%LINE | 最小値 | 最大値 | スループット | KB/sec |
Json | Rails | 48626 | 1816 | 1805 | 2002 | 25 | 2258 | 158.57 | 306.30 |
MessagePack | Rails | 271372 | 317 | 321 | 356 | 5 | 533 | 889.05 | 1701.66 |
Json | Nginx | 48824 | 1785 | 1775 | 1988 | 27 | 2206 | 159.11 | 393.07 |
MessagePack | Nginx | 333783 | 249 | 248 | 279 | 4 | 466 | 1093.61 | 2395.42 |
MessagePack | 非圧縮 | 346175 | 246 | 246 | 271 | 6 | 610 | 1134.33 | 19178.19 |
Jsonの場合はCPUは常に振り切っている状態でしたが、MessagePackではCPUに余裕がありました。
テスト結果のスループットとしてはMessagePack非圧縮のケースが一番速かったのですが、MessagePackのNginxでの圧縮の場合と大きな差はなく、実際のケースでは転送するデータ量を少なくすることによるメリットも大きいので、今回はMessagePackのNginx圧縮パターンを採用することにしました。