2016-04-13 21 views
0

Java ortamında, Google Cloud Storage'a günlük dosyalarını günlük olarak yazmak için çalışıyorum. Ham log dosyalarını ayrıştıran ve JSON satırları üreten bir işlem var; JSON satırlarını bir arabellekte saklıyorum ve arabellek her defasında 5mgb'ye her rastladığında, orijinal ham kaynak tamamen ayrıştırılıncaya kadar aynı dosyaya GCS'de yazmak istiyorum. AWS S3'e yazılan benzer bir kurulum var. Parçalardaki yazı hafıza sorunları nedeniyle yapılır. Google Cloud Storage’a, Java API’sı üzerinden nasıl bir yükleme yapılır?

ben şöyle GCS bir dosya yazmayı başardı (gcsService vb doğrulamalarıyla ve yapılandırılmış bir depolama nesnesidir): Maalesef

private void uploadStream(String path, String name, String contentType, InputStream stream, String bucketName) throws IOException, GeneralSecurityException { 
    InputStreamContent contentStream = new InputStreamContent(contentType, stream); 
    StorageObject objectMetadata = new StorageObject() 
       .setName(path+"/"+name) 
       .setAcl(Arrays.asList(new ObjectAccessControl().setEntity("allUsers").setRole("READER"))); 
    Storage.Objects.Insert insertRequest = gcsService.objects() 
       .insert(bucketName, objectMetadata, contentStream); 
    insertRequest.execute(); 
} 

, ben GKS yazma anlamaya geçiremedi parçaları. Google’ın belgeleri iki yaklaşım önermektedir. https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload

Diğeri yaklaşım istekleri "yaz" içerir: https://cloud.google.com/storage/docs/json_api/v1/objects/compose

Ben bir "devam ettirilebilir" yükleme kurmak almaya çalışırken, ama oldum Yapamam biri "devam ettirilebilir" Ekle istekleri kapsar işe koyul.

Herhangi bir fikrin var mı? Benim özel sorularım şunlardır:

  • GCS'ye parçalar halinde yüklemek için zarif ve/veya uygun bir yol nedir?
  • Java'daki Ekleme istekleri aracılığıyla yeniden yüklenebilen yüklemeleri nasıl GCS'ye kuracağını bilen var mı? Bu hiç yapılabilir mi?

cevap

0

Bunu işe aldım - bir güçlüktü. Kayıt için, benim soruların cevapları:

  • "devam ettirilebilir" yükleme Java çalışır ve yükleme için (Ben bir uzman değilim ve bu yüzden emin değilim) zarif ve belki de tercih yoludur GCS için parçalar halinde dosyaları.
  • A "Yeniden başlatılabilir" yükleme, aşağıda açıklandığı gibi Java'da kurulabilir.

İki yönteme sahip oldum - biri yüklemeyi başlatmak için, diğeri ise göndermek için.

private String initiateResumableUpload() throws IOException { 
     String URI = "https://storage.googleapis.com/" + bucket + "/" + path; 
     GenericUrl url = new GenericUrl(URI); 
     HttpRequest req = requestFactory.buildPostRequest(url, new ByteArrayContent("text/plain", new byte[0])); 
     HttpHeaders headers = new HttpHeaders(); 
     headers.set("x-goog-resumable", "start"); 
     headers.setContentLength((long) 0); 
     headers.setContentType("text/plain"); 
     req.setHeaders(headers); 
     req.setReadTimeout((int) DEFAULT_TIMEOUT); 
     req.setResponseHeaders(headers); 
     HttpResponse resp; 
     try { 
      resp = req.execute(); 
     } catch (IOException e) { 
      throw e; 
     } 
     if (resp.getStatusCode() == 201) { 
      String location = resp.getHeaders().getLocation(); 
      return location; 

     } else { 
      throw new IOException(); 
     } 
    } 

RequestFactory, uygun şekilde oluşturulmuş kimlik bilgilerinizi bilmelidir.

private void writeChunk(final boolean isFinalChunk) throws HttpResponseException, IOException { 
    System.out.println("Writing chunk number " + Integer.toString(chunkCount) + "."); 

    try (InputStream inputStream = new ByteBufInputStream(buffer)) { 
     int length = Math.min(buffer.readableBytes(), DEFAULT_UPLOAD_CHUNK_SIZE); 
     HttpContent contentsend = new InputStreamContent("text/plain", inputStream); 

     String URI = location; 
     GenericUrl url = new GenericUrl(URI); 
     HttpRequest req = requestFactory.buildPutRequest(url, contentsend); 

     int offset = chunkCount*DEFAULT_UPLOAD_CHUNK_SIZE; 
     long limit = offset + length; 
     HttpHeaders headers = new HttpHeaders(); 
     headers.setContentLength((long) length); 
     headers.setContentRange("bytes " + (length == 0 ? "*" : offset + "-" + (limit - 1)) + (isFinalChunk ? "/" + limit : "/*")); 

     req.setHeaders(headers); 

     req.setReadTimeout((int) DEFAULT_TIMEOUT); 

     try { 
      req.execute(); 
      } 
     catch (HttpResponseException e) { 
       if(e.getMessage().equals("308 Resume Incomplete")) 
       { 
        ++chunkCount; 
       } 
       else 
       { 
        throw e; 
       } 
      } 
     catch (Exception e) { 
      throw e; 
     } 
    } 
} 

Arabam bir io.netty.buffer.ByteBuf.

My GCS ilgili ithalat şunlardır:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; 
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; 
import com.google.api.client.http.ByteArrayContent; 
import com.google.api.client.http.GenericUrl; 
import com.google.api.client.http.HttpContent; 
import com.google.api.client.http.HttpHeaders; 
import com.google.api.client.http.HttpRequest; 
import com.google.api.client.http.HttpRequestFactory; 
import com.google.api.client.http.HttpResponse; 
import com.google.api.client.http.HttpResponseException; 
import com.google.api.client.http.HttpTransport; 

Yukarıdaki kod bazı hatalar olabilir, ama başarılı GCS için parçalar halinde bir dosya yazdım.

Ayrıca bu görevi farklı bir kitaplık ve "Yazma" istekleri aracılığıyla gerçekleştirmeyi başardım. Ancak "sürdürülebilir" yaklaşım daha uygun gözüküyor.

Şerefe ve iyi şanslar.

İlgili konular