fluentdで本番環境を再現する

  • 171
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

toyama0919/fluent-plugin-http_shadowというShadow Proxyっぽいことを簡単にやるプラグインを作りました。
production環境で半年くらい動かしてたのでメモしときます。

「Fluentd Meetup 2015 夏」で実際のユースケースを発表しました。

Shadow Proxyサーバとは

Shadow Proxyサーバについては以下がわかりやすいです。

実装としては以下のようなものが公開されています。

本番のリクエストをそのままバックエンドにあるサーバーに複製して送信するのですが、アプリケーションの規模が大きくなればなるほど効果を発揮します。
規模が大きくなればなるほどテスト方法も複雑になってきます。

現在本番で発生しているrequestをそのまま持ってくることで、限りなく本番に近い状態を再現できます。
Shadow Proxy代表的なユースケースとしては負荷試験や結合試験になります。

これをもう少し簡単かつ安全に出来ないかと考え、fluentdで実現してみました。

概要

fluentdに送信されるログからhttp requestを復元しています。

fluent-plugin-http_shadow

Proxyは使わないので、本番のWEBサーバーには影響なく導入出来ます。

設定例(Apache等)

<source>
  type tail
  format ltsv
  time_key log_time
  time_format %d/%b/%Y:%H:%M:%S %z
  path /var/log/httpd/access_log
  pos_file /var/log/td-agent/access.pos
  tag http_shadow.example
</source>

ログフォーマット例

  {
    "host": "exsample.com",
    "ip_address": "127.0.0.1",
    "server": "10.0.0.11",
    "remote": "-",
    "time": "22/Dec/2014:03:20:26 +0900",
    "method": "GET",
    "path": "/hoge/?id=1",
    "code": "200",
    "size": "1578",
    "referer": "http://exsample.com/other/",
    "user_agent": "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"
  }

設定はこう

<match http_shadow.example>
  type http_shadow
  host_hash { 
    "www.example.com": "staging.example.com", 
    "api.example.com": "api-staging.example.com", 
    "blog.ipros.jp": "blog-staging.ipros.jp"
  }
  host_key host
  path_format ${path}
  method_key method
  header_hash { "Referer": "${referer}", "User-Agent": "${user_agent}" }
  max_concurrency 10
  flush_interval 10
  timeout 10
  rate 10
</match>
  • host_hashでVirtual Hostに対応できます。

    • Host名に対応したrequest先を定義します。
  • rateが10の場合、requestが10%に希釈されます。(残りの90%は破棄される)

    • ステージング環境が本番環境よりも低いスペックの場合などはrateを調節します
  • header_hashでhttp headerを指定できます。

    • ${referer}のようにplaceholderでkeyを指定。
    • 固定文字列も可能です。
  • apacheのログの場合、postのパラメータはないので欠損します。

設定例2(アプリ内で専用のログを作れる場合、Railsとか)

アプリケーションから以下のようなログを出す場合、

  {
    "host": "example.com",
    "ip_address": "127.0.0.1",
    "log_time":"2015-05-18 16:38:14",
    "method": "GET",
    "path": "/hoge/",
    "uuid": "e78407cf040f67d17361281906895ca1283929e33592f81cdbda54a4a24e8cf7",
    "session_id": "42d0c906bfde8a30d323865d82a234abb4d13db80471d3b0bf4b7adc515d06da903f514289340ca17ba5cedde118868deebe53ef3986bfae8b591b9a614f7242",
    "user_id": 1
    "params": {"utf8"=>"✓", "client_id"=>"384809"} ,
    "referer": "http://exsample.com/other/",
    "user_agent": "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"
  }

設定例

<match http_shadow.exsample>
  type http_shadow
  host_hash { 
    "example.com": "staging.example.com"
  }
  host_key host
  path_format ${path}
  method_key method
  header_hash { "Referer": "${referer}", "User-Agent": "${user_agent}" }
  cookie_hash {"rails-app_session": "${session_id}"}
  params_key params
  max_concurrency 10
  flush_interval 10
  timeout 10
  rate 10
</match>
  • cookie_hashでcookieを送信も送信可能です。

    • 設定方法はheader_hashと同じ
  • getやpostのパラメータはparams_keyの中にhashで格納しておけばパラメータをmergeします。

パラメータ

設定可能な値とデフォルト値

  config_param :host, :string, :default => nil
  config_param :host_key, :string, :default => nil
  config_param :host_hash, :hash, :default => nil
  config_param :path_format, :string
  config_param :method_key, :string, :default => nil
  config_param :header_hash, :hash, :default => nil
  config_param :cookie_hash, :hash, :default => nil
  config_param :params_key, :string, :default => nil
  config_param :max_concurrency, :integer, :default => 10
  config_param :timeout, :integer, :default => 5
  config_param :username, :string, :default => nil
  config_param :password, :string, :default => nil
  config_param :rate, :integer, :default => 100

詳細

設定値 内容
host httpリクエストを送信するhost名
host_key Virtual Hostの際の接続Hostのキー
host_hash Virtual Hostの際の接続Hostのペア
path_format urlのpathのフォーマット。${path}などでテンプレート化
method_key http methodが定義されたキー。デフォルトはGET
header_hash http headerのペア
cookie_hash cookieのペア
params_key parameterが格納されたhashのkey
max_concurrency httpリクエストの並列数
timeout タイムアウト時間(秒)
username Basic認証のユーザー名
password Basic認証のパスワード
rate HTTPリクエストの希釈率。デフォルトが100で全てのリクエストがそのまま送信される。50ならば半分のリクエストが送信される。