2015-11-28 15 views
6

Potrzebuję przenieść duże pliki (co najmniej 14 MB) z instancji Cosmos laboratorium FIWARE do mojego zaplecza.Jak mogę odczytać i przesłać fragmenty pliku za pomocą Hadoop WebHDFS?

kiedyś sprężyna RestTemplate jako interfejs klienta dla hadoop WebHDFS odpoczynek czynnych opisano here ale prowadzony w wyjątek 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) 

to rzeczywisty kod, który generuje wyjątek:

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(); 

Myślę, że jest to spowodowane przekroczeniem limitu czasu transferu w instancji Cosmos, więc próbowałem uzyskać wysłać curl na ścieżce, podając parametry offset, buffer and length, ale wydaje się, że są ignorowane: Mam cały plik.

Z góry dziękuję.

+0

Może patrząc na py webhdfs dostaniesz wskazówki -> https://github.com/pywebhdfs/pywebhdfs/blob/master/pywebhdfs/webhdfs.py#L48 – ravwojdyla

+1

Dzięki, ale to nie pomaga. Problem polega na tym, że opcjonalny parametr długości operacji OPEN (patrz "def read_file (self, path, ** kwargs)" w twoim linku) jest całkowicie ignorowany przez serwer –

Odpowiedz

4

Ok, znalazłem rozwiązanie. Nie rozumiem, dlaczego, ale transfer się uda, jeśli użyję Jetty HttpClient zamiast RestTemplate (a więc Apache HttpClient). Działa to teraz:

ContentExchange exchange = new ContentExchange(true){ 
      ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

      protected void onResponseContent(Buffer content) throws IOException { 
       bos.write(content.asArray(), 0, content.length()); 
      } 

      protected void onResponseComplete() throws IOException { 
       if (getResponseStatus()== HttpStatus.OK_200) { 
        FileOutputStream output = new FileOutputStream(new File(<local_path>)); 
        IOUtils.write(bos.toByteArray(), output); 
        output.close(); 
       } 
      } 

     }; 

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

exchange.setURL(builder.build().encode().toUriString()); 
exchange.setMethod("GET"); 
exchange.setRequestHeader("X-Auth-Token", <token>); 

HttpClient client = new HttpClient(); 
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); 
client.setMaxConnectionsPerAddress(200); 
client.setThreadPool(new QueuedThreadPool(250)); 
client.start(); 
client.send(exchange); 
exchange.waitForDone(); 

Czy jest jakiś znany błąd w kliencie HTTP Apache do transferu plików porwanych?

Czy robiłem coś nie tak na mojej próbie RestTemplate?

UPDATE: I nadal nie ma rozwiązania

Po kilku testach widzę, że nie rozwiązali swoje problemy. Dowiedziałem się, że wersja hadoop zainstalowana w instancji Cosmos jest dość stara. Hadoop 0.20.2-cdh3u6 i czytałem, że WebHDFS nie obsługuje częściowego przesyłania plików z parametrem length (introduced since v 0.23.3). Są nagłówki I otrzymane z serwera kiedy wysłać żądanie GET korzystając 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 

Jak widać nagłówek połączenia jest ustawiony, aby zamknąć. W rzeczywistości połączenie jest zwykle zamykane za każdym razem, gdy żądanie GET trwa dłużej niż 120 sekund, nawet jeśli transfer plików nie został zakończony.

Podsumowując, mogę powiedzieć, że Cosmos jest całkowicie bezużyteczny, jeśli nie obsługuje dużego transferu plików.

Proszę poprawić mnie, jeśli się mylę, lub jeśli znasz sposób obejścia problemu.

Powiązane problemy