Carregamentos de API

A funcionalidade de carregamento de multimédia permite que a API BigQuery armazene dados na nuvem e os disponibilize ao servidor. Os tipos de dados que uma pessoa pode querer carregar incluem fotos, vídeos, ficheiros PDF, ficheiros ZIP ou qualquer outro tipo de dados.

Opções de carregamento

A API BigQuery permite-lhe carregar determinados tipos de dados binários ou multimédia. As características específicas dos dados que pode carregar são especificadas na página de referência de qualquer método que suporte carregamentos de multimédia:

  • Tamanho máximo do ficheiro de carregamento: a quantidade máxima de dados que pode armazenar com este método.
  • Tipos MIME de multimédia aceites: os tipos de dados binários que pode armazenar através deste método.

Pode fazer pedidos de carregamento de qualquer uma das seguintes formas. Especifique o método que está a usar com o parâmetro de pedido uploadType.

  • Carregamento multipartes: uploadType=multipart. Para uma transferência rápida de ficheiros e metadados mais pequenos; transfere o ficheiro juntamente com os metadados que o descrevem, tudo num único pedido.
  • Carregamento retomável: uploadType=resumable. Para uma transferência fiável, especialmente importante com ficheiros maiores. Com este método, usa um pedido de início de sessão que, opcionalmente, pode incluir metadados. Esta é uma boa estratégia para usar na maioria das aplicações, uma vez que também funciona para ficheiros mais pequenos ao custo de um pedido HTTP adicional por carregamento.

Quando carrega conteúdo multimédia, usa um URI especial. Na verdade, os métodos que suportam carregamentos de conteúdo multimédia têm dois pontos finais de URI:

  • O URI /upload para o conteúdo multimédia. O formato do ponto final de carregamento é o URI do recurso padrão com um prefixo "/upload". Use este URI quando transferir os próprios dados multimédia.

    Exemplo: POST /upload/bigquery/v2/projects/projectId/jobs

  • O URI do recurso padrão para os metadados. Se o recurso contiver campos de dados, esses campos são usados para armazenar metadados que descrevem o ficheiro carregado. Pode usar este URI quando criar ou atualizar valores de metadados.

    Exemplo: POST /bigquery/v2/projects/projectId/jobs

Carregamento em várias partes

Se tiver metadados que quer enviar juntamente com os dados a carregar, pode fazer um único pedido multipart/related. Esta é uma boa opção se os dados que está a enviar forem suficientemente pequenos para serem carregados novamente na totalidade se a ligação falhar.

Para usar o carregamento multipartes, faça um pedido POST ao URI /upload do método e adicione o parâmetro de consulta uploadType=multipart, por exemplo:

POST https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=multipart

Os cabeçalhos HTTP de nível superior a usar quando faz um pedido de carregamento multipartes incluem:

  • Content-Type. Defina como multipart/related e inclua a string de limite que está a usar para identificar as partes do pedido.
  • Content-Length. Definido como o número total de bytes no corpo do pedido. A parte multimédia do pedido tem de ser inferior ao tamanho máximo do ficheiro especificado para este método.

O corpo do pedido está formatado como um tipo de conteúdo multipart/related [RFC2387] e contém exatamente duas partes. As partes são identificadas por uma string de limite, e a string de limite final é seguida de dois travessões.

Cada parte do pedido de várias partes precisa de um cabeçalho Content-Type adicional:

  1. Parte dos metadados: tem de aparecer primeiro e Content-Type tem de corresponder a um dos formatos de metadados aceites.
  2. Parte multimédia: tem de aparecer em segundo lugar e Content-Type tem de corresponder a um dos tipos MIME de multimédia aceites do método.

Consulte a referência da API para ver a lista de tipos MIME de multimédia aceites e os limites de tamanho dos ficheiros carregados de cada método.

Nota: para criar ou atualizar apenas a parte dos metadados, sem carregar os dados associados, basta enviar um pedido POST ou PUT para o ponto final do recurso padrão: https://www.googleapis.com/bigquery/v2/projects/projectId/jobs

Exemplo: carregamento multipartes

O exemplo abaixo mostra um pedido de carregamento multipartes para a API BigQuery.

POST /upload/bigquery/v2/projects/projectId/jobs?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}


