Article delegate-ja/55 of [1-251] on the server localhost:7119
  upper oldest olders older1 this newer1 newers latest
search
[Top/Up] [oldest] - [Older+chunk] - [Newer+chunk] - [newest + Check]
[Reference:<_A54@delegate-ja.ML_>]
Newsgroups: mail-lists.delegate-ja

[DeleGate-Ja] Re: HTTP Proxy でページが途中までしか読み込まれない(EMERGENCY EXIT)
22 May 2007 04:28:41 GMT ysato@delegate.org (Yutaka Sato)
The DeleGate Project

In message <_A54@delegate-ja.ML_> on 05/22/07(12:21:32)
you Katsuaki Shimadera <pe4aabrv6-mxhgu42ejwxw.ml@delegate.org> wrote:
 |早速のご対応ありがとうございます。
 |同封のパッチで問題が発生しなくなることを確認しました。
 |パッチを当てた状態で運用し様子を見てみます。

これは、gzip圧縮した結果が16KBを越えるデータでは必ず再現するはずです。

 |>各種のLinuxや、FreeBSD、MacOSXで調べましたが、問題が起こるのはSolaris
 |>(SunOS5.5, 5.10)だけでした。
 |>最終的な対処は、Zlib内の動作を調べてからになりますが、とりあえずSolaris
 |>では、同封のパッチのように、上記の non-blocking I/O を無効にすることで、
 |>この問題を回避できると思います。

zlib1.2.3 でテストしましたが、やはり想像したとおり、SunOSでは、
non-blocking モードの fread() が feof() を設定してしまいます。
ですので、DeleGate側での対処方法も前のメールに書いたとおりなのですが、
逆にDeleGate側を変えずに、Zlib側にパッチをあてるという対処方法もあります。

この方法では、実際に非常に低速なサーバからの応答に対して、クライアントが
応答の最初を見るまでの時間を (gzopen()時の fread() を non-blocking にする
ことにより) 短縮することができます。
Zlibへのパッチと、それをDeleGateで使用するには、以下のようにします。

  0) Zlib1.2.3 のソースを展開
  1) gzio.c に同封のパッチをあてる
  2) configure --shared
  3) make
  4) cp -p libz.so.1.2.3 $DGROOT/etc/dgzlib.so


さて、問題のgzio.c ですが、gunzip/gzip の入力バッファのデフォルトのサイズを
16KB としています。これは、例えば 2400bps 程度の非常に遅いもしくは重い
回線経由では、それが満たされるまでに1分近くかかってしまうことになり、この
間クライアントは、何も受け取ることなく待たされることになります。

In message <_A53@delegate-ja.ML_> on 05/22/07(09:55:14) I wrote:
 |なおこれは、もともとZlibのgzio.c:gzopen(),gzread()の実装の問題(常に受信
 |バッファをいっぱいにしてから処理しようとするので、ストリーム型の処理に向か
 |ない)をとりあえず回避しようとしたものでもあります。gzio.cにはこの他にも
 |手を入れたいところがありますので、根本的な解決のためには、gzio.c 相当の
 |ものを自前で作らないといけないと思っています。

より単純な解決方法は、このバッファのサイズ(Z_BUFSIZE)を小さくしてしまう
ことなのですが、そうすると今度は、大きなデータをgzipする際に(多少でしょう
けど)重くなる可能性があります。最初だけ小さくするとか、入力サイズを設定
する関数を追加するという手もあります。
実際9.6.0-preXの最初では、このあたりの改変したZlib1.2.3をデフォルトの
dglibzとして配布することを考えていたのですが、技術的には簡単でも、インス
トールは少なからず複雑化することになりますので、見合わせました。
それで、代替に実装したのが、今回 Solaris で問題になった、gzopen() だけ
non-blocking にして、その後のgzread() は blocking に戻すという方法だった
のでした。

Windows用には以前から dgzlib が必要になっていますし、応答性とスループット
を両立するには結局gzio.cに手を入れるか自作するしかないし、dglibz だけでなく
ついでに dglibssl や subin も自動ダウンロード+インストールするという方向で
9.6.1 (以降)で対処したいと思っています。

                   9 9  
┌─┐┬┌──┬┐ //\^^ ( e ); {Do the more with the less -- B. Fuller}
├─┤│└─┐│ / 877m\_<   >_ <URL:http://www.delegate.org/delegate/>
┴ └┴──┘┴──────────────────────────────
佐藤豊@情報技術研究部門.産業技術総合研究所(独立行政法人)

*** zlib-1.2.3/gzio.c	Tue Jul 12 05:31:48 2005
--- gzio.c	Tue May 22 12:51:36 2007
***************
*** 301,306 ****
--- 301,310 ----
          if (len) s->inbuf[0] = s->stream.next_in[0];
          errno = 0;
          len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+ 
+         /* it might be a bug of SunOS5's fread() in non-blocking mode */
+         if (0 < len && feof(s->file) && errno == 0) clearerr(s->file);
+ 
          if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
          s->stream.avail_in += len;
          s->stream.next_in = s->inbuf;

  admin search upper oldest olders older1 this newer1 newers latest
[Top/Up] [oldest] - [Older+chunk] - [Newer+chunk] - [newest + Check]
@_@V