gRPC contre REST : Comparaison des approches pour la création d’API

Dans le texte d’aujourd’hui, je veux examiner de plus près gRPC et REST, probablement deux des approches les plus couramment utilisées pour créer des API de nos jours.

I will start with a short characteristic of both tools — what they are and what they can offer. Then I will compare them according to seven categories, in my opinion, most crucial for modern-day systems.

Les catégories sont les suivantes:

  1. Protocoles HTTP sous-jacents
  2. Formats de données pris en charge
  3. Taille des données
  4. Débit
  5. Définitions
  6. Facilité d’adoption
  7. Support des outils

Le Pourquoi

Quand les gens entendent « API », ils pensent probablement immédiatement à une API REST. Cependant, REST est l’une des nombreuses approches pour créer des API. Ce n’est pas la solution miracle pour tous les cas d’utilisation. Il existe d’autres moyens, avec le RPC (Appel de Procédure Distante) en étant juste un, et gRPC est probablement le cadre le plus réussi pour travailler avec le RPC.

Malgré être une technologie assez mature et efficace, gRPC est toujours considéré comme le nouveau venu. Par conséquent, il est moins largement adopté que REST, malgré être assez pratique dans certains cas d’utilisation.

Ma principale raison d’écrire cet article de blog est de populariser gRPC et de souligner les cas d’utilisation où il peut briller.

Qu’est-ce que REST?

REST, ou Representational State Transfer, est probablement la manière la plus courante de créer une application qui expose n’importe quel type d’API. Il utilise HTTP comme médium de communication sous-jacent. En raison de cela, il peut bénéficier de tous les avantages d’HTTP, comme le cache.

De plus, étant stateless par conception, REST permet une séparation facile entre client et serveur. Le client n’a besoin de connaître que l’interface exposée par le serveur pour communiquer efficacement avec lui et ne dépend en aucune manière de la mise en œuvre du serveur. La communication entre client et serveur est basée sur une base de demande et de réponse, chaque demande étant une demande HTTP classique.

REST n’est pas un protocole ni un outil (dans une certaine mesure) : c’est une approche architecturale pour la construction d’applications. Les services qui suivent l’approche REST sont appelés services RESTFul. En tant qu’architecture, elle impose plusieurs contraintes à ses utilisateurs. En particulier:

  • Communication client-serveur
  • Communication sans état
  • Mise en cache
  • Interface uniforme
  • Système en couches
  • Code à la demande

Les deux concepts clés de REST sont:

  1. Points de terminaison: Une URL unique (Uniform Resource Locator) représentant un ressource spécifique; peut être considéré comme un moyen d’accéder à une opération ou élément de données particulier sur Internet
  2. Ressource: Un morceau particulier de données disponible sous une URL spécifique

De plus, il existe une description appelée le modèle de maturation de Richardson — un modèle décrivant le degré de « professionnalisme » dans les API REST. Il divise les API REST en 3 niveaux (ou 4, selon si vous comptez le niveau 0) en fonction du set de traits qu’une API particulière possède.

Un tel trait est que le point de terminaison REST doit utiliser des noms communs dans l’URL et les méthodes HTTP correctes pour gérer ses ressources.

  • Exemple: DELETE user/1 au lieu de GET user/deleteById/1

En ce qui concerne les méthodes HTTP et leurs actions associées, cela se passe comme suit:

  • GET — Récupérer une ressource spécifique ou un ensemble de ressources
  • POST — Créer une nouvelle ressource
  • PUT — Insérer ou remplacer une ressource entière
  • PATCH — Mettre à jour partiellement une ressource spécifique
  • DELETE — Supprimer une ressource spécifique par son identifiant

Le modèle de maturité spécifie bien plus que cela; par exemple, un concept appelé HyperMedia. HyperMedia relie la présentation des données et le contrôle des actions que les clients peuvent effectuer.

A full description of the maturity model is out of the scope of this blog — you can read more about it here.

Avertissement : de nombreuses choses mentionnées dans ce paragraphe sont plus nuancées que décrites ici. REST est un sujet assez vaste et mérite une série entière d’articles. Néanmoins, tout est ici conforme aux meilleures pratiques REST communément connues.

Qu’est-ce que gRPC?

Il s’agit encore d’une mise en œuvre du concept relativement ancien de Remote Procedure Call. Des personnes de Google l’ont construit — c’est pourquoi il contient un « g » dans son nom. Il est probablement l’outil le plus moderne et efficace pour travailler avec les RPC et également un projet incubation CNCF.

gRPC utilise les Protocol Buffers de Google comme format de sérialisation tout en utilisant HTTP/2 comme support de transport des données, bien que gRPC puisse également fonctionner avec JSON en tant que couche de données.