--foo_bar_baz
Content-Type: */*

CSV, JSON, AVRO, PARQUET, or ORC data
--foo_bar_baz--

Se o pedido for bem-sucedido, o servidor devolve o código de estado HTTP 200 OK juntamente com quaisquer metadados:

HTTP/1.1 200
Content-Type: application/json

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

Carregamento retomável

Para carregar ficheiros de dados de forma mais fiável, pode usar o protocolo de carregamento com opção de retomar o mesmo. Este protocolo permite-lhe retomar uma operação de carregamento depois de uma falha de comunicação ter interrompido o fluxo de dados. É especialmente útil se estiver a transferir ficheiros grandes e a probabilidade de uma interrupção da rede ou alguma outra falha de transmissão for elevada, por exemplo, quando carregar a partir de uma app cliente para dispositivos móveis. Também pode reduzir a utilização da largura de banda em caso de falhas de rede, uma vez que não tem de reiniciar os carregamentos de ficheiros grandes desde o início.

Os passos para usar o carregamento com opção de retomar o mesmo incluem:

  1. Inicie uma sessão retomável. Faça um pedido inicial ao URI de carregamento que inclua os metadados, se existirem.
  2. Guarde o URI da sessão retomável. Guarde o URI da sessão devolvido na resposta do pedido inicial. Vai usá-lo para os restantes pedidos nesta sessão.
  3. Carregue o ficheiro. Envie o ficheiro multimédia para o URI da sessão retomável.

Além disso, as apps que usam o carregamento com opção de retomar o mesmo têm de ter código para retomar um carregamento interrompido. Se um carregamento for interrompido, descubra a quantidade de dados que foi recebida com êxito e, em seguida, retome o carregamento a partir desse ponto.

Nota: um URI de carregamento expira após uma semana.

Passo 1: inicie uma sessão retomável

Para iniciar um carregamento retomável, faça um pedido POST ao URI /upload do método e adicione o parâmetro de consulta uploadType=resumable, por exemplo:

POST https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable

Para este pedido de iniciação, o corpo está vazio ou contém apenas os metadados. Vai transferir os conteúdos reais do ficheiro que quer carregar em pedidos subsequentes.

Use os seguintes cabeçalhos HTTP com o pedido inicial:

  • X-Upload-Content-Type. Definido como o tipo MIME de multimédia dos dados de carregamento a serem transferidos em pedidos subsequentes.
  • X-Upload-Content-Length. Definido para o número de bytes de dados de carregamento a serem transferidos em pedidos subsequentes.  Se o comprimento for desconhecido no momento deste pedido, pode omitir este cabeçalho.
  • Se fornecer metadados: Content-Type. Definido de acordo com o tipo de dados dos metadados.
  • Content-Length. Defina como o número de bytes fornecido no corpo deste pedido inicial. Não é obrigatório se estiver a usar a codificação de transferência segmentada.

Consulte a referência da API para ver a lista de tipos MIME de multimédia aceites e os limites de tamanho dos ficheiros carregados de cada método.

Exemplo: pedido de iniciação de sessão retomável

O exemplo seguinte mostra como iniciar uma sessão retomável para a API BigQuery.

POST /upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: */*
X-Upload-Content-Length: 2000000

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

Nota: para um pedido de atualização retomável inicial sem metadados, deixe o corpo do pedido vazio e defina o cabeçalho Content-Length como 0.

A secção seguinte descreve como processar a resposta.

Passo 2: guarde o URI da sessão retomável

Se o pedido de início de sessão for bem-sucedido, o servidor da API responde com um código de estado HTTP 200 OK. Além disso, fornece um cabeçalho Location que especifica o URI da sessão retomável. O cabeçalho Location, apresentado no exemplo abaixo, inclui uma parte do parâmetro de consulta upload_id que indica o ID de carregamento exclusivo a usar para esta sessão.

Exemplo: resposta de iniciação de sessão retomável

Aqui está a resposta ao pedido no passo 1:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0

O valor do cabeçalho Location, conforme mostrado na resposta de exemplo acima, é o URI da sessão que vai usar como o ponto final HTTP para fazer o carregamento real do ficheiro ou consultar o estado do carregamento.

Copie e guarde o URI da sessão para o poder usar em pedidos subsequentes.

