APIレスポンスとしてのMessagePack検証

 今まではネイティブのクライアントへJsonでレスポンスを返していたのですが、新しいサービスを開発する際に、レスポンスをMessagePackにしてはどうかとクライアントサイドから提案があったので検証してみました。

 ちなみにリクエストまでMessagePackにすると、リクエスト内容が簡単に参照できなくなってデバッグや問い合わせ時の調査が大変ということで、今回はレスポンスのみに使う想定です。

検証用アプリ


 構成は下記の通りです。

  • Nginx
  • Passenger
  • Ruby2.0
  • Rails4

 今回の検証はJson圧縮とMessagePack圧縮の比較です。アプリはRails4で実装します。また、JsonはデフォルトのJSONクラスよりもoj(Optimized JSON)が早いということなのでそちらを使用しています。MessagePackの方はMsgpackRailsを使います。Gemfileには下記を追加します。

(参考) JSONの替わりに使ったOJが速い
(参考) MsgpackRails

gem 'oj'
gem 'msgpack-rails', :git => 'git://github.com/nzifnab/msgpack-rails.git'

 Controllerは下記のように実装しました。

class StaticPagesController < ApplicationController

  require 'oj'

  after_action :testcompress

  respond_to :json, :mpac

  SERIALIZE_TEST_RESPONSE = {(省略)}

  def serialize_test
    respond_to do |format|
      format.json { render :json => SERIALIZE_TEST_RESPONSE }
      format.mpac { render :text => SERIALIZE_TEST_RESPONSE.to_msgpack, :content_type => 'application/x-mpac' }
    end
  end

  def testcompress
    response.body = ActiveSupport::Gzip.compress(response.body)
  end

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の設定ファイルで下記の設定を有効にします。

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圧縮パターンを採用することにしました。