Transmitir chamadas nas bibliotecas de cliente do Cloud para Java

As chamadas de streaming permitem padrões de interação mais complexos do que simples solicitação/resposta, permitindo que várias mensagens sejam enviadas ou recebidas em uma única conexão.

As bibliotecas de cliente do Cloud para Java oferecem suporte a três tipos de chamadas de streaming:

  • Streaming do servidor:o servidor envia um fluxo de respostas para você.
  • Streaming de cliente:você envia um fluxo de solicitações ao servidor.
  • Streaming bidirecional:é possível enviar um fluxo de solicitações ao servidor, e ele pode enviar um fluxo de respostas para você.

As implementações de streaming são modeladas de acordo com as implementações gRPC-Java para streaming de servidor, cliente e bidirecional.

Compatibilidade com streaming em vários transportes

O streaming é totalmente compatível com o gRPC, mas apenas parcialmente com HttpJson. Consulte a tabela a seguir para saber mais sobre o suporte a streaming.

Tipo de transmissão gRPC HttpJson
Streaming do servidor Com suporte Com suporte
Streaming do cliente Com suporte Incompatível
Streaming bidirecional Com suporte Incompatível

As chamadas unárias (não de streaming) são compatíveis com gRPC e HttpJson.

Como determinar o tipo de streaming

Para determinar o tipo de transmissão da chamada, verifique o tipo Callable retornado:

  • ServerStreamingCallable:streaming do servidor.
  • ClientStreamingCallable:streaming do cliente.
  • BidiStreamingCallable:streaming bidirecional.

Por exemplo, usando Java-Aiplatform e Java-Speech:

// Server Streaming
ServerStreamingCallable<ReadTensorboardBlobDataRequest, ReadTensorboardBlobDataResponse> callable = aiplatformClient.readTensorboardBlobDataCallable();

// Bidirectional Streaming
BidiStreamingCallable<StreamingRecognizeRequest, StreamingRecognizeResponse> callable = speechClient.streamingRecognizeCallable();

Como fazer chamadas de streaming

Fazer uma chamada de streaming varia dependendo se você está usando streaming do servidor ou bidirecional.

Streaming do lado do servidor

O streaming do servidor não exige implementação adicional. A classe ServerStream permite iterar o fluxo de respostas. Usando Java-Maps-Routing como exemplo, veja como chamar a API Server Streaming:

try (RoutesClient routesClient = RoutesClient.create()) {
  ServerStreamingCallable<ComputeRouteMatrixRequest, RouteMatrixElement> computeRouteMatrix =
    routesClient.computeRouteMatrixCallable();  
  ServerStream<RouteMatrixElement> stream = computeRouteMatrix.call(
    ComputeRouteMatrixRequest.newBuilder().build());
  for (RouteMatrixElement element : stream) {
    // Do something with response
  }
}

Neste exemplo, o cliente envia um único ComputeRouteMatrixRequest e recebe um fluxo de respostas.

Streaming bidirecional

O streaming bidirecional exige mais implementação para fazer a chamada. Usando o Java-Speech como exemplo, as etapas a seguir fornecem uma implementação de exemplo para fazer uma chamada de streaming bidirecional.

Primeiro, implemente a interface ResponseObserver usando o seguinte código como uma diretriz:

class BidiResponseObserver<T> implements ResponseObserver<T> {
  private final List<T> responses = new ArrayList<>();
  private final SettableApiFuture<List<T>> future = SettableApiFuture.create();

  @Override
  public void onStart(StreamController controller) {
    // no-op
  }

  @Override
  public void onResponse(T response) {
    responses.add(response);
  }

  @Override
  public void onError(Throwable t) {
    future.setException(t);
  }

  @Override
  public void onComplete() {
    future.set(responses);
  }

  public SettableApiFuture<List<T>> getFuture() {
    return future;
  }
}

Em seguida, siga estas etapas:

  1. Crie uma instância do observador:

    BidiResponseObserver<StreamingRecognizeResponse> responseObserver = new BidiResponseObserver<>();
    
  2. Transmita o observador para o elemento chamável:

    ClientStream<EchoRequest> clientStream = speechClient.streamingRecognizeCallable().splitCall(responseObserver);
    
  3. Envie as solicitações para o servidor e feche o fluxo quando terminar:

    clientStream.send(StreamingRecognizeRequest.newBuilder().build());
    clientStream.send(StreamingRecognizeRequest.newBuilder().build());
    // ... other requests ...
    clientStream.send(StreamingRecognizeRequest.newBuilder().build());
    clientStream.closeSend();
    
  4. Itere as respostas:

    List<StreamingRecognizeResponse> responses = responseObserver.getFuture().get();
    
    for (StreamingRecognizeResponse response : responses) {
      // Do something with response
    }
    

Erros de streaming não compatíveis

Para bibliotecas de cliente que oferecem suporte a transportes gRPC e HTTP/JSON, é possível configurar acidentalmente a biblioteca de cliente para invocar uma chamada de streaming não compatível. Por exemplo, a configuração a seguir mostra o cliente HttpJson do Java-Speech fazendo uma chamada de streaming bidirecional:

// SpeechClient is configured to use HttpJson
try (SpeechClient speechClient = SpeechClient.create(SpeechSettings.newHttpJsonBuilder().build())) {
  // Bidi Callable is not supported in HttpJson
  BidiStreamingCallable<StreamingRecognizeRequest, StreamingRecognizeResponse> callable = speechClient.streamingRecognizeCallable();
  ...
}

Isso não resulta em um erro de compilação, mas aparece como um erro de execução:

Not implemented: streamingRecognizeCallable(). REST transport is not implemented for this method yet.
Important: The client library MUST be configured with gRPC to use client or bidirectional streaming.