Les éléments de base de gRPC comprennent :

  • Méthode : L’élément de base de gRPC, chaque méthode est un appel de procédure distante qui prend une certaine entrée et retourne une sortie. Elle effectue une seule opération mise en œuvre plus loin dans le langage de programmation choisi. Pour l’instant, gRPC prend en charge 4 types de méthodes :
  1. Unitaire : Modèle classique de requête-réponse où la méthode prend une entrée et retourne une sortie
  2. Serveur en flux : Les méthodes acceptent un message en entrée tout en retournant le flux de messages en sortie. gRPC garantit l’ordre des messages au sein d’un appel RPC individuel.
  3. Client en flux : La méthode prend le flux de messages en entrée, les traite jusqu’à ce qu’il n’y ait plus de messages, puis retourne un seul message en sortie. De même qu’au-dessus, gRPC garantit l’ordre des messages au sein d’un appel RPC individuel.
  4. Streaming bidirectionnel: La méthode prend le flux en entrée et retourne le flux en sortie, utilisant efficacement deux flux de lecture et d’écriture. Les deux flux fonctionnent de manière indépendante et l’ordre des messages est préservé au niveau du flux.
  • Service: Représente un groupe de méthodes — chaque méthode doit avoir un nom unique au sein du service. Les services décrivent également des fonctionnalités comme la sécurité, les délais d’attente, ou les nouvelles tentatives.
  • Message: Un objet qui représente l’entrée ou la sortie des méthodes.

Les définitions de l’API gRPC sont écrites sous forme de fichiers .proto qui contiennent les trois éléments de base mentionnés ci-dessus. De plus, gRPC fournit un compilateur de protocole de buffer qui génère le code client et service à partir de nos fichiers .proto.

Nous pouvons implémenter les méthodes côté serveur comme nous le souhaitons. Nous devons respecter le contrat entrée-sortie de l’API.

Côté client, il existe un objet appelé client (ou stub) — semblable à un client HTTP. Il connaît toutes les méthodes du serveur et gère simplement l’appel de procédures distantes et le retour de leurs réponses.

La comparaison

Protocole HTTP sous-jacent

Ceci est la première catégorie et probablement la plus importante, car son influence peut également être visible dans les autres.

En général, REST est basé sur la requête-réponse et utilise HTTP/1.1 comme support de transport. Nous devons utiliser un protocole différent comme WebSocket (plus d’informations à ce sujet ici) ou tout type de streaming ou de connexion plus durable.

Nous pouvons également mettre en place un code de contournement pour donner l’impression que REST fonctionne en streaming. De plus, l’utilisation d’HTTP/1.1 pour REST nécessite une connexion par échange requête-réponse. Une telle approche peut poser problème pour les requêtes longues ou lorsque nous avons des capacités réseau limitées.

Bien sûr, nous pouvons utiliser HTTP/2 pour créer des API similaires à REST; cependant, tous les serveurs et bibliothèques ne prennent pas encore en charge HTTP/2. Par conséquent, des problèmes peuvent survenir ailleurs.

En revanche, gRPC utilise uniquement HTTP/2. Il permet d’envoyer plusieurs paires requête-réponse à travers une seule connexion TCP. Une telle approche peut être un gain de performance significatif pour notre application.

  • Résultat: Léger avantage pour gRPC

Formats de données pris en charge

En supposant le cas par défaut où l’API REST utilise HTTP/1.1, elle peut prendre en charge de nombreux formats.

REST ne soumet généralement aucune restriction concernant le format et le style des messages. Essentiellement, tout format pouvant être sérialisé en texte ordinaire est valide. Nous pouvons utiliser n’importe quel format qui nous convient le mieux dans un scénario particulier.

Le format le plus populaire pour l’envoi de données dans les applications REST est certainement JSON. XML vient en deuxième place en raison du grand nombre d’applications plus anciennes/héritées.

Cependant, lors de l’utilisation de REST avec HTTP/2, seuls les formats d’échange binaires sont pris en charge. Dans ce cas, nous pouvons utiliser Protobuf ou Avro. Bien sûr, une telle approche peut présenter des inconvénients, mais nous en reparlerons dans les points suivants.

En attendant, gRPC ne prend en charge que deux formats pour l’échange de données:

  1. Protobuf — Par défaut
  2. JSON — Lorsque vous avez besoin d’intégrer avec une API plus ancienne

Si vous choisissez d’essayer avec JSON, alors gRPC utilisera JSON comme format de codage pour les messages et GSON comme format de message. De plus, l’utilisation de JSON nécessitera la réalisation de certaines configurations supplémentaires. Voici la documentation gRPC sur la façon de procéder.

  • Résultat: Victoire pour REST, car il prend en charge plus de formats.

