Dans cet article, nous verrons comment créer un service d’API gRPC simple à point de terminaison avec Protocol Buffers et préparer son code côté client et côté serveur avec les outils gRPC. Ce sera une tentative de repartir de zéro, de prendre une fonction simple et de l’exposer via une interface gRPC sur notre propre machine. Nous n’utiliserons pas gRPC dans les modes avancés (streaming de requêtes, streaming de réponses, streaming bidirectionnel) avec des fonctionnalités supplémentaires telles que la gestion des erreurs et l’authentification. Ce didacticiel vous aidera à créer des API à l’aide de gRPC en Python.

Qu’est-ce que gRPC ?

gRPC ou Google Remote Procedure Call est un framework RPC open source conçu pour être rapide et efficace. Il a été créé par Google dans le but de développer un framework RPC moderne pouvant s’exécuter dans n’importe quel environnement. Ils voulaient quelque chose qui puisse fonctionner n’importe où, y compris dans les centres de données ou sur le dernier kilomètre de l’informatique distribuée pour connecter les appareils, les applications mobiles et les navigateurs aux services backend. Il s’agit d’un cadre RPC moderne, open source et hautes performances.

Ce qui le distingue des API REST traditionnelles, c’est qu’il s’appuie sur des tampons de protocole pour définir à la fois les structures de données et les formats de sérialisation. gRPC est compatible avec plusieurs langages de programmation et prend en charge l’équilibrage de charge, le traçage, la vérification de l’état et l’authentification. Il inclut également un support enfichable pour la découverte de services multilingues.

Création d’une fonction à afficher

Commençons par créer une fonction (procédure) que nous allons exposer et appeler à distance . Nous pouvons créer et localiser ce fichier dans un dossier, disons appelé, grpc-tutorial-python.

#calculator.py
import math

def square_root(x):
  y = math.sqrt(x)
  return y

Ici, nous venons de créer une fonction de base avec la bibliothèque mathématique pour générer la racine carrée de x. C’est uniquement pour les tests, vous pouvez mettre ce que vous voulez ici, même une fonction d’impression de base suffira.

Générer les classes gRPC

Ici, nous allons construire le service gRPC en utilisant le langage généré par Protocol Buffers. Les tampons de protocole sont utilisés pour définir les messages, leurs types de données et les modèles de service dans un fichier proto. Le fichier proto est un fichier texte qui se termine par l’extension .proto, écrit en utilisant la syntaxe du Protocol Buffer. Nous pouvons le faire dans un dossier séparé, cal, pour garder les choses en ordre.

#calculator.proto
syntax = "proto3";

message Number {
    float value = 1;
}

service Calculator {
    rpc SquareRoot(Number) returns (Number) {}
}

Le modèle de service est essentiellement la définition de la manière dont nos services transmettront des données et interagiront les uns avec les autres. Ensuite, nous générerons du code pour les classes de message et de serveur à l’aide de la compilation de protocole.

Une fois le modèle de service défini dans le fichier .proto, nous pouvons générer les fichiers de service en exécutant la commande protoc sur le fichier .proto. La commande protoc générera automatiquement du code pour les nouveaux fichiers (et classes). Pour cela, nous aurons besoin de bibliothèques ou d’outils gRPC pouvant être installés avec les commandes suivantes :

pip install grpcio
pip install grpcio-tools

Après cela, nous pouvons exécuter la commande protoc sur le fichier .proto en exécutant la commande suivante :

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. cal/calculator.proto

Les deux fichiers suivants seront créés si tout a fonctionné correctement :

cal/calculator_pb2.py --which  contains message classes
cal/calculator_pb2_grpc.py -- which contains server and client classes

Créer un serveur gRPC

Maintenant que nous avons généré tous les fichiers dont nous avions besoin pour créer le serveur, nous pouvons enfin commencer à écrire le fichier du serveur :

import grpc
from concurrent import futures
import time

#import the generated files
import cal.calculator_pb2 as calculator_pb2
import cal.calculator_pb2_grpc as calculator_pb2_grpc

#import the function files
import calculator

