人間とウェブの未来

「ウェブの歴史は人類の歴史の繰り返し」という観点から色々勉強しています。

Rubyでabコマンドをプログラマブルに操作できるab-mrubyを業務で使ってみたけどまぁまぁ良かった

1年前ぐらいにab-mrubyという、Rubyでabコマンドをプログラマブルに操作・拡張できるツールを作っていたのですが、それを業務のとある環境で使ってみたところまぁまぁ良かったのでその使い方を紹介しようと思います。

github.com

というのも、特定の条件でベンチマークで負荷をかけていくとプロセスがハングするという状況があって、その状況を再現するためにabコマンドでベンチマークをかけていたのですが、abコマンドのオプションがパッと見わかりずらかったり、どのホストのどのパスにベンチマークをかけているかなどをドキュメントで書いていて、

あれ、これRubyのDSLで表現した方がわかりやすくない?

と思って、ab-mrubyを作っていたことを思い出し、Rubyで書いてみました。

target_hosts = ["test001.example.jp", "test002.example.jp"]
target_paths = ["/mem.php"]

unless target_paths.include? get_config("TargetPath")
  puts "invalid path #{get_config("TargetPath")}"
  exit
end

unless target_hosts.include? get_config("TargetHost")
  puts "invalid host #{get_config("TargetHost")}"
  exit
end

add_config(
  "TotalRequests"         => 1000000,                       # int
  "Concurrency"           => 150,                        # int max 20000
  "KeepAlive"             => true,                      # true or false or nil
  #"VerboseLevel"          => 1,                         # int 1 ~ 5
  #"ShowProgress"          => false,                     # true, false or nil
  #"ShowPercentile"        => false,                     # true, false or nil
  #"ShowConfidence"        => false,                     # true, false or nil
  #"WaitSocketError"       => true,                      # true, false or nil
  "RequestTimeOut"        => 3000,                        # int sec
  #"BechmarkTimelimit"     => 50000,                     # int sec
  #"WindowSize"            => nil,                       # int byte
  #"HeadMethodOnly"        => false,                     # true, false or nil
  #"Postfile"              => nil,                       # './post.txt',
  #"Putfile"               => nil,                       # './put.txt',
  #"ContentType"           => nil,                       # 'application/x-www-form-urlencoded',
  #"OutputGnuplotFile"     => nil,                       # './gnu.txt'
  #"OutputCSVFile"         => nil,                       # './csv.txt'
  #"AddCookie"             => nil,                       # 'Apache=1234'
  #"AddHeader"             => 'User-Agent: benachmark test by pepabo',    # 'User-Agent: test'
  #"BasicAuth"             => nil,                       # 'user:pass'
  #"Proxy"                 => nil,                       # 'proxy[:port]'
  #"ProxyAuth"             => nil,                       # 'user:pass'
  #"OutputHtml"            => false,                     # true, false or nil
  #"BindAddress"           => nil,                       # 'example.jp'
  #"SSLCipher"             => nil,                       # 'DHE-RSA-AES256-SHA' or get from [openssl ciphers -v]
  #"SSLProtocol"           => nil,                       # 'SSL2', 'SSL3', 'TLS1', 'TLS1.1', 'TLS1.2' or 'ALL'
  "SilentMode"            => true,
)

後はこれを以下のように実行するだけです。

./ab-mruby -m bench.rb http://test001.example.jp/mem.php

これで、昔ながらのabコマンドのベンチマークが、Rubyの内容を元に実行されます。

上記のようにRubyでベンチマークの設定や拡張を書けて、ベンチマークをするべき対象のホストやパス、後はオプションも意味がわかりやすく伝わりやすいなぁと思ったわけです。(オプションをいっぱい書いてるのはどういうオプションがあるかを見せたいだけで、ほとんどコメントアウトすることができます)

また、ベンチマークでホストを間違えた時に、他人のホストにめっちゃベンチマークかけてた!!!みたいな事もRuby上でちゃんとエラー処理しているので、その心配もなさそうです。パスも同様ですね。

ということで、こんな風にベンチマークの設定をRubyで書いていると、ベンチマークによる事象の再現方法が自分以外に伝えやすかったり、他のホストに間違ってベンチマークしちゃうなどのミスもおこりにくいのでまぁまぁ良いのではないかと思いました。

また、ab-mrubyはベンチマーク実行結果を-Mオプションで渡したRubyスクリプトで受け取る事もできるので、それを使って評価やテスト的なこともできるので、色々使い方によっては夢が広がる気もしています。

github.com

後は使い方によって、ab-mrubyでいい感じにシナリオとか組めそうな気がするけど、できるかなぁ?という感じでその辺りはまだ試していませんので興味を持った方は是非どうぞ!!