2015-11-28 14 views
6

Tôi cần chuyển các tệp lớn (ít nhất 14MB) từ trường hợp Cosmos của Phòng thí nghiệm FIWARE sang chương trình phụ trợ của tôi.Làm thế nào tôi có thể đọc và chuyển các khối tệp bằng Hadoop WebHDFS?

tôi đã sử dụng RestTemplate mùa xuân như một giao diện khách hàng cho Hadoop WebHDFS REST API được mô tả here nhưng tôi chạy vào một ngoại lệ 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) 

Đây là mã thực tế mà tạo ra những ngoại lệ:

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

Tôi nghĩ rằng điều này là do thời gian chờ truyền trên phiên bản Cosmos, vì vậy tôi đã cố gắng gửi curl trên đường dẫn bằng cách chỉ định các thông số offset, buffer and length, nhưng chúng dường như bị bỏ qua: Tôi có toàn bộ tập tin.

Xin cảm ơn trước.

+0

Có thể nhìn vào py webhdfs sẽ cung cấp cho bạn một số manh mối -> https://github.com/pywebhdfs/pywebhdfs/blob/master/pywebhdfs/webhdfs.py#L48 – ravwojdyla

+1

Cảm ơn, nhưng nó không giúp ích gì. Vấn đề là tham số chiều dài tùy chọn của hoạt động OPEN (xem 'def read_file (tự, đường dẫn, ** kwargs)' trong liên kết của bạn) hoàn toàn bị bỏ qua bởi máy chủ –

Trả lời

4

Ok, tôi đã tìm ra giải pháp. Tôi không hiểu tại sao, nhưng chuyển giao succeds nếu tôi sử dụng một HttpClient Jetty thay vì RestTemplate (và vì vậy Apache HttpClient). Công trình này hiện đang hoạt động:

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

Có lỗi nào đã biết trên ứng dụng Apache Http dành cho việc truyền tải tệp chunked không?

Tôi có đang làm gì đó sai trong yêu cầu RestTemplate của mình không?

CẬP NHẬT: Tôi vẫn không có giải pháp

Sau một vài thử nghiệm, tôi thấy rằng tôi chưa giải quyết được sự cố của mình. Tôi phát hiện ra rằng phiên bản hadoop được cài đặt trên phiên bản Cosmos khá cũ Hadoop 0.20.2-cdh3u6 và tôi đọc rằng WebHDFS không hỗ trợ truyền tải một phần với thông số length (introduced since v 0.23.3). Đây là những tiêu đề tôi nhận được từ máy chủ khi tôi gửi một yêu cầu GET sử dụng 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 

Như bạn thấy tiêu đề kết nối được thiết lập để đóng. Trên thực tế, kết nối thường được đóng lại mỗi lần yêu cầu GET kéo dài hơn 120 giây, ngay cả khi việc truyền tệp chưa hoàn tất.

Tóm lại, tôi có thể nói rằng Cosmos hoàn toàn vô dụng nếu nó không hỗ trợ truyền tệp lớn.

Vui lòng sửa tôi nếu tôi sai hoặc nếu bạn biết cách giải quyết.

Các vấn đề liên quan