#create a class to define the server functions derived from calculator_pb2_grpc (or the server and client classes)
class CalculatorServicer(calculator_pb2_grpc.CalculatorServicer):

    #calculator.square_root is exposed here
    def SquareRoot(self, request, context):
        response = calculator_pb2.Number()
        response.value = calculator.square_root(request.value)
        return response


#create a gRPC server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

#use the function "add_CalculatorServicer_to_server" to add the defined class to the created server
calculator_pb2_grpc.add_CalculatorServicer_to_server(
        CalculatorServicer(), server)

#listen on port 50051
print('Starting server. Listening on port 8000.')
server.add_insecure_port('[::]:8000')
server.start()

# since server.start() will not block be blocked ever, a sleep-loop is added to keep alive
try:
    while True:
        time.sleep(86400)
except KeyboardInterrupt:
    server.stop(0)

gRPC appellera automatiquement la méthode square_root remplacée dans la classe CalculatorServicer lorsqu’un client accède au point de terminaison SquareRoot. Nous pouvons maintenant également démarrer le serveur pour voir si tout fonctionne ou non, ce qui peut être fait avec :

python server.py

Et si vous obtenez une réponse comme celle-ci signifie que votre code a fonctionné :

Nous avons maintenant un serveur gRPC en direct, qui s’exécute et répertorie les événements sur le port 8000.

Ensuite, utilisez CalculatorStub pour créer un client pour le service d’API gRPC, comme illustré ci-dessous :

import grpc

#import the generated files
import cal.calculator_pb2 as calculator_pb2
import cal.calculator_pb2_grpc as calculator_pb2_grpc

#open and connect to the gRPC channel we just created
channel = grpc.insecure_channel('localhost:8000')

#create a stub (client)
stub = calculator_pb2_grpc.CalculatorStub(channel)

#create a valid request message or just any number in our case
number = calculator_pb2.Number(value=15)

#make the call
response = stub.SquareRoot(number)

#print the results
print(response.value)

Le client se connectera à une API que vous proposez via GRPC. Votre serveur utilisera la classe CalculatorService, avec un paramètre de nom pour en acquérir une instance. gRPC interprète cette classe Python comme une classe définie par Protocol Buffers. Il créera ensuite une instance de Python en analysant le message CalculatorService Protobuf et en le transmettant à votre serveur via une connexion GRPC. La réponse de votre serveur, un message User Protocol Buffers, est ensuite analysée dans une classe User Python, puis imprimée.

Considérez le fichier .proto comme un contrat entre le serveur et ses clients. gRPC est le coursier et Protocol Buffers est l’arbitre/traducteur qui applique le contrat. Les tampons de protocole traduisent ce que les clients et les serveurs parlent depuis/vers un langage de traduction universel avec gRPC assurant les communications dans HTTP/2. Lorsque vous travaillez avec des tampons de protocole et gRPC, vous pouvez vous concentrer davantage sur les véritables fonctionnalités de votre application.

Résultats

python3 client.py

Nous pouvons exécuter ce fichier de la même manière que nous l’avons fait pour l’autre :

Notez que nous devons garder le fichier du serveur en cours d’exécution lorsque nous l’exécutons car c’est là que se trouve notre API. Vous pouvez ouvrir un autre terminal pour cela.

Après avoir exécuté le fichier ci-dessus, vous devriez obtenir une réponse semblable à celle-ci :

Cela signifie que cela a fonctionné !!

Conclusion

L’architecture de microservice fait fureur en ce moment. Les microservices vous permettent de diviser votre architecture monolithique en plusieurs services plus petits, chacun avec sa propre base de code, son magasin de données et son instance déployable et de communiquer entre eux sur un réseau. Il existe d’autres subtilités qui composent gRPC, telles que le streaming de réponse et le streaming bidirectionnel, mais j’espère que ce message deviendra une bonne référence pour ceux qui débutent.

Il y a beaucoup de place à l’amélioration en ce qui concerne ce projet, alors essayez d’expérimenter par vous-même à l’aide de la documentation de Google sur gRPC. C’est ainsi que vous créez des API à l’aide de gRPC en Python.

Voici quelques tutoriels utiles que vous pouvez lire :