Passo 3: carregue o ficheiro

Para carregar o ficheiro, envie um pedido PUT para o URI de carregamento que obteve no passo anterior. O formato do pedido de carregamento é:

PUT session_uri

Os cabeçalhos HTTP a usar quando fizer os pedidos de carregamento de ficheiros retomáveis incluem Content-Length. Defina este valor para o número de bytes que está a carregar nesta solicitação, que é geralmente o tamanho do ficheiro de carregamento.

Exemplo: pedido de carregamento de ficheiros retomável

Segue-se um pedido retomável para carregar o ficheiro CSV, JSON, AVRO, PARQUET ou ORC completo de 2 000 000 bytes para o exemplo atual.

PUT https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: */*

bytes 0-1999999

Se o pedido for bem-sucedido, o servidor responde com um HTTP 201 Created, juntamente com quaisquer metadados associados a este recurso. Se o pedido inicial da sessão retomável tivesse sido um PUT, para atualizar um recurso existente, a resposta de êxito seria 200 OK, juntamente com todos os metadados associados a este recurso.

Se o pedido de carregamento for interrompido ou se receber um erro HTTP 503 Service Unavailable ou qualquer outra resposta 5xx do servidor, siga o procedimento descrito em retomar um carregamento interrompido.  


Carregar o ficheiro em partes

Com os carregamentos retomáveis, pode dividir um ficheiro em partes e enviar uma série de pedidos para carregar cada parte sequencialmente. Esta não é a abordagem preferida, uma vez que existem custos de desempenho associados aos pedidos adicionais e, geralmente, não é necessária. No entanto, pode ter de usar a divisão em blocos para reduzir a quantidade de dados transferidos num único pedido. Isto é útil quando existe um limite de tempo fixo para pedidos individuais, como acontece com determinadas classes de pedidos do Google App Engine. Também lhe permite fazer coisas como fornecer indicações de progresso do carregamento para navegadores antigos que não têm suporte de progresso do carregamento por predefinição.


Retome um carregamento interrompido

Se um pedido de carregamento for terminado antes de receber uma resposta ou se receber uma resposta HTTP 503 Service Unavailable do servidor, tem de retomar o carregamento interrompido. Para o fazer:

  1. Estado do pedido. Consulte o estado atual do carregamento enviando um pedido PUT vazio para o URI de carregamento. Para este pedido, os cabeçalhos HTTP devem incluir um cabeçalho Content-Range que indique que a posição atual no ficheiro é desconhecida.  Por exemplo, defina o valor de Content-Range como */2000000 se o comprimento total do ficheiro for de 2 000 000. Se não souber o tamanho total do ficheiro, defina Content-Range como */*.

    Nota: pode pedir o estado entre blocos, não apenas se o carregamento for interrompido. Isto é útil, por exemplo, se quiser mostrar indicações de progresso do carregamento para navegadores antigos.

  2. Obtenha o número de bytes carregados. Processe a resposta da consulta de estado. O servidor usa o cabeçalho Range na respetiva resposta para especificar os bytes que recebeu até agora.  Por exemplo, um cabeçalho Range de 0-299999 indica que foram recebidos os primeiros 300 000 bytes do ficheiro.
  3. Carregue os dados restantes. Por último, agora que sabe onde retomar o pedido, envie os dados restantes ou o fragmento atual. Tenha em atenção que tem de tratar os dados restantes como um bloco separado em qualquer dos casos, pelo que tem de enviar o cabeçalho Content-Range quando retomar o carregamento.
Exemplo: retomar um carregamento interrompido

1) Pedir o estado do carregamento.

O pedido seguinte usa o cabeçalho Content-Range para indicar que a posição atual no ficheiro de 2 000 000 bytes é desconhecida.

PUT {session_uri} HTTP/1.1
Content-Length: 0
Content-Range: bytes */2000000

2) Extraia o número de bytes carregados até agora da resposta.

A resposta do servidor usa o cabeçalho Range para indicar que recebeu os primeiros 43 bytes do ficheiro até agora. Use o valor superior do cabeçalho Range para determinar onde iniciar o carregamento retomado.

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42

Nota: é possível que a resposta de estado seja 201 Created ou 200 OK se o carregamento estiver concluído. Isto pode acontecer se a ligação for interrompida depois de todos os bytes terem sido carregados, mas antes de o cliente receber uma resposta do servidor.

