2012-03-31 8 views
10

Ho un'applicazione che lavora molto su S3, per lo più il download di file da esso. Sto vedendo molti errori di questo tipo e mi piacerebbe sapere se questo è qualcosa sul mio codice o se il servizio è davvero inaffidabile come questo.Il client S3 Java non funziona molto con "Fine del corpo del messaggio delimitato Content-Length" o "Socket java.net.SocketException chiuso"

Il codice che sto usando per leggere dal flusso oggetto S3 è la seguente:

public static final void write(InputStream stream, OutputStream output) { 

    byte[] buffer = new byte[1024]; 

    int read = -1; 

    try { 

    while ((read = stream.read(buffer)) != -1) { 
     output.write(buffer, 0, read); 
    } 

    stream.close(); 
    output.flush(); 
    output.close(); 
    } catch (IOException e) { 
    throw new RuntimeException(e); 
    } 

} 

Questo OutputStream è una nuova BufferedOutputStream (nuova FileOutputStream (file)). Sto usando l'ultima versione del client Java Amazon S3 e questa chiamata viene ritentata quattro volte prima di mollare. Quindi, dopo aver provato questo per 4 volte non riesce ancora.

Eventuali suggerimenti o suggerimenti su come potrei migliorare questo sono apprezzati.

+0

accade con tutti (o la maggior parte di) file, con file casuali, o con una serie limitata e riproducibile? Stai impostando dei metadati prima del primo caricamento? Ho visto casi in cui i metadati (o la mancanza di) su alcuni file potrebbero causare alcuni problemi strani. Se non hai ancora provato, potrebbe valere la pena provare. –

+0

