• ベストアンサー

javaのxmlファイル出力をするウェブアプリでの複数アクセスがあった時の挙動について

基本的な考え方の問題になってしまうと思います。 また、質問攻めな文章になってしまいましたが、どうにも解決できないので質問させて下さい。 現在、WindowsXP/Eclipse3.3/Tomcat5.5/GEF3.3/struts- 1.3.8/JDK1.5の環境で、 参考書は「Eclipseパーフェクトマニュアル ベストセレクション」 「xml 逆引きクイックリファレンス」 という本をもとに勉強しています。 ブラウザの書き込みフォームからのSubmitで、 書き込まれた内容をxmlに出力するウェブアプリ(Strutsで作成したWAR)の作成を考えています。 簡単に言えば、 Aさんが「発注します」と書き込み Bさんが「発注します」と書き込み Cさんが「A、B発注希望受領しました」と書き込み というメッセージを受けた順番で「発注管理.xml」に出力するイメージです。 上記の例で言えば、AさんとBさんの他、仮に大勢の人が同時一斉に書き込んだ場合、発注管理.xmlへ正常に書き込めなくなるケースを恐れているのですが、こうしたケースはあるのでしょうか?  また、多重のアクセスに対してはアプリ(Strutsで作成したWAR)が勝手にアクセスとファイル出力をさばいていってくれるのかと考えたのですが、この考えは誤りでしょうか?  それとも、こうした場合には自前で書き込みスレッド(synchronized)を用意して、スレッドの生成上限数を1つに設定、上限を超えたら「リトライして下さい」というエラーページに飛ぶ、と言った形でないとダメなのでしょうか? 

質問者が選んだベストアンサー

  • ベストアンサー
  • OKbokuzyo
  • ベストアンサー率43% (130/296)
回答No.3

