Dolipoや
Polipoが
話題になっているようで。
でもその原理になっている HTTP/1.1の仕組みとかはそれほど理解されてなさそう。
この記事
でも Poor Man's Multiplexingは飛ばしちゃってるし。
ということで、自分の思い出すのと UMLGraphの練習を兼ねて
解説したいと思います。
Sequence図の UMLGraph sourceももれなく公開という大盤振る舞いです
(って、だれが喜ぶんだろう)。
HTTP 0.9
まず、HTTPの基本形とは以下のようなかんじです。
Requestがあって Responseがあるという単純なもの。
そして重要なのが transactionごとに TCPを張り直すということ。
これは、HTTP/0.9時代は responseの終わりを TCP Disconnectionで
示すという荒っぽい仕様だったためしかたないっす。
つまり、三つの tranasctionがあったら以下のようになります。
TCPの SYNや FINの時間がもったいないっすね。
HTTP/1.1 の工夫
ということで出てくるのが persistent connectionです。
これは HTTP/1.0では Content-length headerでコンテントの
終わりを明示できるのでできる技です。
HTTP/1.1ではこれが標準になってます:
絵の上からでも短くなったのが分かるでしょう。
さらに、全体の応答時間 (latency) を短くするための
工夫が pipeliningです。
絵ではちとズルをして縦幅を短くしてありますが、
Responseを待ってから次の Requestを
投げるより、Requestを立て続けに投げた方が
全体として時間を無駄にしてないのはイメージできますよね?
あともう一つ、Range Requestの話もしときます。
これは、コンテンツを頭から読み出すんじゃなくて
指定したバイトから指定した長さだけ呼び出すってもの。
たとえば PDF Pluginとかで使われてます。
Web最適された文書の場合、読みたいページに飛んだらそこの
内容だけを読み出すようにして、いらない途中のページの転送時間をかけない。
だから、PDFは Downloadして Helper applicationで読むより、
Pluginで読む方が早いはず。
でも、個人的には昔の Pluginが不安定だったり、
Pluginだと画面が狭くなるので、Helper applicationで呼んでますが。
polipoはこういう技術をバリバリ慎重に使ってる
で、こういう風な工夫がされているのが HTTP/1.1なんだけど、
実のところ積極的には使用されてないような気がします。
調べたわけじゃないので断言できないけど。
少なくとも某社のブラウザとかでは。
なぜかといえばいろいろ実運用上問題があるから。
たとえば典型的な問題に pipeline stallというのがあります。
上の sequece chartでいえば、
Response1 がすごく重い CGIで生成される画像で、
Response2 がちっちゃい静的な画像だったりします。
そうすると、Response1の生成に時間がかかってるせいで、
Response2の画像も画面に表示することができない。
複数 connectionを張っていれば、Response2はサクッと
素早く取り出せたのに。
まあ、そういうしがらみがあって、みんな保守的にやってるのかもしれません。
そこを、polipoは果敢に使える機能は使っちゃってるので
いい感じに早くなってるのかも。
そして、そういう問題を回避する know howとかも入ってるんじゃ
ないかなあ、って documentも読まずに想像してます。
「polipoのパイプラインについて」(わかつも) によると
polipoはサーバーがパイプラインをサポートしているか慎重に調べ(carefully probes)てからパイプラインを使うぜ
だそうです。ここら辺が肝なんでしょうねえ。
最後に Poor Man's Multiplexing
で、最後に問題の Poor Man's Multiplexingについて説明します。
でもドキュメント見ると polipoの PMMって既定値では offなんですよね。
やっぱり "an intrinsically unreliable technique" (本質的に信頼できない技巧) だからねえ。
ということで PMMは polipoの高速性にはあんまり貢献してないと思うんですが、
乗りかかった船ということで。
最初に、Multiplexingとは何かと言うと、
複数の transactionを順番じゃなくて同時に送っちゃうことです。
本来 Persistent connectionや pipelineを使っても、objectは順番にしか
取り出せないわけです。
で、 pipeline stallとかの問題が起こるわけです。
ちょっと前の (今でも?) お行儀の悪い web browserとかでは、
そこらへんは 複数 connecitionで回避してたわけです。
Operaの connectionの張り方なんてすごかった気がします。
最近はおとなしくなったんでしょうか。
HTTP/1.1 では client ごとに 2本だけの connectionにしとけよ! って
仕様にかかれていて、やっぱりこれを守りつつ multiplexしたい!
というと PMMになっちゃったんでしょう。
っていういみでは、Poor Manじゃなくて、規約を守る
Nice Man's Multiplexingって気もしますが。
どうやってやるかというと、Pipelining と Range requestを
駆使するんだと思います。多分。実験しないでかいて申し訳ありませんが。
Content{0, 1, 2} を擬似的に同時に取りたい場合、
- Content0 を先頭から 1KiB だけ
- Content1 を先頭から 1KiB だけ
- Content2 を先頭から 1KiB だけ
- つぎに Content0 を 1KiB目から 1KiB
- 以下続く
って感じに Pipeliningを使ってやるんだと思います。
試してませんが。
まあ、でもこれも Content2が重い CGIだったりすると stallする
可能性は大なので、労多くして益少なし、ってことで offになってるんでしょう。
まとめ
UMLGraphは便利だけど、いまどき PSを吐くので Pngにするのが面倒です。
ここら辺、自動的にやってくれないかなあ。
最近のコメント