Taille des données

Par défaut, gRPC utilise un format d’échange de données binaires, ce qui RÉDUISE considérablement la taille des messages échangés sur le réseau : recherche indique environ 40–50% de taille inférieure en octets — mon expérience d’un des projets précédents indique même 50–70% de moins.

L’article ci-dessus fournit une comparaison de taille relativement approfondie entre JSON et Protobuff. L’auteur a également fourni un outil pour générer des JSON et des fichiers binaires. Ainsi, vous pouvez réexécuter ses expériences et comparer les résultats.

Les objets de l’article sont assez simples. Néanmoins, la règle générale est — plus il y a d’objets imbriqués et plus la structure de JSON est complexe, plus il sera lourd par rapport à Protobuf. Une différence de 50% en taille en faveur de Protobuf est une bonne base de référence.

La différence peut être minimisée ou éliminée en utilisant le format d’échange binaire pour REST. Cependant, ce n’est ni la manière la plus courante ni la mieux prise en charge pour faire des API RESTful, il peut donc y avoir d’autres problèmes.

  • Résultat: Par défaut, victoire pour gRPC; dans le cas où les deux utilisent un format de données binaires, match nul.

Débit

Encore une fois, dans le cas de REST, tout dépend du protocole HTTP sous-jacent et du serveur.

Par défaut, REST basé sur HTTP/1.1, même le serveur le plus performant ne pourra pas battre les performances de gRPC, surtout lorsque nous ajoutons l’overhead de sérialisation et de désérialisation lors de l’utilisation de JSON. Bien que lorsque nous passons à HTTP/2, la différence semble diminuer.

En ce qui concerne le débit maximal, dans les deux cas, HTTP est un médium de transport, il a donc le potentiel de s’échelonner à l’infini. Ainsi, tout dépend des outils que nous utilisons et de ce que nous faisons exactement avec notre application, car il n’y a pas de limites par conception.

  • Résultat: Par défaut, gRPC; dans le cas où les deux utilisent des données binaires et HTTP/2, match nul ou légère victoire pour gRPC.

Définitions

Dans cette partie, je vais décrire comment nous définissons nos messages et notre service dans les deux approches.

Dans la plupart des applications REST, nous déclarons simplement nos requêtes et réponses en tant que classes, objets, ou toute autre structure prise en charge par un langage particulier. Ensuite, nous nous reposons sur les bibliothèques fournies pour la sérialisation et la désérialisation de JSON/XML/YAML, ou de quelque format que nous ayons besoin.

De plus, des efforts en cours existent pour créer des outils capables de générer du code dans le langage de programmation de choix en fonction des définitions d’API REST à partir de Swagger. Cependant, ils semblent être en version alpha, donc il peut encore y avoir des bugs et des problèmes mineurs qui les rendront difficiles à utiliser.

Il n’y a que peu de différence entre les formats binaires et non binaires pour les applications REST, car la règle est plus ou moins la même dans les deux cas. Pour le format binaire, nous définissons simplement tout de la manière requise par un format particulier.

De plus, nous avons défini notre service REST via des méthodes ou des annotations de notre bibliothèque ou framework sous-jacent. L’outil est également responsable de l’exposer avec d’autres configurations au monde extérieur.

Dans le cas de gRPC, nous avons Protobuf par défaut et de facto la seule façon d’écrire des définitions. Nous devons déclarer tout : messages, services et méthodes dans des fichiers .proto, donc la question est assez simple.

Ensuite, nous utilisons l’outil fourni par gRPC pour générer du code pour nous, et nous n’avons qu’à mettre en œuvre nos méthodes. Après cela, tout devrait fonctionner comme prévu.

De plus, Protobuf prend en charge l’importation, nous pouvons donc répartir notre configuration sur plusieurs fichiers d’une manière assez simple.

  • Résultat: Pas de gagnant ici, juste une description et un conseil de ma part : choisissez l’approche qui vous convient le plus.

Facilité d’adoption

Dans cette partie, je comparerai le soutien de la bibliothèque/framework pour chaque approche dans les langages de programmation modernes.

En général, chaque langage de programmation (Java, Scala, Python) que j’ai rencontré dans ma courte carrière en tant qu’ingénieur logiciel dispose d’au moins 3 grandes bibliothèques/frameworks pour créer des applications de type REST, sans parler d’un nombre similaire de bibliothèques pour analyser les JSON vers des objets/classes.

De plus, comme REST utilise par défaut des formats lisibles par l’homme, il est plus facile à déboguer et à utiliser pour les nouveaux arrivants. Cela peut également influencer la rapidité de livraison de nouvelles fonctionnalités et vous aider à combattre les bugs qui apparaissent dans votre code.

