2015-11-28 17 views
6

FIWARE LabのCosmosインスタンスから大きなファイル(最低14MB)をバックエンドに転送する必要があります。Hadoop WebHDFSでファイルのチャンクを読み込んで転送するにはどうすればよいですか?

HadoopのWebHDFS REST APIのクライアント・インタフェースがhereを説明したが、私はIO例外に遭遇すると、私は春RestTemplateを使用:

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) 

これは、例外を生成し、実際のコードです:

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

私はこれがCosmosインスタンスの転送タイムアウトに起因すると考えています。したがって、 はをパスにoffset, buffer and lengthパラメータを指定して送信しようとしましたが、そのように見えます無視される:私はファイル全体を得た。

ありがとうございます。

+0

py webhdfsを見てみると、いくつかの手がかりを得ることができます - > https://github.com/pywebhdfs/pywebhdfs/blob/master/pywebhdfs/webhdfs.py#L48 – ravwojdyla

+1

ありがとうございますが、助けになりません。問題は、OPEN操作のオプションの長さパラメータ(リンク内の 'def read_file(self、path、** kwargs)'を参照)がサーバーによって完全に無視されることです –

答えて

4

私は解決策を見つけました。私は理由を理解できませんが、RestTemplate(とApache HttpClient)の代わりにJetty HttpClientを使用すると転送が成功します。これは今動作します:

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

チャンクファイル転送のApache Httpクライアントには既知のバグはありますか?

RestTemplateリクエストで何か問題がありましたか?

UPDATE:私はまだ私は私の問題を解決していないことを見るいくつかのテストの後

解決策を持っていません。 Cosmosインスタンスにインストールされているhadoopバージョンがかなり古いことがわかりましたHadoop 0.20.2-cdh3u6そして、WebHDFSは部分ファイル転送をlengthパラメータ(introduced since v 0.23.3)でサポートしていません。 これらは私がcurlを使用してGETリクエストを送信するとき、私はサーバーから受信したヘッダです:

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 

あなたはConnectionヘッダを閉じるように設定されて見ての通り。実際には、ファイル転送が完了していなくても、GET要求が120秒を超えるたびに接続が通常閉じられます。

結論として、大きなファイル転送をサポートしていない場合、Cosmosは全く役に立たないと言えます。

私が間違っている場合、または回避策が分かっている場合は、私に修正してください。

関連する問題