rebuild-pagesでMT再構築を自動化すると必ず行き当たる問題をgo-setlockで解決する話

2016.02.04

201601_go-setlockmovable_typerebuild-pages.png

こんにちは、池田です。

ウェブサイト制作の際、ページ下部やサイドバーに「最新記事一覧」「人気記事一覧」といった頻繁に変わる情報を載せておきたいことはよくあります。Movable Type(MT)では、rebuild-pagesというスクリプトを使ってこれを実現することができます。ところが、このrebuild-pagesは

  • 実行時間がコンテンツの量によって変わるため、事前に見積もれない
  • MTを作っているシックス・アパート社のサポート対象になっていない
  • スクリプトを修正すると、以後シックス・アパート社のサポートが受けられなくなる

と、扱いに難点もあります。

今日はこの悩みを解消できる、go-setlockというツールを紹介します。

201601_go-heading.png「最新記事一覧」を本当に最新に保つ方法

「最新記事一覧」というエリアを作成してウェブサイトの各ページに配置し、ブログやニュースが更新されるたびにそのエリアも更新されていく、ということはよくやりたくなることだと思います。MTではそのためのテンプレートモジュールを作成し、他のテンプレートから読み込むことでこれを実現できます。

ただ、これだけでは、例えば新しいブログ記事を投稿しても「最新記事一覧」は更新されません。このモジュールを読み込んでいる各テンプレートを再構築する必要があります。

記事の投稿・更新を行うのが一人だけで、ページ数も多くないのであれば、更新のたびに手動で再構築してもいいでしょう。しかし、運用者が増えれば、ブログの更新時に他のテンプレートも再構築するよう徹底させる必要がありますし、ページの種類が増えれば再構築を要するテンプレートも増えます。サイトが成長するに従って、この運用は早々に破綻します。

201601_go_01.png

MT添付のMultiBlogプラグインにある再構築トリガーという機能を使うと、これを自動化できます。ブログの更新、記事追加やコメント投稿を切っ掛けにして、インデックステンプレートと呼ばれる種類のテンプレートを自動で再構築する機能です(詳しくはMT公式サイトのMultiBlog 機能を利用したポータルブログの設定をご覧ください)。多くの場合はMultiBlogプラグインでいいでしょう。再構築トリガーで再構築するインデックステンプレートを小さなHTMLにしておき、ウェブサーバーのSSI機能やPHPなどで読み込むことで、一つ更新すればサイト全体に反映されるようにもできます。

rebuild-pagesというスクリプトを使うこともできます。MultiBlogでは、「どのブログを更新した時に、どのインデックスが更新されるべきなのか」という依存関係を、自分で考えて設定する必要があります。「最新記事一覧」「人気記事一覧」「ブログカテゴリーの人気記事一覧」「ニュースカテゴリーの新規記事一覧」......と種類が増えてくると、慎重に設定しなければなりません。rebuild-pagesはそういった依存関係を気にせず再構築するブログを指定するだけなので、設定が複雑化してきた際に有効です。また、MTの管理画面ではなくサーバーのバックグラウンドで実行するためのスクリプトなので、運用者が再構築を待つ必要もありません。

201601_go-heading.png rebuild-pagesの問題点

rebuild-pagesはMT添付のスクリプトで(但し、シックス・アパートのサポート対象ではありません)、ブログのIDを指定して個別または複数のブログ全体を再構築したり、全ブログを再構築する物です。通常は以下のようにcronなどで定期的に実行します。

10 * * * * www cd /app/movabletype && ./tools/rebuild-pages --user=rebuilder --pass=$MT_REBUILDER_PASSWORD --blog_id=1 --blog_id=3 --blog_id=4

10分に一度、ブログIDが134のブログを再構築する例です。

ただ、難点があって、実行時間が延びていきます。実行時間は記事の量やサイトの構造によるので、何年も運用しているようなサイトでは設定した10分を越えるようになることも珍しくありません。そうすると、同時に複数のrebuild-pagesスクリプトが実行され、サーバーリソースの枯渇などの問題を引き起こすことになります。

運用開始時点では、rebuil-pagesが、実行間隔よりも短い時間で終了する。
運用開始時点では、rebuil-pagesが、実行間隔よりも短い時間で終了する。
数十か月後、rebuild-pagesの実行時間が、実行間隔よりも長くなる。
数十か月後、rebuild-pagesの実行時間が、実行間隔よりも長くなる。

サイトのローンチ当初はたかだか1、2分の実行時間で全く気に掛けなかった物が、ある時「MTの管理画面が重い」、「サイトの表示が遅い」、最悪の場合は「サイトが見られない」などといった運用担当者からの報告とともに、同時に多数のrebuild-pagesが実行されているのを発見する、などということも起こり得ます。

かと言って、実行間隔を1時間にしてしまうと、「最新」のはずのエリアが全く最新ではなくなってしまいますし、そもそも問題はそこではありません。「いつかは実行時間が実行間隔を越える、しかしそれがいつかは分からない」ということが本当の問題です。

そこでrebuild-pagesのスクリプトを修正して対応しようと思っても、それはできません。サポート対象にはなっていませんが、それでもMT添付のスクリプトなので、修正を加えてしまうと、それ以後MT本体もシックス・アパート社からのサポートを受けられなくなってしまうからです。

201601_go-heading.png go-setlockによる解決

このような問題を解決するツールとして、昔からsetlockが知られています。導入を検討したこともありますが、インストールを億劫に感じて二の足を踏んでいました。ふと思い立って検索してみたところ、go-setlock - Go port of setlockというブログ記事を見付けました。setlockをGoによる移植版であるgo-setlockという物を作った、という記事です。

go-setlockはGo製なのでインストールは非常に簡単です。そして、setlockと同様にsetlockというコマンドを提供しており、上記の問題を解決することができます。cronで以下のように設定します(ここではsetlock/usr/local/bin/setlockに配置したとします)。

10 * * * * www /usr/local/bin/setlock -nx rebuild-pages bash -c 'cd /app/movabletype && ./tools/rebuild-pages --user=rebuilder --pass=$MT_REBUILDER_PASSWORD --blog_id=1 --blog_id=3 --blog_id=4'

元々のrebuild-pages実行の前にsetlockコマンドが置かれています。このようにすると、実行スクリプト(ここではbash)がrebuild-pagesという名前のグループに属することになります(setlockへの第二引数として指定します)。

setlockは、スクリプト(bash)を実行する時に、同じグループのスクリプトが実行中でないかチェックします。他に実行されていなければ、スクリプトをそのまま実行します。もし他に実行中であれば、新しく実行されようとしているスクリプトを実行しません。

つまり、一つ前(10分前)のrebuild-pages実行がまだ終わっていなければ、新しいrebuild-pagesを実行しないのです。こうすることで、一度に複数のrebuild-pagesが実行されることを防止できます。

setlockは同じスクリプトを複数実行することを防ぐことができる
setlockは同じスクリプトを複数実行することを防ぐことができる

これで、便利なのに扱いに困りがち、というrebuild-pagesに、手を入れることなくをうまく活用していけるようになりました。setlockは他にも様々なシーンで活躍するので、ぜひお試しください。

シナップではWEBエンジニア、WEBディレクターを募集しています。

私たちは、クライアントのビジネス立ち上げから、サービスの継続的発展までのサポートを得意としている会社です。 あなたの知見、アイデアで、サービスの改善を促進させてください。
ご応募、心よりお待ちしております。

この記事をシェアする