Pour faire court, le support pour les applications de style REST est au moins très bon.

En Scala, nous avons même un outil appelé tapir — pour lequel j’ai eu le plaisir d’être l’un des mainteneurs pendant un certain temps. Tapir nous permet d’abstraire notre serveur HTTP et d’écrire des points de terminaison qui fonctionneront pour plusieurs serveurs.

gRPC lui-même fournit une bibliothèque cliente pour plus de 8 langages de programmation populaires. C’est généralement suffisant car ces bibliothèques contiennent tout ce qui est nécessaire pour créer une API gRPC. De plus, je suis au courant des bibliothèques offrant des abstractions plus élevées pour Java (via Spring Boot Starter) et pour Scala.

Une autre chose est que REST est aujourd’hui considéré comme un standard mondial et un point d’entrée pour la création de services, tandis que RPC et gRPC, en particulier, sont encore perçus comme une nouveauté malgré leur ancienneté à ce stade.

  • Résultat: REST, étant plus largement adopté et disposant de bien plus de bibliothèques et de frameworks

Support des outils

Les bibliothèques, frameworks et parts de marché générales ont été abordées ci-dessus, donc dans cette partie, je voudrais couvrir le support des outils autour des deux styles. Il s’agit d’outils pour les tests, les tests de performance/de stress et la documentation.

Tests automatisés/Tests

Premièrement, dans le cas de REST, les outils pour créer des tests automatisés sont intégrés dans différentes bibliothèques et frameworks ou sont des outils distincts conçus uniquement à cette fin, comme REST-assured.

Dans le cas de gRPC, nous pouvons générer un stub et l’utiliser pour les tests. Si nous voulons être encore plus stricts, nous pouvons utiliser le client généré comme une application distincte et l’utiliser comme base pour nos tests sur le service réel.

En ce qui concerne le support des outils externes pour gRPC, je suis au courant de:

  • Application Postman support pour gRPC
  • Le client HTTP de JetBrains utilisé dans leurs IDE peut également supporter gRPC avec une configuration minimale

  • Résultat un: Victoire pour REST; cependant, la situation semble s’améliorer pour gRPC.

Tests de performance

Ici, REST présente des avantages significatifs, car des outils comme JMeter ou Gatling facilitent la mise à l’épreuve des APIs REST.

Malheureusement, gRPC ne bénéficie pas de ce soutien. Je suis conscient que les personnes de Gatling ont le plugin gRPC inclus dans la version actuelle de Gatling, donc la situation semble s’améliorer.

Cependant, jusqu’à présent, nous n’avions qu’un plugin et une bibliothèque non officiels appelés ghz. Tous ces outils sont bons; ce n’est tout simplement pas le même niveau de support que pour REST.

  • Résultat deux: Victoire pour REST; cependant, la situation semble s’améliorer pour gRPC, encore une fois 😉

Documentation

En ce qui concerne la documentation des API, la victoire revient une fois de plus à REST avec OpenAPI et Swagger qui sont largement adoptés dans l’industrie et sont le standard de facto. Presque toutes les bibliothèques pour REST peuvent exposer la documentation swagger avec un effort minimal ou directement.

Malheureusement, gRPC n’a rien de semblable.

Cependant, la question est de savoir si gRPC a besoin d’un outil comme celui-ci. gRPC est plus descriptif que REST par sa conception, donc des outils de documentation supplémentaires peuvent.

En général, les fichiers .proto avec notre description d’API sont plus déclaratives et compactes que le code responsable de la création de notre code API REST, donc peut-être qu’on n’a pas besoin de plus de documentation à partir de gRPC. La réponse, je vous la laisse.

  • Résultat trois: Victoire pour REST; cependant, la question de la documentation gRPC reste ouverte.

Résultat global: 

A significant victory for REST


Résumé

Le tableau des scores finaux ressemble à ceci.


Les scores sont équitablement partagés entre les deux styles, avec trois victoires chacun et une catégorie sans vainqueur clair.

Il n’y a pas de solution miracle : pensez simplement à quelles catégories peuvent être les plus importantes pour votre application, puis choisissez l’approche qui a gagné dans la plupart d’entre elles — c’est au moins mon conseil.

Quant à mon préféré, je vais essayer gRPC si je le peux, car cela a très bien fonctionné dans mon dernier projet. Cela pourrait être une meilleure option que le vieil ami REST.

Si vous avez besoin d’aide pour choisir entre REST et gRPC ou pour résoudre tout autre problème technique, faites-le moi savoir. Je pourrais être en mesure d’aider.

Merci de votre temps.

Source:
https://dzone.com/articles/grpc-vs-rest-comparison