2016-09-30 24 views
6

W gRPC, jak dodać globalny przechwytywacz wyjątków, który przechwytuje wszystkie RuntimeException i propaguje istotne informacje dla klienta?Jak dodać globalnego przechwytywacza wyjątków w serwerze gRPC?

na przykład metoda divide może rzucić ArithmeticException z komunikatem / by zero. Na stronie serwera, mogę napisać:

@Override 
public void divide(DivideRequest request, StreamObserver<DivideResponse> responseObserver) { 
    int dom = request.getDenominator(); 
    int num = request.getNumerator(); 

    double result = num/dom; 
    responseObserver.onNext(DivideResponse.newBuilder().setValue(result).build()); 
    responseObserver.onCompleted(); 
} 

Jeśli klient przechodzi mianownik = 0, to otrzymamy:

Exception in thread "main" io.grpc.StatusRuntimeException: UNKNOWN 

a serwerem wyjścia

Exception while executing runnable io.grpc.in[email protected]62e95ade 
java.lang.ArithmeticException:/by zero 

Klient robi” wiem, co się dzieje.

Jeśli chcę przekazać / by zero wiadomość do klienta, muszę zmodyfikować serwer: (jak opisano w tym question)

try { 
    double result = num/dom; 
    responseObserver.onNext(DivideResponse.newBuilder().setValue(result).build()); 
    responseObserver.onCompleted(); 
    } catch (Exception e) { 
    logger.error("onError : {}" , e.getMessage()); 
    responseObserver.onError(new StatusRuntimeException(Status.INTERNAL.withDescription(e.getMessage()))); 
    } 

A jeśli klient wysyła mianownik = 0, to otrzymamy:

Exception in thread "main" io.grpc.StatusRuntimeException: INTERNAL:/by zero 

Dobra, / by zero jest przekazywana do klienta.

Ale problem polega na tym, że w prawdziwie korporacyjnym środowisku będzie dużo RuntimeException s, i jeśli chcę przekazać wiadomości tego wyjątku do klienta, będę musiał spróbować złapać każdą metodę, która jest bardzo uciążliwa.

Czy istnieje jakiś globalny przechwytywacz, który przechwytuje każdą metodę, przechwytując RuntimeException i wyzwala onError i propaguje komunikat o błędzie do klienta? Tak, że nie mam do czynienia z RuntimeException s w moim kodzie serwera.

Wielkie dzięki!

Uwaga:

<grpc.version>1.0.1</grpc.version> 
com.google.protobuf:proton:3.1.0 
io.grpc:protoc-gen-grpc-java:1.0.1 

Odpowiedz

0
public class GrpcExceptionHandler implements ServerInterceptor { 

private final Logger logger = LoggerFactory.getLogger (GrpcExceptionHandler.class); 

@Override 
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall (ServerCall<ReqT, RespT> call, 
                   Metadata headers, 
                   ServerCallHandler<ReqT, RespT> next) { 
    logger.info ("GRPC call at: {}", Instant.now()); 
    ServerCall.Listener<ReqT> listener; 

    try { 
     listener = next.startCall (call, headers); 
    } catch (Throwable ex) { 
     logger.error ("Uncaught exception from grpc service"); 
     call.close (Status.INTERNAL 
       .withCause (ex) 
       .withDescription ("Uncaught exception from grpc service"), null); 
     return new ServerCall.Listener<ReqT>() {}; 
    } 

    return listener; 
} 

}

próbki przechwytujący powyżej.

Oczywiście trzeba go najpierw załadować, zanim się czegoś spodzieje;

serverBuilder.addService (ServerInterceptors.intercept (bindableService, interceptor)); 

UPDATE

public interface ServerCallHandler<RequestT, ResponseT> { 
    /** 
    * Produce a non-{@code null} listener for the incoming call. Implementations are free to call 
    * methods on {@code call} before this method has returned. 
    * 
    * <p>If the implementation throws an exception, {@code call} will be closed with an error. 
    * Implementations must not throw an exception if they started processing that may use {@code 
    * call} on another thread. 
    * 
    * @param call object for responding to the remote client. 
    * @return listener for processing incoming request messages for {@code call} 
    */ 
    ServerCall.Listener<RequestT> startCall(
     ServerCall<RequestT, ResponseT> call, 
     Metadata headers); 
} 

Niestety, inny kontekst wątek oznacza brak możliwości obsługi wyjątku, więc moja odpowiedź nie jest rozwiązaniem szukasz ..

+0

Niestety, to nie działa. Wiersz 'logger.error (" Uncaught exception from grpc service ");' nie został osiągnięty! Też jestem dziwny. – smallufo

+0

Czy mógłbyś podzielić się swoim kodem? – Gladmir

+0

kod tutaj, FYI: http://pastebin.com/a96suWB1 – smallufo

0

Czytałeś java grpc examples dla przechwytywacza?

Tak więc w moim przypadku używamy standardowego kodu i wiadomości, aby określić rodzaj błędu, jaki serwer wysłał na klienta.

Przykłady: serwer wysyła odpowiedź jak

{ 
    code: 409, 
    message: 'Id xxx aldready exist' 
} 

Więc klienta można przechwytujących klient konfiguracji dla uzyskania tego kodu i odpowiedzi z refleksji. Fyi używamy serwera Lognet Spring Boot starter for grpc i rozruchu Spring dla klienta.

Powiązane problemy