- - PR -
クライアント-サーブレット間の通信について
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2004-03-19 19:12
はじめまして、つんきちと言います。
突然ですが、質問があります。 教えて頂けないでしょうか? 現在、AppletとServletを使用したシステムを構築しています。 その詳細はオブジェクトをシリアライズしてサーバとクライアント間を通信していま す。 ですが、この方法ではシリアライズに時間がかかってしまい、業務に耐え兼ねないと 判断しています。 下記にソースのサンプルを添付します。 下記のソースは、GZIPInputStreamを用いております。 通常のOutputStreamより、30%(7MByteのオブジェクト)ほど応答時間が改善されました。 これより、さらに応答時間を短縮したいのですが、 何か良い技術は、ありますでしょうか? ※SERVLET側ソースサンプル(一部抜粋) /** * 受信 * @param request * @return */ public Hashtable receive(HttpServletRequest request){ Hashtable hashRe = new Hashtable(); ObjectInputStream ois = null; GZIPInputStream zipIn = null; zipIn = new GZIPInputStream(new BufferedInputStream(request.getInputStream())); ois = new ObjectInputStream(zipIn); hashRe = (Hashtable)ois.readObject(); ois.close(); return hashRe; } /** * 送信 * @param res * @param hashSe */ public void send(HttpServletResponse res, Hashtable hashSe){ ObjectOutputStream oos = null; GZIPOutputStream gzos = null; try{ //圧縮先ファイルへのストリームを開く gzos = new GZIPOutputStream(new BufferedOutputStream(res.getOutputStream()) ); oos = new ObjectOutputStream(gzos); oos.writeObject(hashSe); oos.flush(); }finally{ try { oos.close(); gzos.close(); } catch (IOException e) { e.printStackTrace(); } } } ※クライアント側ソースサンプル(一部抜粋) /** * サーブレットにデータを送信する * @param conn コネクション * @param hashSnd */ private void send(URLConnection conn, Hashtable hashSnd){ ObjectOutputStream oos = null; GZIPOutputStream zipOut = null; //出力ストリーム作成 zipOut = new GZIPOutputStream(conn.getOutputStream()); oos = new ObjectOutputStream(new BufferedOutputStream(zipOut)); //送信 oos.writeObject(hashSnd); oos.flush(); oos.close(); } /** * サーブレットからデータを受信する * @param conn コネクション * @return 受信したデータ */ private Hashtable recieve(URLConnection conn){ Hashtable hashRcv = null; ObjectInputStream ois = null; GZIPInputStream zipIs = null; //入力ストリーム作成 zipIs = new GZIPInputStream(conn.getInputStream()); ois = new ObjectInputStream(new BufferedInputStream(zipIs)); //受信 hashRcv = (Hashtable) ois.readObject(); return hashRcv; } | ||||
|
投稿日時: 2004-03-19 19:19
はじめまして、なっちゃんです。
私もこの問題に直面したことがあるのですが、やはりオブジェクトのサイズを小さくするしか ないのでしょうか?それともZIP形式ではなく、他の圧縮形式でためしてみるのも良いかもしれません。お役に立てなくて申し訳ありませんでした。 | ||||
|
投稿日時: 2004-03-19 19:32
ストリームの処理は結構重たいので、gzip による圧縮を Apache にやらせてはいかがでしょうか?
mod_gzip(Apache1.3.x)やmod_deflate(Apache2.0.x)などに処理させることができます。 | ||||
|
投稿日時: 2004-03-19 20:05
どのようなオブジェクトなのか判りませんが、差分だけやり取りしてはいかがでしょうか?
#「そんなに単純じゃないよ」 ってツッコミが聞こえてきそうですが・・・。 | ||||
|
投稿日時: 2004-03-19 21:25
返信ありがとうございます。つんきちです。
>ストリームの処理は結構重たいので、gzip による圧縮を >Apache にやらせてはいかがでしょ>うか? >mod_gzip(Apache1.3.x)やmod_deflate(Apache2.0.x)などに処理させることができます。 ありがとうございます。 早速、試してみます。 >どのようなオブジェクトなのか判りませんが、差分だけやり取りしてはいかがでしょうか? 現在の処理としましては、 DB検索後(SERVLET側)のオブジェクト群が7Mほどに、なってしまいます。 (7Mは、大きすぎるのでしょうか。。) キャッシュ技術か何かで、差分だけやり取りという技術があるのでしょうか? | ||||
|
投稿日時: 2004-03-19 23:13
自前での実装を前提にして投稿しました。 サーバからクライアントがオブジェクトを取得し、加工してサーバへ送り返すと勝手に判断しました。(間違っていたらごめんなさい) クライアントがオブジェクトを握っている間は、他のクライアントからの要求は考慮しなくてもいい仕様なのだろうと。 だったら、オブジェクトの世代を管理して、その差分をやり取りしたらどうだろう? と、思ったわけです。 変更ログを使ってデータベースをリカバリするようなイメージで・・。 ズレた話をしていたら申し訳ないです・・。 | ||||
|
投稿日時: 2004-03-20 10:22
unibon です。こんにちわ。
7MBでしょうか。程度問題だとは思いますので、いわゆるハード増強とか、あるいは技術が進歩するまで寝て待つ Hashtable をシリアライズされているようですが、Hashtable のコードを見ると key と value を地道にエントリの順番にシリアライズしているだけであり、Hashtable 自体を改善する余地は残っていないようです。 key や value の個数を減らしたり、あるいは、たとえば key や value が文字列ならば文字数を減らすとかといった余地は残っているので、アプリケーションの仕様の範囲内で工夫することはできるかもしれませが、どんな性質のデータなのかが分からないとなんとも言えないです。 ほかのソリューションとしては、マルチスレッドを使ってシリアライズデータを読みながらでもユーザインターフェースを受けつけるようにするなどですが、状態遷移の管理が面倒になります。 | ||||
|
投稿日時: 2004-03-23 11:58
Hashtable#writeObject()のソースコードを読むと、「内容が重複するエントリのvalueやkeyオブジェクトについても、逐一Serializeしている」ようですので、ここで「Hashtable内部で重複するkey,valueについては1つのインスタンスのみSerializeし、個々のエントリの要素はサイズの小さい自作リファレンスオブジェクトで代用する」ような処理をすると、重複する要素のサイズや数によっては小さくなるかもしれません。
私は実績を持っていないので、やってみないと分かりませんが… #JSR-000114 JDBC(TM) Rowset Implementationsを利用するというのは、解決策になりますか?JDK1.5以降でコアAPIになると聞いた覚えがあるのですが。 http://jcp.org/aboutJava/communityprocess/review/jsr114/ [追記] keyが重複するはずがありませんね。すみません^^; [ メッセージ編集済み 編集者: シュン 編集日時 2004-03-23 12:05 ] | ||||
