2015/01/24(土)PukiWiki bodycache patch副作用:id重複
PukiWiki bodycache patch副作用:id重複
たまたま気が付いたのですが、ECO-Wikiのメニューバーと本文それぞれの見出しのidが重複していました。
例えば、ECO-Wiki (acronia) トップページでは、メニューバーの「ECO攻略Wiki」と本文の「ECO-Wiki (acronia):エミル・クロニクル・オンライン攻略情報wiki」に同じid="content_1_0"が振られています。
原因を追ってみたところ、どうやらbodycacheパッチの副作用のようです。
- 発生条件
- PukiWiki bodycacheパッチを適用している。
- MenuBarと本文の両方で見出しを使用している。
- 原因
- bodyキャッシュを読み込んだときは、本文に対するconvert_htmlの実行はスキップされる。その結果、convert_html内の$contents_idがインクリメントされなくなるため、メニューバー生成時のconvert_htmlの実行結果に影響を与えてしまう。
function convert_html($lines) { //省略 static $contents_id = 0; //省略 $body = & new Body(++$contents_id); //この$contents_idのインクリメントが必要 //省略 }
- bodyキャッシュを読み込んだときは、本文に対するconvert_htmlの実行はスキップされる。その結果、convert_html内の$contents_idがインクリメントされなくなるため、メニューバー生成時のconvert_htmlの実行結果に影響を与えてしまう。
- 対策
- 場当たり的な対応ですが、$bodycache_statusが'cached'になっていたら、bodycacheによりconvert_htmlの実行がスキップされたと見なして、$contents_idをインクリメントするコードを追加しました。
function convert_html($lines) { //省略 static $contents_id = 0; global $bodycache_status; if ( $bodycache_status === 'cached' ) { //bodycacheから取得済み ++$contents_id; } //省略 $body = & new Body(++$contents_id); //省略 }
- 場当たり的な対応ですが、$bodycache_statusが'cached'になっていたら、bodycacheによりconvert_htmlの実行がスキップされたと見なして、$contents_idをインクリメントするコードを追加しました。
追記
改良したbodycache patchを公開しました。
2015/01/23(金)タイトルプラグイン
タイトルプラグイン(PukiWiki)導入
ECO-Wiki (acronia)にタイトルプラグインを導入しました。これで、ページ名(URL)とは別に、自由にタイトルを設定できるようになります。
導入した理由ですが、検索エンジンでの検索結果には基本的にタイトルが表示されるので、そこを分かりやすくしたかったからです。あとは、うまく使えば検索結果の上位に表示されやすくなってくれるかな~。
bodycacheとの干渉
タイトルプラグインですが、すんなり導入できるかと思ったら、bodycacheと干渉しました^^;
タイトルはbody部に含まれないので、確かにそのままだとタイトルはキャッシュ対象外になってしまいます。
対策としては、bodycache側を改造して、タイトルもbodycacheファイルに含めるようにしました。(ファイル構造が変わるのでバージョンを1から2に変更。)
追記: 2015/01/24
今のECO-Wikiの構成だと、ページ内の最初の見出しがほぼタイトル相当なので、最初の見出しをタイトルとして使うようにPukiWikiを改造しました。
そのため、わざわざ#titleで指定する必要はほとんどなくなりました。(#titleによる指定も引き続き可能です。)
2015/01/03(土)ECO-Wiki (acronia) 状況
2014/11/20(木)CGI(PHP)とCacheやLast-Modified
CGI(PHP)とCacheやLast-Modified
ECO-Wiki (acronia) 設定メモで $lastmod = 1; の設定をしてみましたが、BugTrack/763-負荷対策のまとめ-キャッシュを生かすをみると、これだけではIf-Modified-Sinceの判定などは行われないとのことで、あまり意味がなさそうでした。
そこで、実際に確認してみました。まず、初回アクセス。
[Request] GET /wiki/ HTTP/1.1 Host: eco.acronia.net User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive [Response] HTTP/1.1 200 OK Date: Wed, 19 Nov 2014 12:58:24 GMT Server: Apache/2.2.25 Cache-Control: no-cache, max-age=10 Pragma: no-cache Last-Modified: Sat, 15 Nov 2014 14:57:47 GMT Expires: Wed, 19 Nov 2014 12:58:34 GMT Keep-Alive: timeout=5, max=20 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=EUC-JP
確かに、Last-Modifiedは出力されています。また、no-cacheも返しているのでPukiWikiとしてはキャッシュして欲しくなさそうです。
そして、2回目のアクセス。
[Request] GET /wiki/ HTTP/1.1 Host: eco.acronia.net User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive If-Modified-Since: Sat, 15 Nov 2014 14:57:47 GMT [Response] HTTP/1.1 304 Not Modified Date: Wed, 19 Nov 2014 12:58:02 GMT Server: Apache/2.2.25 Connection: Keep-Alive Keep-Alive: timeout=5, max=17 Expires: Wed, 19 Nov 2014 12:58:12 GMT Cache-Control: no-cache, max-age=10
ブラウザはIf-Modified-Sinceを送っていました。no-cacheは「キャッシュしても良いけど毎回確認してね」くらいの意味合いなので、この挙動自体はまあ普通です。*1
そして、なぜかレスポンスは「304 Not Modified」。つまり、サーバー側でIf-Modified-Sinceを解釈して更新されていないと返答したことになります。しかし、PukiWikiのソースコードを探してもそんなことをしている記述はなさそう、う~ん(ーー;)
そこでもっと調べてみると、どうやらスクリプトがLast-Modifiedを返すと、CGIがIf-Modified-Sinceと比較してNot Modifiedかどうか判断してくれる、らしいです。なにそれΣ('◇'*)
ただ、phpスクリプトはIf-Modified-Sinceなんか見ずに普通に動いている訳なので、
- Not Modifiedでもサーバー側のCPU負荷とかはたぶん通常と同じだけかかる
- データは送られないので、通信量は削減できる
ということになるでしょうか。う~ん、微妙(・・?)
そして、問題なのはPukiWikiのLast-Modifiedは、#pcommentや#include*2を見ていないので、コメントが書き込まれてもキャッシュが更新されずにそれが見えないという現象が起こります(;^_^A
というわけで、$lastmodの設定は元に戻すことにしました。
ちゃんとキャッシュするには?
クライアントキャッシュをちゃんと使うなら、以下の対応が必要でしょうか。
- phpスクリプトでIf-Modified-Sinceを見て、Not Modifiedなら処理をスキップする
- 以下のどちらかの方法で#pcommentや#includeに対応
- Last-Modifiedを調べるときに#pcommentや#includeもたどる
- コメントや被includeファイルを更新したとき、親ファイルの更新日時も変える
#pcommentや#includeもたどるのは、結局ファイルを読む必要があるので負荷を下げたいという目的を考えると微妙です。その点では同時更新が有力ですが、コメントはともかくincludeの対応はちょっと難しいですね。(親ファイルを探す方法を考えないといけない。)
いろいろ手間がかかりそうなのでこれはやらないと思います^^;
PukiWiki bodycache
bodycacheの動作テストをしているのですが、これも更新日時判定の問題で#pcommentや#includeが存在するページは対象外とするようです。ただ、#pcommentについては対策パッチが出ています。(親ファイルの更新日時も変える方式。)
#includeを使っているページは少なくないですが、それ以外のページだけでも負荷が減るなら適用してみても良いかな。