_ HTTP のリクエストとレスポンスを効率よくやりとりするためには、HTTP/1.1 の persistent connection を使ったり、persistent connection の上でさらに pipelining したりとかいう方法がある。 この前の /.j の議論では区別がついてない人がいたみたいだけど、ちゃんと区別してね。
_ でも、これ以外にもまだ方法はあるはずだよね。リクエストとレスポンスを複数繰り返すから接続数の問題が出てくるのであって、リクエストとレスポンスを1回やりとりするだけで複数のリソースを受け渡せるようにすればいい。
_ ……ってことで、3年近く前に実験したことがあるんだわ。クライアントは IE、Mozilla、Opera で試したんだけど、メモを見ても当時どのバージョンを使ったのか書いてない。あれからだいぶたってクライアントの対応状況はどう変わったんだろ。だれか暇な人がいたら再実験してほしいなぁ。以下、昔の実験結果のメモをもとに。
_ Content-Type: mulitpart/* ってのは、メールだけではなく HTTP でもちゃんと認められている。RFC2616 3.7.2 Multipart Types より。
In general, an HTTP user agent SHOULD follow the same or similar behavior as a MIME user agent would upon receipt of a multipart type. If an application receives an unrecognized multipart subtype, the application MUST treat it as being equivalent to "multipart/mixed".ちうことで、Web ブラウザでも MIME なメッセージを扱える他のアプリ(要するにメーラー)と同じようにテキストや画像をマルチパートメッセージとしてひとつのレスポンスで返してもちゃんと扱ってくれることを期待するわけだが……。最大多数派の IE が対応していないものは事実上使えないのと同じ。
- multipart/mixed: ×IE, ○Mozilla, ○Opera
- multipart/alternative: ×IE, ×Mozilla, ×Opera
_ data URL scheme (RFC2397)。バイト列を URL として表記する。 かんたんな例。
やっぱり IE がダメ。
- ×IE, ○Mozilla, ○Opera
_ MHTML (RFC2557)。IE で Web ページを保存するときに単一ファイルを選択したときに使われる形式。いちばん外側は RFC822 の形式(メールと同じ)で、そのヘッダ中で Content-Type: multipart/related と宣言してやればいい。
とーぜん IE はサポートしているが、今度は IE 以外がダメ。
- ○IE, ×Mozilla, ×Opera
_ というわけで、仕様としては存在しているがクライアント側の対応が追いついていない。ただし繰り返すけど、上記は3年ぐらい前に試した結果をそのまま載せてるだけで、最近のブラウザで試したわけじゃない。最新バージョンで追試してみたら結果は変わるかもしれないので、ヒマな人がいたら誰か試してみて。おねがい。
_ この前自転車で仕事に行ったが、夜に雨が降ったり外出直帰だったり風邪ひいてぶっ倒れたり。てなわけで1週間以上放置したあげく、週末の明るい時間に自転車を取りに。
_ 皇居内堀を1周してたら、なんか人が多く警備も厳重。今日なんかあったっけ、と思ったら、そういえば天皇誕生日だった。ふつーの土曜日のつもりですっかり忘れてたぞ。つーか、土曜の祝日も振替休日にする制度を作れ。命令。荒川を下ったり中川を上ったり途中で足がつったりうろうろしながら、2時間ちょいで48km走って帰還。まっすぐ帰ればこの半分の距離なのだが。
_ きのう 50km 近く走ったから今日は休もうかなと思ったんだが、 よつばと!の6巻を見てたら走りたくなった。クリスマス? なにそれ。
_ つーわけで、北風にめげずに江戸川を北上。……めげそう。気持ちよく走ってるときは脳味噌からあぶない麻薬が出まくってひじょーにハイになってるんだが、向かい風に逆らってるときは、ダイエットとか運動不足解消とかの目的があるでなし、誰かに強制されてるわけでなし、ましてや金がもらえるわけでもなし、なんでわしは好んでこんな苦行をしてるんだろうと哲学的思考をしながら復路の追い風を期待してちっとも前に進まない自転車をこぐわけよ。
_ 目標の折り返し点が近づくにつれて風がやんできた。かなりバテてたのでありがたい。が、それって帰りの追い風もなくなったということ。どーしてくれんだよ。往路で力を使いきっても風が背中を押してくれるから、と期待してたのにそれがないってどういうことよ。つーか帰り道は途中からやや南よりの東風にかわって、背中を押してくれるどころか逆風だし。うちに帰りつけないんじゃないかと思ったぞ。
_ けっきょく、利根川と江戸川が分岐する関宿城まで往復 83km を4時間10分で。そのうち 75km がほとんど止まらずに走れるサイクリングロードだったのに、平均で 20km/h に届かないってあたりがダメダメ。
別にそう珍しい手法ではないと思うのだが、実は意外と知られていないのか?と思った。知ってる人はすぐに問題に気がつくから、使わないし広めようとも思わないだけなんじゃないかな。_ mod_negotiation ってのはその名のとおりクライアントとサーバでネゴシエーションするモジュールなんだから、ネゴった結果によって複数の応答を用意しておかないと、406 Not Acceptable でアクセスできないクライアントがどうしても出てきちゃう。 前に書いたMultiViews で PHP を拡張子なしでアクセスさせる方法がよろしくないというのも根はまったく同じ。Accept-Encoding: gzip を吐かないクライアントを無視していいというのであればそれでもいいんだけど、クライアントによっては gzip に対応してないものがあることを忘れちゃいけない(主要なブラウザはほとんど対応してるけど、携帯や PDA、ロボットやクローラーの類があやしい)。
_ mod_negotiation ってのはファイルの拡張子を省略してもアクセスできるようにするモジュールじゃないですから。クライアントの機能によって返すコンテンツを動的に選択するモジュールですから。正しく覚えておいてね。どーしてもそういうのがやりたければ、mod_speling をベースに改造するのが筋だと思う。
_ となりの席のヒロシが「メリー給料日」といってました。なんだかハッピーな気分になれました。ありがとうヒロシ。
_ あれ、もう売ってるんだ。近所の本屋で見かけなかったからまだ先だと思ってた。というわけで、 何か書いたらしいですが、中身は コレのダイジェストなので、わしの書いた分に関していえば買ってまで読む必要はないです。ほかの人の書いた記事に価値を見出せれば買ってあげてください。
_ 朝からメールサーバの流量が少ない。なんでだろ。みんな仕事納めしちゃって業務メールが流れなくなった?
_ と思ったら、どうやら 台湾の地震で回線が切れたために中国方面からのメール(ほとんど spam)が届かなくなったせいらしい。地震が発生した時刻と流量が減りだした時刻に数時間の差がある(実際に回線が切れた時刻はわからない)のでそうと断定はできないものの、たぶん合ってると思う。
_ わかってたことだけどさ、spam の量が流量減としてはっきりと見える形でグラフにあらわれるとヘコむね。なんでこんなもののためにサーバの増強とかしてるんだろ。
_ この前のつづき、かな? .html.gz なファイルを置いておいて、MultiViews を使って .html という名前でアクセスさせる方法では、Content-Encoding: gzip を扱えないクライアントでは問題が発生するから、そういうクライアントを無視していい場合以外はやらない方が無難、というおはなし。
_ そういえば、mod_deflate を使って Content-Encoding: gzip を扱える(Accept-Encoding: gzip でリクエストする)クライアントに対して、gzip 圧縮したレスポンスを返す、ということはよくおこなわれている。だったら、その逆をやればいいんじゃね? つまり、あらかじめ gzip 圧縮したコンテンツを用意しておき、gzip に対応していないクライアントに対してだけはコンテンツを伸張して返してやればいい。
_ ということで実現方法を調べてみた。Apache 2.0 の mod_deflate は出力フィルタとしてレスポンスを圧縮するだけでなく、POST メソッドでリクエストボディが圧縮されていた場合にそれを伸張する入力フィルタとしても使える。だったら、もしかしたら 2.2 あたりで出力フィルタでも伸張できるように機能追加されてるかも?
_ ……うわ、 まじで実装されてる。ほんの思いつきだったんだけどなー。
_ というわけでちょっといじってみたんだけど、どうやら Apache をプロクシサーバとして使う場合に、オリジンサーバから返ってきた圧縮されたレスポンスを伸張するのに使う目的で実装されたようで、Apache 自身がオリジンサーバとなる場合に圧縮コンテンツを伸張してからクライアントに返す、という使いかたはできないみたい。また、クライアントの Accept-Encoding の値の扱いがダメダメ。このままじゃ今回の目的にはちょっと使えない。
_ てなわけで、 改造してみた。apache 2.2.3 用。2.0 不可。とりあえず手元では動いてるように見えるけど細かいチェックはしてないし、INFLATE 部分で足りない部分を DEFLATE フィルタからコピペしただけで中身の動作について深く理解してるわけではないので、どっか不具合あるかも。また、元々の用途らしいプロクシとしての動作についてはまったく確認していないので注意。
_ httpd.conf でこのパッチを当てた mod_deflate をロードしておき、
としておくと、gzip 転送に対応していないクライアントが *.html.gz にリクエストすると、伸張してからクライアントに返すようになる(MultiViews を有効にしておくと、*.html でアクセスできるようになる)。gzip 対応のクライアントに対しては何もせず圧縮したまま返すので、gzip 対応クライアントからのアクセスが多い場合には、生コンテンツを圧縮してから返す通常の DEFLATE フィルタよりも負荷には強くなると思われる。RemoveType .gz AddEncoding x-gzip .gz AddOutputFilter INFLATE .gz_ また、force-gunzip という環境変数が定義されていると、クライアントが gzip に対応していたとしても伸張した応答を返すようにしておいたので、
なんて設定しておくと、あらかじめ圧縮しておいたファイルを伸張してから SSI を解釈し、再度圧縮してクライアントに返すという凝ったこともできる。<Files *.shtml.gz> SetEnv force-gunzip SetOutputFilter INFLATE;INCLUDES;DEFLATE </Files>_ (2007/4/22 追記) apache 2.2.4 でパッチがうまく当たらないようになったので修正。たいして変わっちゃいないけど。 こちらから。
_ 中国からの spam はあっとゆーまに復活しました。ふだんより若干少ないかな、という気はしなくもないけどね。
_ ただ、 警察庁の定点観測では、そんなに減ったようには見えないんだよね。ワームの攻撃が27日未明から昼にかけて急減したようにも見えるけど、地震の数時間前から増加してたのが元に戻っただけという見方もできるし。 JPCERT/CC の定点観測はまだ先週までのデータしか載ってないので役に立たず。
_ ホスティングプロバイダでよく使われている商用のサーバ管理ツールに Pleskってのがあって、だいぶ前にこいつ、というかその下で動いている Virtuozzo(OpenVZ の商用版)を評価する目的で借りていじったことがある。
_ で、その Plesk には qmail が入っておりましたとさ。よく知られてるように、 qmail にはバイナリ配布に厳しい制限があるので、おいこれライセンス大丈夫なのか、とベンダに問い合わせたら、ほげほげなので問題ないですよ、と返ってきた。いや、それ理由になってないだろ、と激しくつっこみたくなる回答だったということは覚えているのだが、理由になってない理由とはどんなものだったのか今となっては思い出せないのが残念。djb が指定した方法でパッケージングしたものならばバイナリでも問題なく配布できるし、そうでなくてもちゃんと許可を受ければ配布は可能なのだが、Plesk は qmail-sppを使っていて、指定の方法でパッケージングしたバイナリではないことは確か。だとすれば djb の許可を得ていることになるのだが、ベンダがよこした回答はそれじゃなかったし、djb の思想とはあまりにかけ離れた qmail-spp パッチつきのものを djb が許可するとはあんまり思えないんだよなぁ。Plesk っていろんなレンタルサーバ業者で使われてるけど、あれほんとにライセンス大丈夫なのかしらん。
_ ……ということを、qmail-spp の話をひさしぶりに 目にして思いだした。
_ Plesk にかぎらず、この手のサーバ管理ツールではなぜか qmail が採用されることが多いんだよね。たとえば HDEも qmail なんだけど、こいつはインストールメディアにはバイナリでは収録されておらず、インストーラを起動するとおもむろに qmail をソースからコンパイルするというステキな方法で qmail の配布制限を回避してる(午後のこーだも同じ方法で回避してたよね)。わざわざそんなトリッキーな方法を使ってまでライセンスのめんどくさいものを使わなくてもいいんじゃないかと思うんだけどねぇ。
_ 非圧縮のファイルを必要に応じて圧縮してクライアントに返すという mod_deflate の標準的な動作とは反対に、圧縮済みのファイルを用意しておいて必要に応じて伸張してクライアントに返してみよう、の件。
_ この前は Apache 2.2 で mod_deflate を改造したが、今度は無改造の Apache 2.0 で可能な方法。といっても、mod_ext_filter と mod_headers が必要。どちらもあまり使われることはなく、とくに前者はインストールすらされていない環境も多いと思う。
Accept-Encoding: gzip なリクエストに対して accept_gzip という環境変数を設定し、これが設定されていない場合に /usr/bin/gzcat な外部フィルタを発動させ、Content-Encoding: gzip なレスポンスヘッダを返さないようにする。ExtFilterDefine gunzip mode=output cmd=/usr/bin/gzcat disableenv=accept_gzip SetEnvIf Accept-Encoding gzip accept_gzip <Files *.gz> SetOutputFilter gunzip Header unset Content-Encoding env=!accept_gzip Header append Vary Accept-Encoding </Files>_ 動作確認は一切してないけど、たぶん動くと思う。ただし、mod_deflate を改造した場合とは異なり、304 Not Modifid を返せないし、そもそもそれに必要な Last-Modified: や ETag: が失われる(はず)。プロクシが適切にキャッシュできるようにいちおう Vary: ヘッダを追加して返すようにしてるけど、Last-Modified も ETag もないので事実上キャッシュは効かなくなる。毎回外部コマンドを起動するし、keep alive も(たぶん)効かなくなるのでパフォーマンスは大きく落ちるはず。こんなこともできるよ、といったデモ程度の意味しかない。mod_deflate を使えばこのような問題はない。
_ 今年最後の自転車のり。きのう素人なりにディレイラーとかブレーキとか調整してみたら変速が見違えるほどスムーズになった。31km を1時間20分で。
_ つーことで。
富士山に沈む2006年最後の太陽を江戸川から臨む。言われなきゃ富士山だなんてわからんな。_ 帰ってきてからデジカメの日付がちょうど1年ズレてたことに気がついた。EXIF を見ると2005年になってるけど、ついさっき撮った写真です。ほんとなんです信じてください。
_ てなわけで、今年もお世話になりました。よいお年を。