2016-05-30 2 views
1

У меня есть простой клиент КПГР следующим образом:КПГР клиент onNext не терпит неудачу, если нет сервера

/** 
    * Client that calls gRPC. 
    */ 
    public class Client { 

    private static final Context.Key<String> URI_CONTEXT_KEY = 
     Context.key(Constants.URI_HEADER_KEY); 

    private final ManagedChannel channel; 
    private final DoloresRPCStub asyncStub; 

    /** 
    * Construct client for accessing gRPC server at {@code host:port}. 
    * @param host 
    * @param port 
    */ 
    public Client(String host, int port) { 
    this(ManagedChannelBuilder.forAddress(host, port).usePlaintext(true)); 
    } 

    /** 
    * Construct client for accessing gRPC server using the existing channel. 
    * @param channelBuilder {@link ManagedChannelBuilder} instance 
    */ 
    public Client(ManagedChannelBuilder<?> channelBuilder) { 
    channel = channelBuilder.build(); 
    asyncStub = DoloresRPCGrpc.newStub(channel); 
    } 

    /** 
    * Closes the client 
    * @throws InterruptedException 
    */ 
    public void shutdown() throws InterruptedException { 
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); 
    } 

    /** 
    * Main async method for communication between client and server 
    * @param responseObserver user's {@link StreamObserver} implementation to handle 
    *  responses received from the server. 
    * @return {@link StreamObserver} instance to provide requests into 
    */ 
    public StreamObserver<Request> downloading(StreamObserver<Response> responseObserver) { 
    return asyncStub.downloading(responseObserver); 
    } 

    public static void main(String[] args) { 
    Client cl = new Client("localhost", 8999); // fail?? 
    StreamObserver<Request> requester = cl.downloading(new StreamObserver<Response>() { 
     @Override 
     public void onNext(Response value) { 
     System.out.println("On Next"); 
     } 
     @Override 
     public void onError(Throwable t) { 
     System.out.println("Error"); 
     } 
     @Override 
     public void onCompleted() { 
     System.out.println("Completed"); 
     } 
    }); // fail ?? 
    System.out.println("Start"); 
    requester.onNext(Request.newBuilder().setUrl("http://my-url").build()); // fail? 
    requester.onNext(Request.newBuilder().setUrl("http://my-url").build()); 
    requester.onNext(Request.newBuilder().setUrl("http://my-url").build()); 
    requester.onNext(Request.newBuilder().setUrl("http://my-url").build()); 
    System.out.println("Finish"); 
    } 
} 

Я не запустить любой сервер и запустить метод main. Я предположил бы, что программа не будет работать на:

  • создание клиента
  • client.downloading вызов
  • или observer.onNext

но удивительно (для меня), код выполняется успешно, только сообщения потерялись. Выход: Start Finish Error Из-за асинхронной природы финиш можно вызвать еще до того, как ошибка будет распространена, по крайней мере, через наблюдателя ответа. Это желаемое поведение? Я не могу потерять никаких сообщений. Я что-то упускаю?

Спасибо, Адам

ответ

1

Это предполагаемое поведение. Как вы уже упоминали, API является асинхронным, поэтому ошибки обычно должны быть асинхронными. gRPC не гарантирует доставку сообщений, а в случае сбоя RPC потоковой передачи не указывает, какие сообщения были получены удаленной стороной. Расширенный API ClientCall calls this out.

Если вам нужны более надежные гарантии, он должен быть добавлен на уровне приложения, например, с ответами или с статусом OK. Например, в gRPC + Image Upload я упоминаю использование двунаправленного потока для подтверждений.

Создание ManagedChannelBuilder не является ошибкой, потому что канал ленив: при необходимости он создает TCP-соединение (и снова подключается). Кроме того, поскольку большинство отказов являются временными, мы не хотели бы предотвращать все будущие RPC на канале только потому, что ваш клиент начал работу, когда сеть была сломана.

Поскольку API уже асинхронен, grpc-java может целенаправленно отбрасывать сообщения при отправке, даже когда он знает, что произошла ошибка (т. Е. Он не выбрасывает). Таким образом, почти все ошибки доставляются в приложение через onError().

Смежные вопросы