L’une des décisions techniques les plus cruciales lors de la conception de l’API consiste à choisir le protocole approprié pour l’échange de données. Ce n’est pas une tâche facile. Vous devez répondre à au moins quelques questions importantes – qui s’intégreront à l’API, si vous avez des limitations de réseau, quelle est la quantité et la fréquence des appels, et le niveau de maturité technologique de votre organisation vous permettra-t-il de le maintenir à l’avenir ?

Lorsque vous rassemblez toutes les informations, vous pouvez comparer différentes technologies pour choisir celle qui vous convient le mieux. Vous pouvez choisir entre SOAP, REST ou GraphQL bien connus. Mais dans cet article, nous aimerions vous présenter un tout nouvel acteur dans le monde des microservices : gRPC Remote Procedure Call.

Qu’est-ce que gRPC (Remote Procedure Call) ?

gRPC est un framework open-source d’appel de procédure à distance (RPC) multiplateforme initialement créé par Google. La plate-forme utilise Protocol Buffers comme protocole de sérialisation des données, car le format binaire nécessite moins de ressources et les messages sont plus petits. De plus, un contrat entre le client et le serveur est défini dans proto format, afin que le code puisse être généré automatiquement. Le framework s’appuie sur HTTP/2 (prend en charge TLS) et au-delà des performances, de l’interopérabilité et de la génération de code, offre des fonctionnalités et des canaux de streaming.

Déclarer les méthodes dans le contrat

Avez-vous lu notre article sur sérialisation des données avec Protocol Buffers? Nous allons y ajouter quelques définitions supplémentaires :

message SearchRequest 
  string vin = 1;
  google.protobuf.Timestamp from = 2;
  google.protobuf.Timestamp to = 3;


message SearchResponse 
  repeated Geolocation geolocations = 1;


service GeolocationServer 
  rpc Insert(Geolocation) returns (google.protobuf.Empty);
  rpc Search(SearchRequest) returns (SearchResponse);

La structure du fichier est assez simple, mais il y a quelques points à noter :

  • service GeolocationServer – le service est déclaré par mot-clé avec ce nom
  • rpc Insert(Geolocation) – les méthodes sont définies par rpc mot-clé, son nom et le type de paramètre de requête
  • returns (google.protobuf.Empty) – et à la fin enfin un type de retour. Comme vous pouvez le voir, vous devez toujours renvoyer n’importe quelle valeur, dans ce cas, est un wrapper pour une structure vide
  • message SearchResponse repeated Geolocation geolocations = 1; – si vous voulez retourner une liste d’objets, vous devez les marquer comme repeated et donner un nom au champ

Construire la configuration

Nous pouvons combiner les fonctionnalités de Spring Boot et simplifier la configuration du serveur gRPC en utilisant la bibliothèque dédiée GitHub – yidongnan/grpc-spring-boot-starter : module de démarrage Spring Boot pour le framework gRPC. (suivez le guide d’installation ici).

Cela nous a permis d’utiliser toutes les qualités du framework Spring (comme Dependency Injection ou Annotations).

Vous êtes maintenant prêt à générer du code Java ! ./gradlew generateProto

Implémentation du serveur

Pour implémenter le serveur pour la définition de nos méthodes, nous devons tout d’abord étendre la classe abstraite appropriée, qui a été générée à l’étape précédente :

public class GeolocationServer extends GeolocationServerGrpc.GeolocationServerImplBase

À l’étape suivante, ajoutez le @GrpcService annotation au niveau de la classe pour enregistrer le serveur gRPC et remplacer les méthodes du serveur :

@Override
public void insert(Geolocation request, StreamObserver<Empty> responseObserver) 
    GeolocationEvent geolocationEvent = convertToGeolocationEvent(request);
    geolocationRepository.save(geolocationEvent);

    responseObserver.onNext(Empty.newBuilder().build());
    responseObserver.onCompleted();


@Override
public void search(SearchRequest request, StreamObserver<SearchResponse> responseObserver) 
    List<GeolocationEvent> geolocationEvents = geolocationRepository.searchByVinAndOccurredOnFromTo(
        request.getVin(),
        convertTimestampToInstant(request.getFrom()),
        convertTimestampToInstant(request.getTo())
    );

    List<Geolocation> geolocations = geolocationEvents.stream().map(this::convertToGeolocation).toList();

    responseObserver.onNext(SearchResponse.newBuilder()
        .addAllGeolocations(geolocations)
        .build()
    );
    responseObserver.onCompleted();

  • StreamObserver<> responseObserver – flux de messages à envoyer
  • responseObserver.onNext() – écrit les réponses au client. Les appels unaires doivent invoquer surSuivant au plus une fois
  • responseObserver.onCompleted() – reçoit une notification d’achèvement réussi du flux

Nous devons convertir les objets gRPC internes en entités de notre domaine :

private GeolocationEvent convertToGeolocationEvent(Geolocation request) 
    Instant occurredOn = convertTimestampToInstant(request.getOccurredOn());
    return new GeolocationEvent(
        request.getVin(),
        occurredOn,
        request.getSpeed().getValue(),
        new Coordinates(request.getCoordinates().getLatitude(), request.getCoordinates().getLongitude())
    );


private Instant convertTimestampToInstant(Timestamp timestamp) 
    return Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos());

La gestion des erreurs

Aucun client ne nous envoie toujours un message valide et notre système n’est pas suffisamment résilient pour gérer toutes les erreurs, nous devons donc fournir des moyens de gérer les exceptions.

Si une erreur se produit, gRPC renvoie à la place l’un de ses codes d’état d’erreur, avec une description facultative.

Nous pouvons le gérer facilement à la manière de Spring, en utilisant les annotations déjà disponibles dans la bibliothèque :

@GrpcAdvice
public class GrpcExceptionAdvice 

    @GrpcExceptionHandler
    public Status handleInvalidArgument(IllegalArgumentException e) 
        return Status.INVALID_ARGUMENT.withDescription(e.getMessage()).withCause(e);
    

  • @GrpcAdvice – marque la classe comme un conteneur pour des gestionnaires d’exceptions spécifiques
  • @GrpcExceptionHandler – méthode à invoquer lorsqu’une exception spécifiée comme argument est levée

Maintenant, nous nous sommes assurés que nos messages d’erreur sont clairs et significatifs pour les clients.

gRPC – est-ce la bonne option pour vous ?

Comme démontré dans cet article, gRPC s’intègre bien à Spring Boot, donc si vous le connaissez bien, la courbe d’apprentissage est fluide.

gRPC est une option intéressante à considérer lorsque vous travaillez avec des systèmes distribués à faible latence et hautement évolutifs. Il fournit un protocole précis, efficace et indépendant de la langue.

Consultez la documentation officielle pour plus de connaissances ! gRPC

Leave a Reply