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;