Edited at

fluentdで本番環境を再現する

More than 3 years have passed since last update.

toyama0919/fluent-plugin-http_shadowというShadow Proxyっぽいことを簡単にやるプラグインを作りました。

production環境で半年くらい動かしてたのでメモしときます。


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


Shadow Proxyサーバとは

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

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

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

規模が大きくなればなるほどテスト方法も複雑になってきます。

現在本番で発生しているrequestをそのまま持ってくることで、限りなく本番に近い状態を再現できます。

Shadow Proxy代表的なユースケースとしては負荷試験や結合試験になります。

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


概要

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

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ならば半分のリクエストが送信される。