3) Retome o carregamento a partir do ponto em que ficou.

O pedido seguinte retoma o carregamento enviando os bytes restantes do ficheiro, começando no byte 43.

PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

Práticas recomendadas

Ao carregar conteúdo multimédia, é útil conhecer algumas práticas recomendadas relacionadas com o processamento de erros.

  • Retome ou tente novamente os carregamentos que falham devido a interrupções de ligação ou a erros 5xx, incluindo:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Use uma estratégia de retirada exponencial se for devolvido algum erro do servidor 5xx ao retomar ou tentar novamente os pedidos de carregamento. Estes erros podem ocorrer se um servidor estiver sobrecarregado. A retirada exponencial pode ajudar a aliviar este tipo de problemas durante períodos de elevado volume de pedidos ou tráfego de rede intenso.
  • Outros tipos de pedidos não devem ser processados pela retirada exponencial, mas ainda pode tentar novamente alguns deles. Ao tentar novamente estes pedidos, limite o número de vezes que os tenta novamente. Por exemplo, o seu código pode limitar a dez novas tentativas ou menos antes de comunicar um erro.
  • Resolva os erros 404 Not Found e 410 Gone quando fizer carregamentos retomáveis, reiniciando todo o carregamento desde o início.

Retirada exponencial

A retirada exponencial é uma estratégia de processamento de erros padrão para aplicações de rede em que o cliente repete periodicamente um pedido falhado durante um período de tempo cada vez maior. Se um volume elevado de pedidos ou um tráfego de rede intenso fizer com que o servidor devolva erros, a retirada exponencial pode ser uma boa estratégia para processar esses erros. Por outro lado, não é uma estratégia relevante para lidar com erros não relacionados com o volume da rede ou os tempos de resposta, como credenciais de autorização inválidas ou erros de ficheiro não encontrado.

Quando usada corretamente, a retirada exponencial aumenta a eficiência da utilização da largura de banda, reduz o número de pedidos necessários para obter uma resposta bem-sucedida e maximiza o débito de pedidos em ambientes concorrentes.

O fluxo para implementar a retirada exponencial simples é o seguinte:

  1. Fazer um pedido à API.
  2. Receber uma resposta HTTP 503, que indica que deve tentar novamente o pedido.
  3. Aguarde 1 segundo + random_number_milliseconds e repita o pedido.
  4. Receber uma resposta HTTP 503, que indica que deve tentar novamente o pedido.
  5. Aguarde 2 segundos + random_number_milliseconds e repita o pedido.
  6. Receber uma resposta HTTP 503, que indica que deve tentar novamente o pedido.
  7. Aguarde 4 segundos + random_number_milliseconds e repita o pedido.
  8. Receber uma resposta HTTP 503, que indica que deve tentar novamente o pedido.
  9. Aguarde 8 segundos + random_number_milliseconds e repita o pedido.
  10. Receber uma resposta HTTP 503, que indica que deve tentar novamente o pedido.
  11. Aguarde 16 segundos + random_number_milliseconds e repita o pedido.
  12. Para. Comunique ou registe um erro.

No fluxo acima, random_number_milliseconds é um número aleatório de milissegundos inferior ou igual a 1000. Isto é necessário, uma vez que a introdução de um pequeno atraso aleatório ajuda a distribuir a carga de forma mais uniforme e evita a possibilidade de sobrecarregar o servidor. O valor de random_number_milliseconds tem de ser redefinido após cada espera.

Nota: a espera é sempre (2 ^ n) + random_number_milliseconds, em que n é um número inteiro monotonicamente crescente definido inicialmente como 0. O número inteiro n é incrementado em 1 para cada iteração (cada pedido).

O algoritmo está definido para terminar quando n for 5. Este limite máximo impede que os clientes tentem novamente infinitamente e resulta num atraso total de cerca de 32 segundos antes de um pedido ser considerado "um erro irrecuperável". Um número máximo de tentativas maior não é um problema, especialmente se estiver em curso um carregamento longo. Certifique-se apenas de que limita o atraso das tentativas a algo razoável, por exemplo, menos de um minuto.

Guias da biblioteca de cliente da API