2012年10月02日
DynamicMTMLの初期化を高速化する
DynamicMTMLを有効にしているとき、アクセス数の多いサイトではサーバー負荷が一時的に上がることがあります。このエントリではDynamicMTMLの負荷対策についてご紹介します。
追記:PowerCMS3.2では初期化クエリの数が少なくなっていますのでさほど気にする必要はありません。
DynamicMTMLはPHPで動作しますが、初期化処理でプラグインをスキャンしたりDBへのアクセスを伴います。尚、DynamicMTMLでのテンプレート処理は内部的にはSmartyが利用されています。
DynamicMTMLの処理フロー
- mod_rewriteにより .mtview.phpに処理を渡す
- addons/DynamicMTML.pack/php/dynamicmtml.run.php が実行される
- mt-config.cgi (設定ファイル)を読み込み、環境変数のセット
- DB接続
- mt_configテーブルを読み込み(SQL)、環境変数のセット
- addons/アドオン名/php ディレクトリをスキャンし、init.アドオン名.phpの実行(SQL-別シート参照)、テンプレートタグプラグインをSmartyに登録
- plugins/プラグイン名/php ディレクトリをスキャンし、init.プラグイン名.phpの実行(SQL-別シート参照)、テンプレートタグプラグインをSmartyに登録
- リクエストファイルを読み込む
- リクエストファイル内にMTタグ(MTML)を含まない場合はそのまま返す
- リクエストファイル内にMTタグ(MTML)を含む場合、file_infoレコード(SQL)からコンテクストをセットしてテンプレートをビルド(MTタグをSmartyのテンプレートに変換し、処理)して返す
高速化のポイント
- 不要なページは mod_rewrite の対象外にする
- 動的処理が必要な部分以外はスタティックにパブリッシュする
- APCやeAcceleratorなどのPHPアクセラレーターを使う(またはストレージにSSDを使う)
- プラグインの数を減らす(※)
- キャッシュを利用する
php/lib 以下、addons/AddonDir.pack/php以下、plugins/PluginDir/php以下のすべてのPHPファイルをスキャンします。MT(Smarty)の仕様上テンプレート・タグ1つにつき、1ファイルとなっているため、PowerCMSでは1000近いPHPファイルがスキャンされますので、ダイナミック処理で利用していないテンプレートタグはバックアップディレクトリに退避するなどして外すことで初期化の負荷が軽減します。尚、PHPアクセラレーターやSSDを使うことにより、初期化の負荷を大きく軽減できます。
中でも、初期化のタイミングでDBにクエリを投げるプラグインがあります(init.からはじまるファイル名のプラグイン)。PowerCMSのDynamicMTMLでは以下のようなクエリが発行されています。
処理 | クエリ | クエリを発行しているファイル |
コネクション開始(Connect) | username@localhost on PowerCMS | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
全般設定の読み込み(Query) | SHOW COLUMNS FROM `mt_config` | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
全般設定の読み込み(Query) | select * from mt_config | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
文字コードの識別(Query) | show variables like "character_set_database" | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
文字エンコードのセット(Query) | SET NAMES 'utf8' | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
ウェブサイト/ブログの初期化(Query) | SHOW COLUMNS FROM `mt_blog` | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
ウェブサイト/ブログの初期化(Query) | SHOW COLUMNS FROM `mt_blog_meta` | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
ウェブサイト/ブログの初期化(Query) | select * from mt_blog WHERE blog_id = 1 | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
ウェブサイト/ブログの初期化(Query) | select * from mt_blog_meta WHERE blog_meta_blog_id=1 | /addons/ DynamicMTML.pack/php /dynamicmtml.run.php |
カスタムフィールドのタグの初期化(Query) | SHOW COLUMNS FROM `mt_field` | /addons/ Commercial.pack/php /init.CustomFields.php |
カスタムフィールドのタグの初期化(Query) | select * from mt_field WHERE 1 = 1 | /addons/ Commercial.pack/php /init.CustomFields.php |
オブジェクトグループのタグの初期化(Query) | select * from mt_field WHERE field_type='objectgroup' | /addons/ CustomGroup.pack/php /init.ObjectGroup.php |
カスタムオブジェクトの設定読み込み(Query) | SHOW COLUMNS FROM `mt_plugindata` | /plugins/ CustomObjectConfig/php /init.CustomObjectCfg.php |
カスタムオブジェクトの設定読み込み(Query) | select * from mt_plugindata WHERE plugindata_plugin = 'customobjectconfig' and plugindata_key = 'configuration' | /plugins/ CustomObjectConfig/php /init.CustomObjectCfg.php |
追加カスタムフィールドのタグの初期化(Query) | select * from mt_field WHERE field_type='entry' OR field_type='entry_multi' OR field_type='page' OR field_type='page_multi' OR field_type='checkbox_multi' OR field_type='dropdown_multi' | /plugins/ AdditionalFields/php /init.AdditionalFields.php |
ウェブサイト/ブロググループのタグの初期化(Query) | select * from mt_field WHERE field_type='bloggroup' OR field_type='websitegroup' OR field_type='blogwebsitegroup' | /plugins/ BlogGroup/php /init.BlogGroup.php |
バナー/バナーグループ(カスタムフィールドでの関連付け)のタグの初期化(Query) | select * from mt_field WHERE field_type='campaign' OR field_type='campaign_multi' OR field_type='campaign_group' | /plugins/ Campaign/php /init.Campaign.php |
カテゴリ/フォルダグループのタグの初期化(Query) | select * from mt_field WHERE field_type='categorygroup' OR field_type='foldergroup' OR field_type='categoryfoldergroup' | /plugins/ CategoryGroup/php /init.CategoryGroup.php |
コンタクトフォームのタグの初期化(Query) | select * from mt_field WHERE field_type='contactform' | /plugins/ ContactFormConfig/php /init.ContactFormCfg.php |
カスタムオブジェクトのタグの初期化(Query) | select * from mt_field WHERE field_customobject=1 | /plugins/ CustomObjectConfig/php /init.CustomObjectCfg.php |
エントリ/ウェブページグループのタグの初期化(Query) | select * from mt_field WHERE field_type='entrygroup' OR field_type='pagegroup' OR field_type='entrypagegroup' | /plugins/ EntryGroup/php /init.EntryGroup.php |
リンク/リンクグループ(カスタムフィールドでの関連付け)のタグの初期化(Query) | select * from mt_field WHERE field_type='link' OR field_type='link_multi' OR field_type='link_group' | /plugins/ Link/php /init.Link.php |
スニペットフィールドのタグの初期化(Query) | select * from mt_field WHERE field_type='snippet' | /plugins/ SnippetField/php /init.SnippetField.php |
例えばリンクオブジェクトやバナーオプジェクトのカスタムフィールドでの関連付けを利用していなければ、これらのプラグインは外すことができます(無駄なクエリを投げなくなります)。
条件付きGET/キャッシュを有効にする
キャッシュを利用することで、テンプレートの処理結果がファイルに保存されます。ファイルは適宜再構築処理時にクリアされるため、有効期間を意識する必要はありません。また、条件付きGETを有効にすれば、ブラウザキャッシュがある場合、ブラウザキャッシュを利用させるようになります。これらはウェブサイト/ブログの設定画面でチェックを入れるだけで利用可能になります。
※「キャッシュする」と「ビルド結果をキャッシュする」の違いは、後者はパラメーター付きのページ(?foo=bar)を別のページとしてキャッシュする点です。
但し、会員専用サイトやマルチデバイス対応など、同じURLで内容が異なるページ(このあたりがまさにDynamicMTMLの使いどころなのですが)ではキャッシュは有効にできません。
※マルチデバイス対応だけであればプラグインによってキャッシュ対応が可能です。 https://github.com/alfasado/mt-plugin-multidevice-cache
DB接続を前提としない場合
マルチデバイス対応など、DB接続を伴わない処理にのみDynamicMTMLを利用している場合、.mtview.phpの先頭付近の以下の箇所をコメントアウトすればデータベース接続をスキップしてテンプレート処理を行います。mtIf〜などの条件タグのみを利用しているような場合などでは、この対策により負荷を軽減可能です。
$blog_id = 1; // 1はブログ/ウェブサイトのID
コメントを投稿する