webentwicklung-frage-antwort-db.com.de

Muster für eine umfangreiche Fehlerbehandlung in gRPC

Wie lautet das Muster für das Senden weiterer Details zu Fehlern an den Client mithilfe von gRPC?

Angenommen, ich habe ein Formular zum Registrieren eines Benutzers, der eine Nachricht sendet

message RegisterUser {
  string email = 1;
  string password = 2;
}

dabei muss die E-Mail korrekt formatiert und eindeutig sein und das Kennwort muss mindestens 8 Zeichen lang sein.

Wenn ich eine JSON-API schreibe, würde ich einen 400-Fehler mit dem folgenden Text zurückgeben:

{
  "errors": [{
    "field": "email",
    "message": "Email does not have proper format."
   }, {
     "field": "password",
     "message": "Password must be at least 8 characters."
   }],
}

und der Client könnte dem Benutzer nette Fehlermeldungen bereitstellen (d. h. indem er das Passwortfeld hervorhebt und dem Benutzer ausdrücklich mitteilt, dass mit seiner Eingabe etwas nicht stimmt).

Gibt es eine Möglichkeit, mit gRPC etwas Ähnliches zu tun? Es scheint, dass in den meisten Client-Sprachen ein Fehler dazu führt, dass eine Ausnahme ausgelöst wird, ohne dass die Antwort abgefangen werden kann.

Zum Beispiel möchte ich etwas wie

message ValidationError {
  string field = 1;
  string message = 2;
}

message RegisterUserResponse {
  repeated ValidationError validation_errors = 1;
  ...
}

o.ä.

17
mindvirus

Fügen Sie zusätzliche Fehlerdetails in die Antwortmetadaten ein. Stellen Sie jedoch sicher, dass Sie einen nützlichen Statuscode und eine Meldung bereitstellen. In diesem Fall können Sie RegisterUserResponse zu den Metadaten hinzufügen.

In gRPC Java würde das so aussehen:

Metadata.Key<RegisterUserResponse> REGISTER_USER_RESPONSE_KEY =
    ProtoUtils.keyForProto(RegisterUserResponse.getDefaultInstance());
...
Metadata metadata = new Metadata();
metadata.put(REGISTER_USER_RESPONSE_KEY, registerUserResponse);
responseObserver.onError(
    Status.INVALID_ARGUMENT.withDescription("Email or password malformed")
      .asRuntimeException(metadata));

Eine andere Möglichkeit ist die Verwendung von google.rpc.Status proto das ein zusätzliches Any für details enthält. Jede Sprache wird unterstützt, um den Typ zu verarbeiten. In Java würde es so aussehen:

// This is com.google.rpc.Status, not io.grpc.Status
Status status = Status.newBuilder()
    .setCode(Code.INVALID_ARGUMENT.getNumber())
    .setMessage("Email or password malformed")
    .addDetails(Any.pack(registerUserResponse))
    .build();
responseObserver.onError(StatusProto.toStatusRuntimeException(status));

google.rpc.Status ist in einigen Sprachen sauberer, da die Fehlerdetails als eine Einheit weitergegeben werden können. Es wird auch klargestellt, welche Teile der Antwort fehlerbedingt sind. On-the-Wire verwendet es weiterhin Metadaten, um die zusätzlichen Informationen weiterzuleiten.

Sie könnten auch interessiert sein an error_details.proto , die einige häufige Arten von Fehlern enthält.

Ich diskutierte dieses Thema während der CloudNativeCon. Sie können die Folien und verknüpften Aufzeichnungen auf YouTube ansehen.

25
Eric Anderson