2015-11-28 13 views
6

Ho bisogno di trasferire file di grandi dimensioni (almeno 14 MB) dall'istanza Cosmos di FIWARE Lab al mio back-end.Come posso leggere e trasferire blocchi di file con Hadoop WebHDFS?

ho usato primavera RestTemplate come interfaccia client per il Hadoop WebHDFS REST API descritti here ma corro in un'eccezione IO:

Exception in thread "main" org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://cosmos.lab.fiware.org:14000/webhdfs/v1/user/<user.name>/<path>?op=open&user.name=<user.name>":Truncated chunk (expected size: 14744230; actual size: 11285103); nested exception is org.apache.http.TruncatedChunkException: Truncated chunk (expected size: 14744230; actual size: 11285103) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:580) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545) 
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:466) 

Questo è il codice che genera l'eccezione:

RestTemplate restTemplate = new RestTemplate(); 
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); 
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter()); 
HttpEntity<?> entity = new HttpEntity<>(headers); 

UriComponentsBuilder builder = 
    UriComponentsBuilder.fromHttpUrl(hdfs_path) 
     .queryParam("op", "OPEN") 
     .queryParam("user.name", user_name); 

ResponseEntity<byte[]> response = 
    restTemplate 
     .exchange(builder.build().encode().toUri(), HttpMethod.GET, entity, byte[].class); 

FileOutputStream output = new FileOutputStream(new File(local_path)); 
IOUtils.write(response.getBody(), output); 
output.close(); 

Penso che questo sia dovuto a un timeout di trasferimento sull'istanza Cosmos, quindi ho provato a inviare un curl sul percorso specificando i parametri offset, buffer and length, ma sembrano essere ignorato: ho ottenuto l'intero file.

Grazie in anticipo.

+0

Forse guardando py webhdfs vi darà alcuni indizi -> https://github.com/pywebhdfs/pywebhdfs/blob/master/pywebhdfs/webhdfs.py#L48 – ravwojdyla

+1

Grazie, ma non aiuta. Il problema è che il parametro di lunghezza opzionale dell'operazione OPEN (vedi 'def read_file (self, path, ** kwargs)' nel tuo link) è totalmente ignorato dal server –

risposta

4

Ok, ho trovato una soluzione. Non capisco perché, ma il trasferimento viene eseguito se utilizzo un Jetty HttpClient anziché il RestTemplate (e quindi Apache HttpClient). Funziona ora:

C'è qualche errore noto sul client Http Apache per il trasferimento di file chunked?

Stavo facendo qualcosa di sbagliato nella mia richiesta di RestTemplate?

UPDATE: Io ancora non ho una soluzione

Dopo alcune prove vedo che io non ho risolto i miei problemi. Ho scoperto che la versione di hadoop installata nell'istanza Cosmos è piuttosto vecchia Hadoop 0.20.2-cdh3u6 e ho letto che WebHDFS non supporta il trasferimento parziale di file con il parametro length (introduced since v 0.23.3). Queste sono le intestazioni che ho ricevuto dal server quando invio una richiesta GET utilizzando curl:

Access-Control-Allow-Origin: * 
Access-Control-Allow-Methods: HEAD, POST, GET, OPTIONS, DELETE 
Access-Control-Allow-Headers: origin, content-type, X-Auth-Token, Tenant-ID, Authorization 
server: Apache-Coyote/1.1 
set-cookie: hadoop.auth="u=<user>&p=<user>&t=simple&e=1448999699735&s=rhxMPyR1teP/bIJLfjOLWvW2pIQ="; Version=1; Path=/ 
Content-Type: application/octet-stream; charset=utf-8 
content-length: 172934567 
date: Tue, 01 Dec 2015 09:54:59 GMT 
connection: close 

Come vedete l'intestazione Connection è impostato per chiudere. In realtà, la connessione viene solitamente chiusa ogni volta che la richiesta GET dura più di 120 secondi, anche se il trasferimento del file non è stato completato.

In conclusione, posso dire che Cosmos è totalmente inutile se non supporta il trasferimento di file di grandi dimensioni.

Per favore correggimi se ho torto o se sai una soluzione alternativa.

Problemi correlati