3

ファイルのリポジトリであるWebアプリケーションがそこに座っています。この Web アプリケーションは、クライアントがリポジトリを検索し、SOAP を介して添付ファイルをダウンロードできるようにする Web サービスを提供します。

現在、MTOM で Spring-WS 1.5.8 を使用して添付ファイルをクライアントに送信しようとしましたが、メモリ不足エラーが発生し続けます。私のサーバーには 8 GB のメモリがあり、Tomcat がその 4 GB を使用するように構成しているため、これらのエラーが Tomcat 6 インスタンスに関連しているとは思いません。200MB ほどの小さなファイルでこれらのエラーが発生します。

SOAP を使用する必要がありますが、それはおそらく最善の方法ではありません。私はSpringでの解決策を望んでいますが、それが不可能な場合は、他のアイデアを受け入れます. AxiomSoapMessageFactory を使用して、アップロード目的でファイルをサーバーにストリーミングできることを読みましたが、その逆はできません。これは本当ですか?私はJava 6を使用しています。

Spring WS フレームワーク内で発生し続けるエラーは次のとおりです。

java.lang.OutOfMemoryError: Java heap space
    com.sun.xml.internal.messaging.saaj.util.ByteOutputStream.ensureCapacity(Unknown Source)
    com.sun.xml.internal.messaging.saaj.util.ByteOutputStream.write(Unknown Source)
    com.sun.xml.internal.messaging.saaj.packaging.mime.internet.BMMimeMultipart.find(Unknown Source)
    com.sun.xml.internal.messaging.saaj.packaging.mime.internet.BMMimeMultipart.readBody(Unknown Source)
    com.sun.xml.internal.messaging.saaj.packaging.mime.internet.BMMimeMultipart.getNextPart(Unknown Source)
    com.sun.xml.internal.messaging.saaj.packaging.mime.internet.BMMimeMultipart.parse(Unknown Source)
    com.sun.xml.internal.messaging.saaj.packaging.mime.internet.BMMimeMultipart.parse(Unknown Source)
    com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeMultipart.getCount(Unknown Source)
    com.sun.xml.internal.messaging.saaj.soap.MessageImpl.initializeAllAttachments(Unknown Source)
    com.sun.xml.internal.messaging.saaj.soap.MessageImpl.getAttachments(Unknown Source)
    org.springframework.ws.soap.saaj.Saaj13Implementation.getAttachment(Saaj13Implementation.java:305)
    org.springframework.ws.soap.saaj.SaajSoapMessage.getAttachment(SaajSoapMessage.java:226)
    org.springframework.ws.support.MarshallingUtils$MimeMessageContainer.getAttachment(MarshallingUtils.java:109)
    org.springframework.oxm.jaxb.Jaxb2Marshaller$Jaxb2AttachmentUnmarshaller.getAttachmentAsDataHandler(Jaxb2Marshaller.java:532)
    com.sun.xml.internal.bind.v2.runtime.unmarshaller.MTOMDecorator.startElement(Unknown Source)
    com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(Unknown Source)
    com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(Unknown Source)
    com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(Unknown Source)
    com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source)
    com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source)
    javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    org.springframework.oxm.jaxb.Jaxb2Marshaller.unmarshal(Jaxb2Marshaller.java:421)
    org.springframework.ws.support.MarshallingUtils.unmarshal(MarshallingUtils.java:62)
    org.springframework.ws.client.core.WebServiceTemplate$3.extractData(WebServiceTemplate.java:374)
    org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:560)
4

3 に答える 3

3

それはあなたのエデンスペースが小さすぎることに関係しているかもしれません. Eden スペースは、新しいオブジェクトが割り当てられ、GC を生き残るまで残るヒープの一部です。エデンスペースはそれほど大きくありません。(デフォルト値はありませんが、1GB ヒープのデフォルト設定では 64MB しかありません)

ファイルはおそらく eden スペースにロードされます。200 MB の空き領域がないか、バイト配列が小さく割り当てられており、拡大する必要があります。Java で配列をスローする唯一の方法は、新しいより大きな配列を割り当てて memcopy を実行することです。100MB から 200MB への増加には、明らかに合計 300 MB の Eden ヒープ領域が必要です。

-XX:NewSize=4196M4GBのedenヒープスペースを割り当てる設定を試すことができます。

私は、Tomcatが異なるGC /ヒープ戦略を使用するサーバーモードで実行されていることを知らなかったと言わざるを得ません。

jvmstat 3.0visualgc (Java 5 および 6 にバンドルされているディストリビューションではない)から使用して、ヒープを監視し、どのヒープ領域がいっぱいになっているかを判断できます。

また、チェックアウトすることもできます: 5.0 Java[tm] 仮想マシンを使用したガベージ コレクションのチューニング

この問題を解決しても、パフォーマンスが低下し、スケーラブルでないソリューションに直面することになります。おそらく、ある種の直接ストリーミングの方が良いでしょう。その目的のために単純なサーブレットを実装するのは難しいことではありません。

于 2009-11-02T21:47:16.243 に答える
2

Java での SOAP/XML には、常に多くのオーバーヘッドがあり、大量のメモリが必要です。この特定のケースでは、ストリームを別の種類の OutputStream (ByteArrayOutputStream 以外のもの) に直接書き込む代わりに、(大きすぎる) byte[] をメモリに割り当てようとしています。

SOAP インターフェイスのことをまったく忘れて、java.net.URLConnection を使用して基本に戻り、それをさらに構築することを検討しましたか? このようにして、FileOutputStream を使用して InputStream をディスクに直接書き込むことができます。これは、全体をメモリに保存するよりもはるかに効率的です。

于 2009-11-02T19:50:21.837 に答える
0

クライアントに送信されるときにファイルを読み取るのではなく、メモリ内の完全なファイルを処理しているように見えます。

実際のファイルに解決されて送信するURLを作成し、それをそのままにしておく場合、代わりにこれをWebサーバーに分岐させることはできますか?

于 2009-11-02T20:45:45.980 に答える