gRPC
Visualisation de données avec Python
VI. gRPC (Google Remote Procedure Call):
Cette section reprend celle présente dans le cours 2, et vient de la completer.
1. Introduction :
- gRPC est un système de RPC (Remote Procedure Call) moderne et de haute performance qui utilise HTTP/2 pour le transport, et Protocol Buffers comme mécanisme d’interface de description de langage (IDL). RPC permet à un programme d’exécuter une procédure (une routine de sous-programme) sur un autre ordinateur distant, qui peut être sur le même réseau ou situé à travers Internet.
- Conçu pour supporter une multitude de langages, cela signifie qu’un service gRPC écrit en Java pourrait être appelé par un client en Go, et vice versa.
2. Traduction de l’acronyme gRPC :
- g : initialement pour Google, car le framework a été développé par Google, mais il n’est pas un acronyme officiel.
- RPC : Remote Procedure Call, qui est un protocole permettant l’exécution d’une procédure dans un autre espace d’adresse (comme sur un autre ordinateur sur un réseau).
3. Avantages de gRPC :
- Communication bidirectionnelle : Grâce à HTTP/2, il prend en charge la communication bidirectionnelle en streaming.
- Performant : Les Protocol Buffers, souvent appelés protobufs, sont beaucoup plus efficaces que JSON pour la sérialisation et la désérialisation des données.
- Outils et langages : Il supporte de nombreux langages, avec des outils pour générer automatiquement des codes client et serveur dans de multiples langages.
- Deadline/Timeouts : gRPC vous permet de définir combien de temps un client est prêt à attendre pour une RPC à compléter. Le serveur peut vérifier cette et décider de compléter l’opération au lieu de traiter la demande.
- Annulation : Si un client n’a pas besoin du résultat d’un appel, il peut l’annuler. Le serveur est informé de l’annulation et peut économiser des ressources en arrêtant le traitement de l’appel.
Définitions utiles:
HTTP/2 : - HTTP/2 est la deuxième version majeure du protocole HTTP, utilisée par le World Wide Web. Par rapport à HTTP/1.x, HTTP/2: - Est binaire, au lieu de textuel, ce qui est plus efficace et moins sujet à des erreurs. - Permet une multiplexage des requêtes pour éviter le blocage de la connexion. - Utilise la compression des headers pour réduire la surcharge. - Permet des priorités de requêtes et des contrôles de flux.
Sérialisation et Désérialisation: - La sérialisation est le processus de transformation d’objets en une forme qui peut être facilement stockée ou transmise, et la désérialisation est l’inverse, transformant les données sérialisées en objets utilisables par le programme. Dans le contexte de gRPC et Protocol Buffers, la sérialisation transforme les données structurées en une suite de bytes compacte et efficace, tandis que la désérialisation reconvertit cette suite de bytes en une structure de données utilisable par les applications.
4. Protocol Buffers (protobufs) :
- Ce sont un mécanisme de sérialisation compact et efficace, à la fois en termes d’espace et de vitesse. Ils sont plus efficaces que XML ou JSON.
- Ils nécessitent une étape de compilation, où l’interface de description du service est transformée en code dans le langage de votre choix.
5. Fonctionnement :
- Définir le service : Commencez par définir le service dans un fichier .proto. Cela décrit les méthodes pouvant être appelées et leurs types de messages.
- Générer le code : Utilisez le compilateur
Protocol Buffers pour générer le code client et serveur. 3. Implémenter le serveur : Créez un serveur qui implémente les méthodes décrites dans le fichier .proto. 4. Appeler depuis le client : Le client peut appeler le serveur en utilisant le code généré.
6. Cas d’utilisation :
- Les microservices : grâce à sa rapidité et à sa capacité à créer des clients et des serveurs dans différents langages.
- Applications temps réel nécessitant une faible latence.
- Lorsque la taille des données est critique, car protobuf est plus efficace que JSON ou XML.
- Quand vous avez besoin de communication bidirectionnelle, comme les chats ou les notifications en temps réel.
7. Différences entre gRPC et d’autres formes d’IPC
Sockets :
- Différence : gRPC encapsule la complexité des sockets, fournissant une abstraction de haut niveau avec des fonctionnalités supplémentaires. Les sockets nécessitent une gestion manuelle des connexions, des données et des protocoles, tandis que gRPC gère ces aspects automatiquement.
Files d’attente de messages :
- Différence : gRPC est principalement synchronisé et permet une communication structurée et bidirectionnelle, contrairement aux files d’attente de messages qui sont asynchrones et souvent unidirectionnelles. gRPC facilite également la génération de code pour différents langages, ce qui n’est pas une fonctionnalité native des files d’attente de messages.
Pipes :
- Différence : Les pipes sont généralement limités à la communication unidirectionnelle et ne sont pas conçus pour les communications en réseau, tandis que gRPC utilise HTTP/2 pour une communication bidirectionnelle en streaming sur des réseaux. gRPC offre également une meilleure structure et définition des services par rapport aux pipes.
Mémoire partagée :
- Différence : La mémoire partagée est optimale pour les communications rapides au sein d’un même système, mais elle nécessite une gestion explicite de la synchronisation. gRPC, en revanche, fournit une solution clé en main pour la communication entre services, y compris la gestion des erreurs et la synchronisation, ce qui est plus adapté pour les systèmes distribués.
En se concentrant sur ces différences, on peut voir que gRPC offre une solution plus complète et intégrée pour l’IPC dans des environnements distribués, avec des avantages en termes de performance, d’interopérabilité et de facilité d’utilisation grâce à ses capacités de génération de code et de définition de service.
8. Avantages de gRPC pour la Sécurité et l’Authentification
- Confidentialité et intégrité des données : gRPC utilise TLS/SSL pour crypter les données en transit, ce qui empêche les interceptions non autorisées et garantit que les données ne sont pas altérées.
- Authentification au niveau du service : Avec des jetons JWT ou OAuth2, gRPC permet de s’assurer que seuls les clients authentifiés peuvent appeler certaines méthodes RPC.
- Contrôle d’accès basé sur les rôles : gRPC peut être intégré avec des systèmes de gestion des identités pour implémenter des contrôles d’accès basés sur les rôles (RBAC), permettant de définir précisément qui peut faire quoi.
9. Avantages de gRPC pour le Déploiement et l’Échelle
- Gestion efficace des ressources : Les connexions persistantes et le multiplexage dans HTTP/2 permettent à gRPC de gérer les ressources de manière plus efficace, réduisant ainsi les coûts opérationnels.
- Mise à l’échelle automatique : L’intégration avec des outils d’orchestration de conteneurs comme Kubernetes permet à gRPC de s’adapter automatiquement à la demande en ajustant le nombre d’instances de service.
- Équilibrage de charge intégré : gRPC prend en charge l’équilibrage de charge côté client, permettant aux clients de répartir les appels RPC de manière équilibrée entre les instances de serveur.
En résumé, gRPC est bien adapté aux applications modernes où la sécurité, l’authentification et la capacité à opérer à grande échelle sont essentielles. Sa conception permet non seulement une communication inter-services efficace mais aussi une intégration aisée avec les infrastructures de sécurité et de déploiement existantes.
10. Étapes de mise en place d’un service gRPC
a. Définir le service et les messages dans un fichier .proto
La première étape consiste à définir l’interface du service gRPC dans un fichier .proto. Ce fichier spécifie les méthodes RPC disponibles, ainsi que les structures de données d’entrée et de sortie (messages) utilisées par ces méthodes.
b. Générer le code source à partir du fichier .proto
Une fois le fichier .proto écrit, vous utilisez le compilateur Protocol Buffers (protoc) pour générer le code source dans le langage de programmation de votre choix. Ce code source comprend les classes de base pour les messages et les services que vous avez définis, ainsi que les stubs pour le client et le serveur.
c. Implémenter le serveur
Avec le code généré, vous créez ensuite une classe serveur qui étend la classe de base du service gRPC et implémente les méthodes RPC définies dans le fichier .proto.
d. Implémenter le client
De manière similaire, vous utilisez les stubs générés pour construire un client gRPC qui peut appeler les méthodes du service.
e. Démarrer le serveur et appeler le service depuis le client
Enfin, vous démarrez le serveur gRPC pour qu’il écoute les appels entrants, et vous utilisez le client pour appeler les méthodes du service.
11. Exemple de mise en place d’un service gRPC
Imaginons que nous voulons créer un service gRPC simple pour un système de gestion de tâches. Le service permettra aux clients d’ajouter des tâches et de les lister.
a. Fichier .proto pour le service de gestion de tâches
"proto3";
syntax =
package taskmanager;
// Le service de gestion de tâches
service TaskService {// Ajoute une nouvelle tâche
rpc AddTask(AddTaskRequest) returns (AddTaskResponse);
// Liste toutes les tâches
rpc ListTasks(ListTasksRequest) returns (ListTasksResponse);
}
// La demande pour ajouter une tâche
message AddTaskRequest {
string description = 1;
}
// La réponse à une demande d'ajout de tâche
message AddTaskResponse {
bool success = 1;
string id = 2;
}
// La demande pour lister les tâches
message ListTasksRequest {}
// La réponse à une demande de liste de tâches
message ListTasksResponse {
repeated Task tasks = 1;
}
// Une tâche
message Task {
string id = 1;
string description = 2;
bool completed = 3;
}
```python
### b. Génération du code source
Utilisez le compilateur protoc pour générer le code source à partir du fichier .proto. Par exemple, pour générer du code Python :
```bash protoc -I=. --python_out=. --grpc_python_out=. taskmanager.proto
c. Implémentation du serveur en Python
from concurrent import futures
import grpc
import taskmanager_pb2
import taskmanager_pb2_grpc
class TaskService(taskmanager_pb2_grpc.TaskServiceServicer):
def __init__(self):
self.tasks = {}
def AddTask(self, request, context):
= str(len(self.tasks) + 1)
task_id self.tasks[task_id] = {
'description': request.description,
'completed': False
}return taskmanager_pb2.AddTaskResponse(success=True, id=task_id)
def ListTasks(self, request, context):
for task_id, task_info in self.tasks.items():
yield taskmanager_pb2.Task(
id=task_id,
=task_info['description'],
description=task_info['completed']
completed
)
def serve():
= grpc.server(futures.ThreadPoolExecutor(max_workers=10))
server
taskmanager_pb2_grpc.add_TaskServiceServicer_to_server(TaskService(), server)'[::]:50051')
server.add_insecure_port(
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
d. Implémentation du client en Python
import grpc
import taskmanager_pb2
import taskmanager
_pb2_grpc
def run():
with grpc.insecure_channel('localhost:50051') as channel:
= taskmanager_pb2_grpc.TaskServiceStub(channel)
stub = stub.AddTask(taskmanager_pb2.AddTaskRequest(description="Buy milk"))
response print(f"Task added with ID: {response.id}")
= stub.ListTasks(taskmanager_pb2.ListTasksRequest())
tasks for task in tasks:
print(f"Task {task.id}: {task.description} (Completed: {task.completed})")
if __name__ == '__main__':
run()
Dans cet exemple, le serveur gRPC gère un dictionnaire simple de tâches et expose deux méthodes RPC : AddTask pour ajouter une nouvelle tâche et ListTasks pour lister toutes les tâches. Le client crée une connexion au serveur, ajoute une tâche et liste ensuite toutes les tâches disponibles.
12. Comprendre la différence entre gRPC et une API HTTP classique
Comprendre la différence entre les services gRPC et les API HTTP classiques est essentiel pour choisir la bonne technologie en fonction des besoins de votre application. Voici une explication structurée pour clarifier ces différences et aider à décider quand utiliser l’un ou l’autre.
a. Communication et Protocole
gRPC: - Utilise HTTP/2, qui est plus performant que HTTP/1.1 grâce au multiplexage des requêtes, à la compression des en-têtes et au contrôle de flux. - Les appels gRPC sont plus comme des appels de fonctions dans le code, où vous avez un stub (proxy) et vous appelez des méthodes directement sur ce stub.
API HTTP: - Généralement basé sur HTTP/1.1, bien que HTTP/2 soit également utilisé par les API REST modernes. - Les requêtes sont envoyées comme des URL spécifiques avec des méthodes HTTP (GET, POST, PUT, DELETE, etc.).
b. Format des Données
gRPC: - Utilise Protocol Buffers, un mécanisme de sérialisation binaire, qui est plus léger et plus rapide que les formats textuels. - Nécessite une définition préalable du schéma des données dans un fichier .proto, qui est ensuite compilé pour générer le code côté client et serveur.
API HTTP: - Utilise souvent JSON ou XML pour la sérialisation des données, qui sont des formats textuels et plus lourds en comparaison. - Moins formel en termes de définition de schéma, ce qui peut conduire à plus de flexibilité mais aussi à plus d’ambiguïté.
c. Performance et Efficacité
gRPC: - Conçu pour être performant et efficace, idéal pour les environnements à faible latence et les communications fréquentes entre les services. - Le multiplexage sur HTTP/2 permet à plusieurs appels de se produire en parallèle sur une seule connexion TCP.
API HTTP: - Peut être moins performant en raison de l’utilisation de formats de données textuels et de la création de nouvelles connexions TCP pour chaque requête (dans le cas de HTTP/1.1).
d. Facilité d’Utilisation et Compatibilité
gRPC: - Peut avoir une courbe d’apprentissage plus raide en raison de la nécessité de définir des fichiers .proto et de comprendre Protocol Buffers. - N’est pas compatible avec les navigateurs web sans un proxy car les navigateurs ne supportent pas directement gRPC.
API HTTP: - Plus facile à utiliser et à déboguer car les requêtes et les réponses peuvent être lues et comprises directement. - Compatibilité native avec les navigateurs web, ce qui facilite la création d’applications front-end qui communiquent avec le serveur.
e. Gestion des Timeouts et Annulations
gRPC: - Intègre la gestion des timeouts et des annulations directement dans le protocole, permettant des contrôles de flux sophistiqués et des annulations côté serveur.
API HTTP: - Les timeouts doivent souvent être gérés par la bibliothèque cliente ou par le code utilisateur, et il n’y a pas de mécanisme standard pour l’annulation d’une requête une fois qu’elle a été envoyée.
f. Cas d’Utilisation
gRPC est souvent considéré comme plus “intégré” dans les systèmes pour plusieurs raisons :
- Couplage Fort : gRPC nécessite que les clients et les serveurs soient construits à partir de la même définition de service (le fichier .proto). Cela crée un couplage fort entre le client et le serveur, ce qui est idéal pour les systèmes internes où vous contrôlez les deux extrémités de la communication.
- Optimisation Interne : Avec ses caractéristiques de performance et son efficacité de sérialisation, gRPC est souvent utilisé pour la communication interne entre les services dans une architecture de microservices. Cela permet une communication rapide et efficace entre les services qui font partie du même écosystème.
- Non-Browser Friendly : gRPC n’est pas directement supporté par les navigateurs web sans l’utilisation d’un proxy pour convertir les appels gRPC en quelque chose que les navigateurs peuvent comprendre. Cela le rend moins adapté pour les systèmes qui nécessitent une interaction directe avec les clients via le navigateur.
D’autre part, les API HTTP sont souvent vues comme plus “ouvertes” :
- Couplage Faible : Les API HTTP, en particulier celles qui suivent le style REST, sont conçues pour avoir un couplage faible et une interface contractuelle stable. Cela permet aux clients de différentes natures (y compris les navigateurs web) d’interagir avec le serveur sans avoir besoin de partager la même base de code.
- Accessibilité : Les API HTTP sont accessibles via des URL standard et peuvent être consommées par une grande variété de clients, y compris les navigateurs web, les outils de ligne de commande comme curl, et pratiquement n’importe quelle langue de programmation.
- Interopérabilité : Les API HTTP sont basées sur des standards web largement adoptés, ce qui les rend idéales pour l’exposition de services à un public externe, comme les développeurs tiers ou les applications partenaires.
En résumé, gRPC est souvent préféré pour les communications internes au sein d’un système où la performance et la cohérence sont critiques, tandis que les API HTTP sont la norme pour les interfaces publiques et les interactions avec le monde extérieur. Cette distinction n’est pas absolue, et il y a des cas où gRPC est utilisé pour des API publiques (souvent avec un proxy HTTP) ou où les API HTTP sont utilisées pour la communication interne, mais ces tendances générales peuvent servir de guide lors de la conception de l’architecture de votre système.