ソースによりけりですが一般的な回答を。 >仮に大勢の人が同時一斉に書き込んだ場合、発注管理.xmlへ正常に書き込めなくなるケースを恐れているのですが、こうしたケースはあるのでしょうか?  あります。 質問文を読む限り、ひとつのxmlファイル(発注管理.xml)で 全データを扱うのですよね? 正常に書き込めないというより、 タイミングによってリクエストされたデータを消失する恐れがあります。 多分DOMを使ってXMLは処理していると思いますが 例えば、 1.Aさんからリクエスト → 処理開始 → XMLファイルを読み込み 2.Bさんからリクエスト → 処理開始 → XMLファイルを読み込み 3.Aさんからリクエスト処理を終了(XMLファイルへ書き込み)。 4.Bさんからリクエスト処理を終了(XMLファイルへ書き込み)。 という順序で処理された場合、Aさんからのリクエストによって 作成されたデータは4の処理を終えた時点で消失してしまいます。 2の処理時点ではファイルにはAさんからのリクエストデータが 存在しないからです。 これを回避するには排他を行ったりキューを利用したりしますが そもそもDBを使えば解消できます。 というより通常はDBを使うでしょう。(XMLの勉強中なのかもしれませんが) 他にも問題はあります。 発注業務は日常茶飯事にデータの新規追加があると思いますが これを1つのxmlファイルで管理するとなると 将来的にファイルサイズが巨大になりすぎてしまいます。 始めは問題なくとも、システムを使い出すとしばらくして すぐにいろいろな問題が発生することは想像に難くないです。 (まぁ、ただの勉強でやっているだけでしょうが… >多重のアクセスに対してはアプリ(Strutsで作成したWAR)が勝手にアクセスとファイル出力をさばいていってくれるのかと考えたのですが、この考えは誤りでしょうか? 誤りです。多重アクセスはWebサーバが受け付けますが そのあとはJavaのお話です。Webアプリケーションだからとか関係ありません。 ていうか、勝手にさばかれてもそれはそれで困ります。 >こうした場合には自前で書き込みスレッド(synchronized)を用意して、スレッドの生成上限数を1つに設定、上限を超えたら「リトライして下さい」というエラーページに飛ぶ、と言った形でないとダメなのでしょうか? 何を想像しているのかさっぱりですが 排他で行うなら排他中はスリープでいいと思います。 (たかだか誰かとかぶったくらいでエラーページに飛ぶのはいくらなんでもナンセンスすぎる。webだと入力もやり直しになっちゃうし) 何度か処理を試みてそれでもダメな場合はエラーページに飛ぶ感じでも いいのではないかと。 最後に 繰り返しになりますが、フツーはDBを利用します。

javawater
質問者

お礼

> 例えば、 > 1.Aさんからリクエスト → 処理開始 → XMLファイルを読み込み > 2.Bさんからリクエスト → 処理開始 → XMLファイルを読み込み > 3.Aさんからリクエスト処理を終了(XMLファイルへ書き込み)。 > 4.Bさんからリクエスト処理を終了(XMLファイルへ書き込み)。 > という順序で処理された場合、Aさんからのリクエストによって > 作成されたデータは4の処理を終えた時点で消失してしまいます。 > 2の処理時点ではファイルにはAさんからのリクエストデータが > 存在しないからです。 よく分かりました。詳しい内容を回答頂きありがとうございます。 ご指摘の通り勉強中です。 > 発注業務は日常茶飯事にデータの新規追加があると思いますが > これを1つのxmlファイルで管理するとなると > 将来的にファイルサイズが巨大になりすぎてしまいます。 そうですね。 ご指摘を受けた後に思ったのですが、 こちらは日ごとにファイルを分割しようかと思いました。 仮に1日1MBのxmlファイルが生成されるとして、 100日後に100MBのファイルになる、それを処理するのは 非効率なので、生成される日毎にそのファイル名に日付を付けて そこに出力しようかと。 (1)従来案(稼動から100日後に容量が100MBになっている)   hattyu.xml 100MB (2)代替案(稼動から100日後、一日ごとに出力ファイルを変えている)   hattyu_20100319.xml 1MB   hattyu_20100318.xml 1MB   hattyu_20100317.xml 1MB   hattyu_20100316.xml 1MB ・・・ 実用に耐えないとツッコミが入ると思われますが、こんな感じで対処できるのかな、と思っています。 >フツーはDBを利用します。 そうですね・・・しかし、DBを使用しない予定なのです。 色々と勉強になりました。 手厳しい回答ありがとうございました。 今後とも宜しくお願い致します。

javawater
質問者

補足

補足です。 DBを使用しない、と言ったのですが、 どうにもDBを使うのとXMLで実装するのとを比較した際、 メリット・デメリットを勘案して、DBを使用する事になりそうな 気配です。 ご指摘頂きありがとうございました。

その他の回答 (3)

  • Lieserl
  • ベストアンサー率81% (31/38)
回答No.4

DOM使うと遅いので、ベタなテキスト出力で生成するなんてのは 単純な構造のXMLならよくやる手段です。 実体参照へのエスケープは忘れないように。

javawater
質問者

お礼

再度の回答を頂きありがとうございます。 >DOM使うと遅いので、ベタなテキスト出力で生成するなんてのは >単純な構造のXMLならよくやる手段です。 そうなのですね。 >実体参照へのエスケープは忘れないように。 了解です。ご指摘ありがとうございます。

  • Lieserl
  • ベストアンサー率81% (31/38)
回答No.2

XMLの入出力は結構コストが高い(処理が重い)ので、 DBを用意して、テーブルにレコードを追加するアクションと、 別途テーブルから読み込んでXML化してDLする アクションを作った方が現実的かと思います。 気になったのですが、受注処理をする人が複数(たとえばCさんとDさん)いた場合、 AさんとBさんの注文を多重に受けてしまいませんか? A→発注する B→発注する C→発注状況チェック...あ、AさんとBさんから注文きた D→発注状況チェック...あ、AさんとBさんから注文きた D→A,B注文うけつけました C→A,B注文うけつけました

javawater
質問者

お礼

今回はDBは持たない予定なのです。 (DBがもてたらどんなに楽な事か・・・) XML単体は処理が重くてパフォーマンスが悪いのですね。 >気になったのですが、受注処理をする人が複数(たとえばCさんとDさん)いた場合、 >AさんとBさんの注文を多重に受けてしまいませんか? ここは大丈夫です。 説明の時に処理の中身をはしょってしまいましたが、 発注先は書き込みの内容中にありますので。 回答頂きありがとうございました。

javawater
質問者

補足

補足質問させて下さい。 質問には記載しなかったのですが、 現在のxml出力には、DOMオブジェクトの出力を、 TransformerFactory tfactory = TransformerFactory.newInstance(); Transformer transformer = tfactory.newTransformer(); File outfile = new File("sample22.xml"); などでやっています。 これを、例えばxml出力を使わず、 <hattyu> <order type="tv"> <count>3</count> </order> </hattyu> という”文字列”を出力するという形にするとかでも重いのでしょうか?  単なるファイルの入出力もパフォーマンス的に重いのでしょうか? 

  • _ranco_
  • ベストアンサー率58% (126/214)
回答No.1

アプリが勝手に~という部分は、コードを見ないかぎりなんとも言えません。自前のコードでやるなら、先入れ先出しのキューを使って非同期で処理してください。詳しくはjava.util.concurrentのドキュメンテーションや参考書をよく読んでください。

javawater
質問者

お礼

ご紹介頂いたドキュメントを見てみます。 回答ありがとうございました。

関連するQ&A