per lo più file casuali e non utilizziamo alcun metadata :( –

+0

Solo un'ipotesi.Avete assicurato che quei file casuali siano correttamente caricati su s3? Provate a scaricare quei file tramite la richiesta GET o qualche altro strumento – shashankaholic

risposta

12

Sono appena riuscito a superare un problema molto simile. Nel mio caso l'eccezione che stavo ottenendo era identica; è successo per file più grandi ma non per piccoli file, e non è mai accaduto affatto mentre si passava attraverso il debugger.

La causa principale del problema era che l'oggetto AmazonS3Client stava recuperando dati inutili durante il download, causando l'interruzione della connessione di rete. Questo è accaduto perché stavo costruendo un nuovo oggetto AmazonS3Client con ogni chiamata per caricare un file, mentre il caso d'uso preferito è creare un oggetto client di lunga durata che sopravvive attraverso le chiamate - o almeno è garantito che ci sia intorno durante l'intera Scaricare. Quindi, il rimedio semplice è assicurarsi che un riferimento a AmazonS3Client sia mantenuto in modo tale da non ottenere il GC.

Un link sul forum AWS che mi ha aiutato è qui: https://forums.aws.amazon.com/thread.jspa?threadID=83326

+0

Tenere l'oggetto client all'interno del metodo ha fatto il trucco, ahi. Grazie Steve! –

0
  1. Provare a utilizzare wireshark per vedere ciò che sta accadendo sul filo quando questo accade.

  2. Provare a sostituire temporaneamente S3 con il proprio server Web e verificare se il problema persiste. Se lo fa è il tuo codice e non S3.

Il fatto che sia casuale suggerisce problemi di rete tra l'host e alcuni degli host S3.

1

Prima di tutto, il codice funziona completamente normalmente se (e solo se) si verificano problemi di connettività tra te e Amazon S3. Come Michael Slade points out, si applicano i consigli di debug a livello di connessione standard.

Per quanto riguarda il codice sorgente effettivo, prendo nota di alcuni odori di codice di cui dovresti essere a conoscenza. indicandoli direttamente alla fonte:

public static final void write(InputStream stream, OutputStream output) { 

    byte[] buffer = new byte[1024]; // !! Abstract 1024 into a constant to make 
            // this easier to configure and understand. 

    int read = -1; 

    try { 

    while ((read = stream.read(buffer)) != -1) { 
     output.write(buffer, 0, read); 
    } 

    stream.close(); // !! Unexpected side effects: closing of your passed in 
        // InputStream. This may have unexpected results if your 
        // stream type supports reset, and currently carries no 
        // visible documentation. 

    output.flush(); // !! Violation of RAII. Refactor this into a finally block, 
    output.close(); // a la Reference 1 (below). 

    } catch (IOException e) { 
    throw new RuntimeException(e); // !! Possibly indicative of an outer 
            // try-catch block for RuntimeException. 
            // Consider keeping this as IOException. 
    } 
} 

(Reference 1)

In caso contrario, il codice stesso sembra che vada bene. Le eccezioni IO dovrebbero essere previste nelle situazioni in cui ci si connette a un host remoto volubile, e il modo migliore di agire è redigere un criterio sano da memorizzare nella cache e riconnettersi in questi scenari.

0

Anche S3 potrebbe chiudere connessioni lente in base alla mia esperienza.

+0

Se è possibile, prova a memorizzare il tuo stream di input in file e caricalo a S3 tramite browser usando POST (sostituisci il codice del tuo server java sul browser sul stessa macchina per scoprire se il problema è nel tuo codice) –

0

Vorrei dare un'occhiata da vicino all'apparecchiatura di rete più vicina all'app del cliente. Questo problema presenta alcuni dispositivi di rete che perdono pacchetti tra te e il servizio. Cerca di vedere se c'era un punto di partenza quando si è verificato il problema. Sono state apportate modifiche come l'aggiornamento del firmware a un router o la sostituzione di un interruttore in quel periodo?

Verificare l'utilizzo della larghezza di banda rispetto all'importo acquistato dall'ISP. Ci sono momenti del giorno in cui ti stai avvicinando a quel limite? Puoi ottenere grafici sull'utilizzo della larghezza di banda? Verifica se le terminazioni premature possono essere correlate con l'utilizzo della larghezza di banda elevata, in particolare se si avvicina a un limite noto. Il problema sembra prendere su file più piccoli e su file di grandi dimensioni solo quando hanno quasi finito di scaricare? L'acquisto di più larghezza di banda dal tuo ISP può risolvere il problema.

+0

Queste sono macchine EC2 che si collegano alle macchine S3, non c'è alcun tipo di limite. Ma grazie comunque :) –

3

La rete sta chiudendo la connessione, prima che il client ottenga tutti i dati, per una ragione o per l'altra, è quello che sta succedendo.

Parte di qualsiasi richiesta HTTP è la lunghezza del contenuto, il codice sta ricevendo l'intestazione, dicendo hey amico, ecco i dati, e questo è molto di esso .. e quindi la connessione sta cadendo prima che il client abbia letto tutto il dati .. quindi il suo bombardamento con l'eccezione.

Guarderei le impostazioni di timeout della connessione OS/NETWORK/JVM (anche se JVM generalmente eredita dal sistema operativo in questa situazione). La chiave è capire quale parte della rete sta causando il problema. E 'il tuo livello di computer che dice, no non aspetterà più per i pacchetti .. è che stai usando una lettura non bloccante, che ha un'impostazione di timeout nel tuo codice, dove sta dicendo, hey, non hai ottenuto tutti i dati dal server più a lungo di quanto dovrei aspettare, quindi ho intenzione di rilasciare la connessione e l'eccezione. ecc ecc. ecc.

La migliore scommessa è quella di basso livello snoop il traffico di pacchetti e il tracciamento all'indietro, per vedere dove si verifica la caduta della connessione, o vedere se è possibile aumentare il timeout in cose che è possibile controllare, come il software e il sistema operativo/JVM.

+0

Che bello, stiamo incontrando questo problema per un po ' ora e anche problemi di timeout con il nostro Load Balancer. Per qualche ragione non mi ha colpito, i due potrebbero essere uguali. –

Problemi correlati