Advanced MogileFS Making plugins and tips Toru Yamaguchi Yet Another Hackadelic (d:id:ZIGOROu) <zigorou@cpan.org>
Agenda 3 分で分かる MogileFS Plugin の仕組み MogileFS::Store MogileFS の global_hook Server コマンドの作成 開発時の tips など まとめ
3分で分かるMogileFS
3分で分かるMogileFS (1) MogileFS とは? Perl で出来た DFS(Distribute File System) MogileFS の構成 tracker (mogilefsd) storage node (mogstored) database (mysql)
3分で分かるMogileFS (2) trackers ( mogilefsd  : 7001) storage node ( mogstored : 7500) database (mysql) mogilefs client reverse proxy(Perlbal) request MogileFS::Backend::do_command() Query X-Reproxy-URL
3分で分かるMogileFS (3) MogileFS::Client client ライブラリ server コマンドのリクエストは MogileFS::Backend の do_request() MogileFS::Worker::Query client からのコマンドリクエストを受信する worker 今回はこの辺りが主人公です
plugin の仕組み
plugin の仕組み  (1) plugin とは? trackers(mogilefsd) を拡張するモジュールの事。 MogileFS::Plugin::MetaData  (fid ごとのメタデータ保存 ) MogileFS::Plugin::FilePaths  (file の key を実ファイルパスのように ) この 2 つのモジュールが教科書
plugin の仕組み  (2) plugin で出来る事 plugin 用の DB Schema の定義  (mogdbsetup を使って作成 ) global_hook を用いた hook point での callback 実行 Query Worker に新しいコマンドを定義  or  既存コマンド差し替え と言う訳で、この辺りのお話をします
plugin の仕組み  (3) plugin module の構成 load メソッド  : global_hook, worker_command の登録など unload メソッド  : global_hook の削除 MogileFS::Store::TABLE_xxx メソッド  :  新規テーブルの定義 大体こんな感じ
MogileFS::Store と mogdbsetup
MogileFS::Store と mogdbsetup (1) 新しいテーブルを作る plugin モジュールの中で package  MogileFS::Store ; を宣言して、その中で sub  TABLE_plugin_table_name  {}  を作り、テーブル定義を文字列で返す MogileFS::Store- > add_extra_tables () を実行してテーブル読み込み
MogileFS::Store と mogdbsetup (2) plugin_sample_test を作るサンプル package  MogileFS::Plugin::Sample; ###  ここに plugin の処理 package  MogileFS::Store; sub  TABLE_plugin_sample_test  { return  ‘CREATE TABLE plugin_sample_test ( id  int  primary key, name varchar( 255 ))’;  } __PACKAGE__->add_extra_tables(‘plugin_sample_test’);  1 ;
MogileFS::Store と mogdbsetup (3) mogdbsetup でテーブル作成 $ mogdbsetup --plugins Sample --verbose --yes scheme_version が最新のとき mysql > UPDATE server_settings SET value = value - 1 WHERE field = ‘schema_version’; 一時的にバージョンを下げればおk!
MogileFS::Store と mogdbsetup (4) Plugin 中での $dbh の取得 MogileFS::Server を use した時に読まれる Mgd::get_dbh(); を引数無しで取得 my   $dbh  = Mgd::get_dbh();
MogileFS の global_hook
MogileFS の global_hook (1) global_hook とは? 予め cmd 中に用意された hook ポイントで任意のコールバックを実行出来る。 MogileFS:: register_global_hook ($hookname, $callback); MogileFS:: unregister_global_hook ($hookname); MogileFS:: run_global_hook ($hookname);
MogileFS の global_hook (2) global_hook で出来る事 コールバックに渡される値は、その cmd への引数 (HASHREF) のみ 特定の hook に対して登録出来る callback は一つだけ orz… 複数の hook を登録するモジュールを作りました。 ( MogileFS::Plugin::MultiHook )
MogileFS の global_hook (3) MultiHook の install $ sudo cpan -I MogileFS::Plugin::MultiHook setup (mogilefsd.conf) plugins =  MultiHook , FilePaths これだけです><
MogileFS の global_hook (4) 既知の hookpoint cmd_create_open  :  ファイル受信開始 cmd_create_close  :  ファイル受信完了 file_stored  :  ファイル保存完了 cmd_delete  :  ファイル削除時
MogileFS の global_hook (5) MultiHook のサンプル package  MogileFS::Plugin::Sample; use  MogileFS::Server; use  MogileFS::Util; use  MogileFS::Worker::Query; sub  load  { MogileFS::register_global_hook( 'fire_stored' ,   sub   { my   $args  =  shift ; ###  保存された storage node の URL をログに記載 MogileFS::Util::debug( &quot;stored to &quot;  .  $args ->{path}); return   1 ;  }); }
サーバーコマンドの作成
サーバーコマンドの作成 (1) 基本的な流れ MogileFS::register_worker_command($cmd_name, $cmd_code); を実行 MogileFS::Worker::Query で” cmd_plugin_${cmd_name}” と言うメソッドになる MogileFS::Backend->do_request でデバッグする
サーバーコマンドの作成 (2) MogileFS::Backend から直接サーバーコマンドを叩く my   $mogc  = MogileFS::Client-> new ( hosts  =>  $hosts ,  domain  =>  $domain );  $mogc ->{backend}->do_request( &quot;plugin_echo_show_args&quot; , {  foo  =>  1 ,  bar  =>  2   });   自分で作った cmd の動作確認は do_request で行う
サーバーコマンドの作成 (3) 引数をそのまま返す cmd の作成 sub  load  { MogileFS::register_worker_command( &quot;plugin_echo_show_args&quot; ,   sub   {  my  MogileFS::Worker::Query  $self  =  shift ; my   $args  =  shift ; $self ->ok_line( $args );  }); }   ok_line($res) の $res(HASHREF) は client に渡されるレスポンス
サーバーコマンドの作成 (3) 引数のハッシュの値は全て scalar のみ $mogc ->{backend}->do_request( &quot;test&quot; , {  foo  => {  bar  =>  1   },  baz  => [ qw/1 2/ ]  });   こういうのは NG です。 baz_0 => 1, baz_1 => 2 みたいに。
開発時のtipsなど
開発時のtipsなど (1) Mgd::log($level, $mgs) standalone 時は STDOUT に出力 daemon 時は syslog に出力 daemontools 使った管理がいい感じ 子プロセスでは使えない  (query worker とか )
開発時のtipsなど (2) MogileFS::Util::debug($msg) 子プロセスでも使える 但し STDOUT に記載されるタイミングは不安定? 改行不可なのでデータの dump は改行を落とさなければならない。
開発時のtipsなど (3) $MogileFS::DEBUG true にすると client, server 共にデバッグフラグが立つ client のデバッグログはレスポンスの成否とレスポンスデータの dump 等を出力する Query Worker の ok_line($res) にデバッグデータ突っ込むのをお勧め
開発時のtipsなど (4) テスト時の plugin の読み込み local   @ARGV  =  qw/--skipconfig --plugins MultiHook/ ;  eval  { MogileFS::Config->load_config; };   @ARGV を一時的に捏造 --skipconfig :  設定ファイルを読み飛ばす --plugins : plugin の指定 (suffix で )
まとめ
まとめ (1) plugin を使って出来る事 特定の hook にデバッグコード入れたり 監視に使えるコマンドを作ったり File にまつわる補足データを突っ込んだり 新しい hook 作ってみたり
まとめ (2) ファイル配信時の問題点 mogstored からの Content-Type ヘッダがでたらめ 出来れば Etag だとか Last-Modified とか自動的にあると嬉しい Cache 系リクエストヘッダに応じて tracker に問い合わせて、よしなに処理 今、作ってます orz…
まとめ (3) MogileFS の plugin 開発まとめ plugin 開発は わりと 簡単 MultiHook プラグイン推奨  ( ないと拡張性が乏しすぎ ) ロギングは適宜方法を選ぶと良い MogileFS について分からない人は Software Design 9, 10, 11 月号 を買うべし!w
Thanks ご清聴 ありがとうございました。 Toru Yamaguchi <zigorou@cpan.org>

Shibuya Pm Tt08 Advanced Mogilefs

  • 1.
    Advanced MogileFS Makingplugins and tips Toru Yamaguchi Yet Another Hackadelic (d:id:ZIGOROu) <zigorou@cpan.org>
  • 2.
    Agenda 3 分で分かるMogileFS Plugin の仕組み MogileFS::Store MogileFS の global_hook Server コマンドの作成 開発時の tips など まとめ
  • 3.
  • 4.
    3分で分かるMogileFS (1) MogileFSとは? Perl で出来た DFS(Distribute File System) MogileFS の構成 tracker (mogilefsd) storage node (mogstored) database (mysql)
  • 5.
    3分で分かるMogileFS (2) trackers( mogilefsd : 7001) storage node ( mogstored : 7500) database (mysql) mogilefs client reverse proxy(Perlbal) request MogileFS::Backend::do_command() Query X-Reproxy-URL
  • 6.
    3分で分かるMogileFS (3) MogileFS::Clientclient ライブラリ server コマンドのリクエストは MogileFS::Backend の do_request() MogileFS::Worker::Query client からのコマンドリクエストを受信する worker 今回はこの辺りが主人公です
  • 7.
  • 8.
    plugin の仕組み (1) plugin とは? trackers(mogilefsd) を拡張するモジュールの事。 MogileFS::Plugin::MetaData (fid ごとのメタデータ保存 ) MogileFS::Plugin::FilePaths (file の key を実ファイルパスのように ) この 2 つのモジュールが教科書
  • 9.
    plugin の仕組み (2) plugin で出来る事 plugin 用の DB Schema の定義 (mogdbsetup を使って作成 ) global_hook を用いた hook point での callback 実行 Query Worker に新しいコマンドを定義 or 既存コマンド差し替え と言う訳で、この辺りのお話をします
  • 10.
    plugin の仕組み (3) plugin module の構成 load メソッド : global_hook, worker_command の登録など unload メソッド : global_hook の削除 MogileFS::Store::TABLE_xxx メソッド : 新規テーブルの定義 大体こんな感じ
  • 11.
  • 12.
    MogileFS::Store と mogdbsetup(1) 新しいテーブルを作る plugin モジュールの中で package MogileFS::Store ; を宣言して、その中で sub TABLE_plugin_table_name {} を作り、テーブル定義を文字列で返す MogileFS::Store- > add_extra_tables () を実行してテーブル読み込み
  • 13.
    MogileFS::Store と mogdbsetup(2) plugin_sample_test を作るサンプル package MogileFS::Plugin::Sample; ### ここに plugin の処理 package MogileFS::Store; sub TABLE_plugin_sample_test { return ‘CREATE TABLE plugin_sample_test ( id int primary key, name varchar( 255 ))’; } __PACKAGE__->add_extra_tables(‘plugin_sample_test’); 1 ;
  • 14.
    MogileFS::Store と mogdbsetup(3) mogdbsetup でテーブル作成 $ mogdbsetup --plugins Sample --verbose --yes scheme_version が最新のとき mysql > UPDATE server_settings SET value = value - 1 WHERE field = ‘schema_version’; 一時的にバージョンを下げればおk!
  • 15.
    MogileFS::Store と mogdbsetup(4) Plugin 中での $dbh の取得 MogileFS::Server を use した時に読まれる Mgd::get_dbh(); を引数無しで取得 my $dbh = Mgd::get_dbh();
  • 16.
  • 17.
    MogileFS の global_hook(1) global_hook とは? 予め cmd 中に用意された hook ポイントで任意のコールバックを実行出来る。 MogileFS:: register_global_hook ($hookname, $callback); MogileFS:: unregister_global_hook ($hookname); MogileFS:: run_global_hook ($hookname);
  • 18.
    MogileFS の global_hook(2) global_hook で出来る事 コールバックに渡される値は、その cmd への引数 (HASHREF) のみ 特定の hook に対して登録出来る callback は一つだけ orz… 複数の hook を登録するモジュールを作りました。 ( MogileFS::Plugin::MultiHook )
  • 19.
    MogileFS の global_hook(3) MultiHook の install $ sudo cpan -I MogileFS::Plugin::MultiHook setup (mogilefsd.conf) plugins = MultiHook , FilePaths これだけです><
  • 20.
    MogileFS の global_hook(4) 既知の hookpoint cmd_create_open : ファイル受信開始 cmd_create_close : ファイル受信完了 file_stored : ファイル保存完了 cmd_delete : ファイル削除時
  • 21.
    MogileFS の global_hook(5) MultiHook のサンプル package MogileFS::Plugin::Sample; use MogileFS::Server; use MogileFS::Util; use MogileFS::Worker::Query; sub load { MogileFS::register_global_hook( 'fire_stored' , sub { my $args = shift ; ### 保存された storage node の URL をログに記載 MogileFS::Util::debug( &quot;stored to &quot; . $args ->{path}); return 1 ; }); }
  • 22.
  • 23.
    サーバーコマンドの作成 (1) 基本的な流れMogileFS::register_worker_command($cmd_name, $cmd_code); を実行 MogileFS::Worker::Query で” cmd_plugin_${cmd_name}” と言うメソッドになる MogileFS::Backend->do_request でデバッグする
  • 24.
    サーバーコマンドの作成 (2) MogileFS::Backendから直接サーバーコマンドを叩く my $mogc = MogileFS::Client-> new ( hosts => $hosts , domain => $domain ); $mogc ->{backend}->do_request( &quot;plugin_echo_show_args&quot; , { foo => 1 , bar => 2 }); 自分で作った cmd の動作確認は do_request で行う
  • 25.
    サーバーコマンドの作成 (3) 引数をそのまま返すcmd の作成 sub load { MogileFS::register_worker_command( &quot;plugin_echo_show_args&quot; , sub { my MogileFS::Worker::Query $self = shift ; my $args = shift ; $self ->ok_line( $args ); }); } ok_line($res) の $res(HASHREF) は client に渡されるレスポンス
  • 26.
    サーバーコマンドの作成 (3) 引数のハッシュの値は全てscalar のみ $mogc ->{backend}->do_request( &quot;test&quot; , { foo => { bar => 1 }, baz => [ qw/1 2/ ] }); こういうのは NG です。 baz_0 => 1, baz_1 => 2 みたいに。
  • 27.
  • 28.
    開発時のtipsなど (1) Mgd::log($level,$mgs) standalone 時は STDOUT に出力 daemon 時は syslog に出力 daemontools 使った管理がいい感じ 子プロセスでは使えない (query worker とか )
  • 29.
    開発時のtipsなど (2) MogileFS::Util::debug($msg)子プロセスでも使える 但し STDOUT に記載されるタイミングは不安定? 改行不可なのでデータの dump は改行を落とさなければならない。
  • 30.
    開発時のtipsなど (3) $MogileFS::DEBUGtrue にすると client, server 共にデバッグフラグが立つ client のデバッグログはレスポンスの成否とレスポンスデータの dump 等を出力する Query Worker の ok_line($res) にデバッグデータ突っ込むのをお勧め
  • 31.
    開発時のtipsなど (4) テスト時のplugin の読み込み local @ARGV = qw/--skipconfig --plugins MultiHook/ ; eval { MogileFS::Config->load_config; }; @ARGV を一時的に捏造 --skipconfig : 設定ファイルを読み飛ばす --plugins : plugin の指定 (suffix で )
  • 32.
  • 33.
    まとめ (1) pluginを使って出来る事 特定の hook にデバッグコード入れたり 監視に使えるコマンドを作ったり File にまつわる補足データを突っ込んだり 新しい hook 作ってみたり
  • 34.
    まとめ (2) ファイル配信時の問題点mogstored からの Content-Type ヘッダがでたらめ 出来れば Etag だとか Last-Modified とか自動的にあると嬉しい Cache 系リクエストヘッダに応じて tracker に問い合わせて、よしなに処理 今、作ってます orz…
  • 35.
    まとめ (3) MogileFSの plugin 開発まとめ plugin 開発は わりと 簡単 MultiHook プラグイン推奨 ( ないと拡張性が乏しすぎ ) ロギングは適宜方法を選ぶと良い MogileFS について分からない人は Software Design 9, 10, 11 月号 を買うべし!w
  • 36.

Editor's Notes