Catégories
Start-up et applications

Comment utiliser les bibliothèques et les cadres gRPC

Bien que le gRPC apporte beaucoup de puissance à l'informatique distribuée au niveau de l'entreprise, ce n'est pas une technologie facile à mettre en œuvre. gRPC est une spécification uniquement. Ainsi, tout programmeur ou entreprise est libre de l'implémenter dans n'importe quel langage capable de gérer les détails de la spécification. Mais c'est plus facile à dire qu'à faire car la mise en œuvre de gRPC est une tâche ardue. Non seulement vous devez écrire des routines pour encoder et décoder les structures de données qui convertissent les messages texte gRPC vers et depuis le format binaire Protocol Buffers, vous devez également écrire la logique derrière les procédures gRPC qui sont définies dans le fichier .proto qui décrit l'API gRPC donnée. En outre, vous devez écrire la logique de routage côté serveur qui permet aux messages codés binaires de se déplacer entre un client et un service spécifique dans l'API gRPC.

Et, si cela ne suffisait pas, si vous souhaitez utiliser l'API, vous devez écrire un client gRPC qui prend en charge l'accès au serveur via HTTP / 2 (la dernière version du protocole de base du Web avec lequel très peu de gens savent travailler encore). Ce client doit être en mesure d'effectuer le codage et le décodage des tampons de protocole comme spécifié dans le même .proto fichier utilisé par le serveur.

C'est beaucoup de travail. Heureusement, c'est un travail que vous n'avez pas à faire. La Cloud Native Computing Foundation (CNCF), l'organisation qui supervise le développement gRPC (dont Google est un membre platine), publie un certain nombre de projets qui effectuent la plupart du travail nécessaire pour créer un serveur et un client gRPC entièrement fonctionnels. Ces projets fournissent un cadre qui effectue toute la programmation requise pour créer un serveur HTTP / 2 et exécuter le routage vers chaque procédure définie dans l'API. En outre, les projets effectuent le travail d'encodage et de décodage des données dans et à partir du format binaire Protocol Buffers. Dans la plupart des cas, il suffit au programmeur de fournir la logique interne de chaque procédure définie dans le .proto fichier. Le cadre s'occupe du reste.

Cela ne veut pas dire que l'utilisation d'un projet est une promenade dans le parc. Chacune des implémentations a sa propre façon de travailler avec gRPC. Par exemple, l'implémentation .NET publie un certain nombre de classes dans un espace de noms spécial nommé Gprc qui couvre tous les aspects de gRPC opérations. Chacune de ces classes a beaucoup de détails qui doivent être compris. Il en va de même pour l'implémentation Java où ces classes se trouvent dans les packages io.grpc. *. Encore une fois, beaucoup de cours, beaucoup de détails. Ce ne sont que deux des treize implémentations de gRPC répertoriées sur grpc.io. Go, qui n'est pas un langage orienté objet, a sa propre approche pour implémenter une API gRPC, tout comme Python. Ainsi, quelle que soit la route que vous envisagez de prendre, vous pouvez vous attendre à vivre une courbe d'apprentissage importante absorbant les tenants et les aboutissants de l'implémentation donnée.

Aux fins de cet article, nous à ProgrammableWeb ont décidé de se concentrer sur un examen détaillé de l'implémentation Node.js de gRPC. L'approche que nous avons adoptée consiste à définir une API gRPC de démonstration dans le .proto puis implémentez l'API à l'aide des bibliothèques Node.js publiées ici.

Le nom de l'API gRPC de démonstration est SimpleService. Vous pouvez trouver le code source de SimpleService dans le ProgrammableWeb Dépôt GitHub ici.

Présentation de SimpleService

Le projet SimpleService qui accompagne cette tranche est livré avec un serveur gRPC et un outil CLI qui permet aux utilisateurs d'interagir directement avec l'API exécutée sur le serveur gRPC. La figure 1 ci-dessous montre une animation de l'outil CLI appelant la procédure nommée Blabber () sur le serveur gRPC associé. Blabber () est implémenté à l'aide d'un flux bidirectionnel.

Figure 1: Un exemple qui montre les outils CLI appelant la procédure bidirectionnelle SimpleService Blabber ().

Avant d'entrer dans les détails sur la façon dont SimpleService implémente chacune de ses procédures distantes, examinons le travail requis pour que le serveur gRPC soit opérationnel. Les bibliothèques Node.js utilisées pour implémenter SimpleService offrent deux façons d'implémenter l'API. Un moyen est appelé statique. L'autre s'appelle dynamique.

Implémentation statique vs dynamique d'une API gRPC sous Node.js

L'implémentation statique utilise des classes JavaScript créées à l'aide d'une version spéciale du protocole outil de génération automatique de code. Cet outil s'appelle grpc_tools_node_protoc. Un développeur exécutera grpc_tools_node_protoc contre les API .proto fichier pour créer des objets JavaScript correspondant aux messages et procédures définis dans le .proto fichier. Le développeur programme ensuite le serveur et le client en utilisant ces classes. Pour en savoir plus sur le fonctionnement de la génération automatique, vous pouvez lire l'article associé sur ProgrammableWeb ici.

L'implémentation dynamique, d'autre part, utilise la bibliothèque de chargeur Node.js Protobuf (@ grpc / proto-loader) pour charger le .proto en mémoire lors de l'exécution et pour générer le message JavaScript et les objets de procédure dans les coulisses. Aucune génération automatique de code manuelle n'est requise. La bibliothèque fait tout.

L'API gRPC de démonstration SimpleService implémente une implémentation dynamique. En fait, vous verrez les mécanismes du chargement dynamique dans l'examen de l'implémentation Node.js du serveur gRPC que nous aborderons ensuite.

Présentation de l'implémentation de l'API gRPC de démonstration

Le listing 1 ci-dessous montre le fichier, server.js. Le fichier contient la logique basée sur Node.js qui initialise et démarre le serveur gRPC SimpleService.

Le code d'initialisation du serveur est assez simple. Lignes 1 et 2, déclarez les packages gRPC requis qui feront le gros du travail dans les coulisses. Ces packages contiennent l'intelligence du serveur HTTP / 2 ainsi que les mécanismes de routage, de sérialisation et de désérialisation qui seront utilisés sous couvert pour fournir et traiter les données provenant d'un client appelant.

La ligne 5 définit l'emplacement et le nom des tampons de protocole .proto fichier que les packages utilisent à des fins de routage, de sérialisation et de désérialisation. (Se souvenir du .proto file est la définition faisant autorité de l'API. Le fichier .proto fournit les définitions des messages Protocol Buffer et des procédures distantes.)

La ligne 6 définit le port sur lequel le serveur écoutera le trafic entrant. Ce port peut être personnalisé à l'aide de la variable d'environnement PORT du système d'exploitation. Si PORT n'est pas défini dans une variable d'environnement, le port par défaut 8080 sera utilisé.

La ligne 8 utilise l'objet protoLoader fourni par la bibliothèque Protobuf Loader. Le protoLoader, comme décrit ci-dessus, est la bibliothèque qui effectue le travail de conversion des messages et des procédures définis par l'API .proto fichier dans JavasScript utile

le packageDéfinition est utilisé pour créer le nom personnalisé simple_proto objet à la ligne 16. Le simple_proto object est la représentation du service gRPC défini dans le .proto fichier.

Listing 1: Le code d'initialisation et de démarrage de l'API SimpleService

Liste 1: Le code d'initialisation et de démarrage de l'API SimpleService

Les lignes 22 à 68 sont des fonctions qui correspondent aux procédures API définies dans le .proto fichier. Ces fonctions contiennent la logique métier réelle derrière chaque procédure.

La ligne 71 du listing 1 ci-dessus est l'endroit où le gRPC est créé dans la fonction principale(). Notez que la ligne 72 crée un objet nommé implémentations. Les propriétés ajouter, soustraire, multiplier, diviser, bavarder, bavardage, et ping sont ajoutés à implémentations aux lignes 73 à 79. Notez également que chaque propriété se voit attribuer le nom de l'une des fonctions définies précédemment aux lignes 22 à 68. Par exemple, implémentations.add se voit attribuer la fonction ajouter() à la ligne 73.

L'affectation d'une fonction à une propriété de l'objet implémentations est la façon dont la liaison route-à-procédure est implémentée à l'aide de grpc paquet.

Un nouvel objet serveur gRPC est créé à la ligne 81. Ensuite, à la ligne 82, un service est ajouté au serveur à l'aide du méthode server.addService (). Notez que le objet simple_proto qui représente les définitions dans le .proto fichier et le implémentations l'objet est passé à serveur.addService () comme paramètres. Les internes de serveur.addService () fera tout le travail d'acheminement des appels client vers la procédure distante appropriée. Aussi, serveur.addService () gère tout le travail de transmission de données vers et depuis la procédure distante donnée. Cela inclut non seulement les données transmises aux appels de demande / réponse, mais également les données transmises dans les flux unidirectionnels et bidirectionnels.

Comme vous pouvez le voir, c'est beaucoup de travail. Imaginez devoir tout faire à partir de zéro. Comme dit précédemment, c'est une tâche herculéenne. Heureusement, les bibliothèques font tout le travail pour vous. Tout ce que le programmeur doit faire est de fournir la logique métier pour les fonctions définies dans le .proto fichier et acheminé par le grpc paquet en conséquence. Voyons donc comment l'implémentation des procédures distantes est facilitée à l'aide de Node.js grpc paquet. Commençons par examiner les communications de demande / réponse.

Communication de demande / réponse unique

L'API de démonstration a quatre fonctions mathématiques et une fonction ping qui prennent en charge la communication demande / réponse entre le client et le serveur. Le listing 2 ci-dessous montre un extrait de l'API .proto fichier dans lequel ces fonctions sont définies conformément à la spécification Protocol Buffers.

   rpc Add (Request) returns (Response) { }
   rpc Subtract (Request) returns (Response) { }
   rpc Multiply (Request) returns (Response) { }
   rpc Divide (Request) returns (Response) { }
   rpc Ping (PingRequest) returns (PingResponse) { }

Liste 2: Les procédures de l'API de démonstration qui communiquent par requête / réponse

Nous allons examiner de près la mise en œuvre du Ajouter() procédure car sa structure est représentative de la façon dont tout appel de demande / réponse est implémenté à l'aide de Node.js grpc paquet.

Le listing 3 ci-dessous montre le code Node.js pour la procédure nommée ajouter().

Listing 3: Une requête / réponse appelle l'API gRPC SimpleService

Liste 3: Une demande / réponse appelle l'API gRPC SimpleService

le ajouter() fonction est liée à la Ajouter() procédure définie dans le .proto utilise l'instruction suivante, comme indiqué ci-dessus dans le listing 1, ligne 73:

implementations.ping = ping;

Attention, cette technique de liaison est spéciale pour le package gRPC Node.js. Les bibliothèques et frameworks dans d'autres langages tels que Java et C # auront une manière différente de lier les procédures définies dans un .proto fichier au code d'implémentation réel.

Comme vous pouvez le voir ci-dessus dans le listing 3, ligne 1, la fonction ajouter() a deux paramètres, call et callback. Les composants internes de Node.js grpc package fournit des valeurs pour ces paramètres à chaque fois ajouter() la procédure est appelée par un client.

le appel Le paramètre représente un objet qui est l'appel logique effectué par le client à la fonction. L'objet d'appel a la propriété, demande, qui représente la requête HTTP / 2 réelle effectuée par le client appelant. le rappeler le paramètre représente une fonction de rappel fournie par le Node.js grpc package au moment de l'exécution. La fonction de rappel est un wrapper pour la réponse HTTP / 2 que le Node.js grpc le code renvoie au client appelant.

La fonction de rappel a deux paramètres implicites se tromper et Les données structuré comme ça rappel (err, données). Le ajouter() fonction lancer une erreur, le message d'erreur ou l'objet qui représente l'erreur sera transmis comme se tromper paramètre. Si tout se passe bien, le résultat de la fonction sera passé comme Les données paramètre. Celles-ci se tromper et Les données les paramètres ainsi que leur ordre sont la convention standard de Node.js pour les fonctions de rappel.

Passons à l'examen de la logique de mise en œuvre du ajouter() une fonction. La déclaration suivante est tirée du listing 3, ligne 2 ci-dessus. L'instruction affecte le tableau de nombres transmis par le client appelant à une variable locale nommée contribution.

 const input = call.request.numbers;

Le code ci-dessus attribue la valeur de la propriété call.request.numbers à l'entrée variable. Mais, d'où vient call.request.numbers viens de? Regardons la façon dont le Ajouter() la procédure est définie dans le .proto fichier:

 rpc Add (Request) returns (Response) { }

Notez que le Ajouter() la procédure prend la coutume Demande message en tant que paramètre et que la coutume Demande le message est défini comme tel dans le .proto fichier:

message Request {
   repeated double numbers = 1;
}

Notez dans le message Protocol Buffers ci-dessus que la coutume Demande message définit un champ nommé Nombres. Ce Node.js grpc package traduit ceci Nombres champ sur le appel objet passé au ajouter() procédure comme ceci:

call.request.numbers;

Donc, call.request.numbers est le tableau de valeurs numériques que le ajouter() la fonction doit être traitée.

Additionner les chiffres est une entreprise simple. La déclaration ci-dessous est tirée du listing 3, ligne 3:

const result = input.reduce((a, b) => a + b, 0);

Le code utilise le réduire() function, qui est une méthode implicite à tout tableau JavaScript pour parcourir les éléments du tableau de nombres transmis à la méthode et les résumer. Ensuite, le résultat est passé à la fonction de rappel comme ceci:

callback(null, {result});

Notez que le résultat de input.reduce () est retourné comme un objet JavaScript comme ceci {résultat}. La bibliothèque Node.js pour grpc s'attend à ce que les résultats soient renvoyés en tant qu'objet JSON.

La mise en œuvre du Ping () la fonction fonctionne d'une manière presque identique à Ajouter(). Le but de Ping () est de renvoyer les données qui lui sont envoyées. Ainsi, il recycle simplement la chaîne envoyée par l'appelant comme ceci:

callback(null, {result: call.request.data} );

Encore une fois, d'où viennent les données de valeur? Jetez un œil au chemin Ping () la procédure est définie dans le .proto fichier:

rpc Ping (PingRequest) returns (PingResponse) { }

Et puis regardez comment le .proto fichier définit le PingRequest message.

message PingRequest {
   string data = 1;
}

Comme vous pouvez le voir, data est le nom du champ unique dans le PingRequest message. Ainsi, il est représenté par le Node.js grpc paquet comme call.request.data.

Maintenant que nous avons expliqué comment la communication demande / réponse est implémentée dans l'API de démonstration gRPC, passons au streaming.

Implémentation de flux unidirectionnels

Comme décrit précédemment, gRPC est conçu pour prendre en charge les flux unidirectionnels et bidirectionnels. L'API SimpleService fournit des exemples de chaque type. Le streaming unidirectionnel est implémenté dans le Bavarder() procédure. Le streaming bidirectionnel est implémenté dans le Blabber () procédure.

L'intention de la Bavarder() procédure consiste à renvoyer une chaîne définie par le chatItem de retour dans un flux du serveur au client en continu. Le nombre de fois chatItem valeur sera renvoyée est indiquée par la valeur définie dans le limite champ. Tous les deux chatItem et limite sont définis dans le message ChatterRequest comme indiqué ci-dessous:

message ChatterRequest {
   string chatItem = 1;
   int32 limit = 2;
}

le Bavarder() procédure définie dans le .proto fichier comme suit …

rpc Chatter (ChatterRequest) returns (stream ChatterResponse) {}

… Est implémenté dans le JavaScript bavarder() fonction illustrée ci-dessous dans la liste 4.

Listing 4: Streaming de données vers un client appelant avec un nombre limité d'éléments à l'aide d'un flux de terminaison

Liste 4: Diffusion des données vers un client appelant avec un nombre limité d'éléments à l'aide d'un flux de terminaison

Le format défini par le Node.js grpc package pour gérer un flux est différent du format de demande / réponse indiqué dans le ajouter() et ping () fonctions illustrées ci-dessus. Alors qu'une fonction prenant en charge une interaction demande / réponse gRPC utilise une fonction de rappel pour renvoyer des données dans une réponse, l'envoi de données sur un flux du serveur au client implique l'utilisation du écrire méthode qui fait partie de la appel objet. Comme avec le ajouter() et ping () fonctions montrées précédemment, les appel est fournie par le Node.js grpc paquet au bavarder() fonctionne comme un paramètre d'exécution.

La façon dont bavarder fonctionne est-ce que call.write est appelé dans une boucle JavaScript for, comme indiqué ci-dessus dans le listing 4 à la ligne 2. Le nombre d'itérations dans la boucle for est défini par la valeur affectée à call.request.limit.

  • appel est l'objet d'appel fourni au moment de l'exécution en tant que paramètre par le package grpc Node.js
  • demande un objet qui représente la demande du client
  • limite représente les champs de limite spécifiés dans le ChatRequest message défini dans le .proto fichier

Chaque itération de la boucle for renverra un message au client dans un flux. Le flux est établi par les composants internes de Node.js grpc paquet. Le format des informations renvoyées au client dans le flux est conforme à la structure du message de retour spécifié ChatterResponse ainsi:

message ChatterResponse {
   string chatItem = 1;
   int32 index = 2;
}

Le message sera transmis à call.write () au format JSON. Les composants internes de Node.js grpc package sérialisera le JSON dans le binaire Protocol Buffers qui sera envoyé dans le flux. Un exemple de JSON qui est envoyé à call.write () est comme suit:

{chatItem: "hi there", index: 3}

Dans le cas illustré ci-dessus, le serveur SimpleService renverra la chaîne "hi there" au client 3 fois dans un flux.

Quand le pour la boucle est terminée, le call.end () est appelée à la ligne 6 du listing 4 et arrête le flux.

Implémentation de flux bidirectionnels

Le code côté serveur pour prendre en charge un flux bidirectionnel est similaire au code pour prendre en charge un flux unidirectionnel du client au serveur. La différence est que le code côté serveur a un call.on () gestionnaire d'événements qui capture les messages provenant du flux client.

Le listing 5 ci-dessous montre le blabber () qui est un extrait du code server.js répertorié ci-dessus.

Listing 5: Streaming de données vers un client appelant à l'aide d'un flux connecté en continu

Liste 5: Streaming de données vers un client appelant à l'aide d'un flux connecté en continu

Notez qu'il existe un gestionnaire d'événements JavaScript, call.on () qui capture l'événement de données à la ligne 3 de la liste 5. L'événement de données reflète un message provenant du client appelant vers le serveur via un flux HTTP / 2 établi par le client. le call.write () La méthode à la ligne 4 du listing 5 renvoie un objet JSON au client. L'objet JSON a deux propriétés, jaser et indice. La chaîne attachée au jaser Le champ du message gRPC est converti en majuscules et est assigné au jaser propriété de l'objet JSON. le indice la propriété reçoit la valeur de la variable je. La valeur de je est une valeur qui augmente continuellement. Chaque fois call.write () est invoquée, la valeur de je augmente de un, comme indiqué à la ligne 5 du listing 5 ci-dessus.

le bavardage est destinée à s'exécuter jusqu'à ce que le flux HTTP / 2 soit interrompu. Ainsi, il n'y a AUCUNE invocation de call.end () comme c'est le cas pour le chatter de méthode de diffusion unidirectionnelle.

Maintenant que nous avons couvert les bases de la création d'un serveur gRPC sous Node.js, passons au client.

Codage de l'outil CLI

Afin de travailler avec le serveur que nous avons créé ci-dessus, nous avons besoin d'un client qui peut accéder directement au .proto fichier qui définit l'API gRPC SimpleService. En outre, le client doit pouvoir accéder au serveur gRPC via HTTP / 2. Nous pourrions utiliser un outil tiers tel que BloomRPC pour agir en tant que client. (Voir la figure 2 ci-dessous.)

Figure 2: BloomRPC est un client tiers utile pour interagir avec n'importe quel serveur gRPC

Figure 2: BloomRPC est un client tiers utile pour interagir avec n'importe quel serveur gRPC

À des fins pédagogiques, nous avons pris le temps d'implémenter un client gRPC spécialement conçu pour l'API SimpleService. Le client est un exécutable que vous appelez à partir de la ligne de commande. Il s'appelle sscli. Vous pouvez voir le code complet ici.

Une fois installé, vous pouvez utiliser sscli pour interagir avec l'API gRPC SimpleService. (La figure 1, au début de cet article, est un GIF animé qui illustre l'utilisation du sscli outil de ligne de commande pour appeler bavardage procédure sous l'API gRPC SimpleService.)

Jetons un œil aux détails.

Encapsulation de la logique client gRPC

La logique du client gRPC personnalisé est encapsulée dans la classe JavaScript SimpleServiceClient comme indiqué ci-dessous dans la liste 6. Le SimpleServiceClient class publie des méthodes publiques qui correspondent aux procédures publiées dans l'API SimpleService.

le sscli L'outil de ligne de commande utilise la classe pour exécuter le comportement du client sur le serveur gRPC.

Par exemple, lorsque le sscli l'outil veut appeler le Ajouter() procédure sur le SimpleService, il appellera SimpleServiceClient.add () comme indiqué ci-dessous dans le listing 6:

const SERVER_URL = 'localhost:8080';
const PROTO_PATH = __dirname + '/proto/simple.proto';
const client = new SimpleServiceClient(SERVER_URL, PROTO_PATH);
const numbers = (1,1,1,3);
client.add(numbers, callback); //callback is the name of a function defined previously

Liste 6: Un exemple de création et d'utilisation de la classe JavaScript, SimpleServiceClient

Pour appeler la procédure Divide, sscli appelle la classe SimpleServiceClient.divide (), pour appeler la procédure Multiplier sscli appels SimpleServiceClient.multiply () etc. Nous n'allons pas entrer dans les détails de chaque appel client. Au lieu de cela, nous verrons comment la classe SimpleServiceClient appelle le Blabber () procédure sur l'API SimpleService. Nous choisissons Blabber car c'est un bon exemple de la façon d'implémenter la diffusion bidirectionnelle entre un serveur gRPC et un client gRPC. Nous aborderons les détails de Blabber () dans un instant, mais voyons d'abord comment le client réel qui fait partie de Node.js grpc le package est créé dans la classe SimpleServiceClient.

Création du client gRPC

SimpleServiceClient publie deux paramètres dans le constructeur de la classe. Un paramètre est serverUrl qui est l'URL du serveur gRPC sur le réseau. L'autre paramètre, protoPath, est le chemin exact de l'API gRPC .proto fichier sur disque ou sur le réseau. (Ligne 2, liste 7 ci-dessous.) Le paramètre protoPath peut pointer vers l'emplacement d'une copie d'un .proto fichier utilisé par le serveur, mais le contenu des deux fichiers doit être identique. (Il y a des situations dans lesquelles le .proto les fichiers peuvent différer par leur contenu, mais la description de ces détails dépasse le cadre de cet article.) Dans le cas du projet de démonstration, un script shell personnalisé copie un .proto à partir d'un emplacement unique dans les répertoires du serveur et du client où la génération automatique de code aura lieu.

Le constructeur de SimpleServiceClient utilise le protoLoader objet pour créer les messages et procédures sous-jacents qui seront utilisés par le client. Cela se fait aux lignes 3 à 10 de la liste 6 ci-dessous. (Veuillez noter que le Listing 7 montre des extraits du SimpleServiceClient classe, pas dans son intégralité.)

Le client gRPC est créé à la ligne 15 du listing 7.

Listing 7: Un extrait du code du client gRPC personnalisé, sscli

Liste 7: Un extrait du code du client gRPC personnalisé, sscli

Consommer un flux bidirectionnel entre le serveur et le client

Comme mentionné ci-dessus, SimpleServiceClient est la classe JavaScript qui permet le sscli outil en ligne de commande pour interagir avec un client gRPC sous-jacent via les méthodes de la classe. De plus, comme mentionné ci-dessus, la méthode que nous allons examiner est Blabber () car c'est un bon exemple d'implémentation d'un appel client lié à un flux bidirectionnel entre un client et un serveur.

Le code de la méthode SimpleServiceClient.blabber ({message, count}, rappel) est affiché aux lignes 23 à 58 de la liste 7 ci-dessus.

Le but de SimpleServiceClient.blabber ({message, count}, rappel) est d'appeler le blabber () procédure sur le serveur API gRPC SimpleService. Lorsque le client passe l'appel à blabber (), le serveur renverra à plusieurs reprises la chaîne soumise dans la propriété message de l'objet JSON du premier paramètre. Le nombre de répétitions de la chaîne est indiqué par le compter propriété de l'objet JSON.

Par exemple, l'appel du client …

SimpleServiceClient.blabber({"I like cheese", 5}, callback)

… Enverra la chaîne, "J'aime le fromage"cinq fois au serveur via un flux HTTP / 2. Le serveur renvoie chaque chaîne envoyée par le client au client dans un flux HTTP / 2.

La chose importante à comprendre est que contrairement à la math et ping méthodes définies dans SimpleServiceClient qui sont standard demande/réponse méthodes, les Blabber () La méthode est bidirectionnelle. Cela signifie qu'un client diffuse vers le serveur et que le serveur renvoie également vers le client. C'est comme s'il y avait une connexion continue entre eux. Bien qu'il ne s'agisse que d'un exemple d'application très simple à des fins de démonstration, il appartient aux architectes informatiques et aux développeurs de comprendre quand un tel streaming bidirectionnel est une exigence commerciale pour une application particulière.

Le travail de création du flux bidirectionnel vers le client est effectué à la ligne 28 du listing 7 ci-dessus:

 const stream = this.client.Blabber();

Une fois le flux établi, le SimpleServiceClient.blabber () fonction liée au flux 'Les données'événement comme ça:

stream.on('data', function (response) {
       callback(null,JSON.stringify(response));
});

Le 'Les données«L'événement indique que les données arrivent du serveur. Les données réelles sont représentées dans le réponse paramètre passé à la fonction définie dans le stream.on () gestionnaire d'événements. La fonction de gestionnaire d'événements appelle à son tour la fonction de rappel qui est passée en paramètre à SimpleServiceClient.blabber ({message, count}, rappel). Cela prend en charge les données provenant du flux côté serveur.

L'envoi de données au serveur à partir du client nécessite une certaine ingéniosité de programmation. Cela se fait aux lignes 41 à 57 du listing 7 ci-dessus et que nous avons reproduit ci-dessous dans le listing 8:

Listing 8: Le code pour appeler un flux gRPC continu du client au serveur

Liste 8: Le code pour appeler un flux gRPC continu du client au serveur

Concentrons-nous sur la fonction intervalle() illustré ci-dessus à la ligne 48 du listing 8.

La fonction intervalle() est fourni par un package NPM tiers nommé intervalle-promesse. Le but de intervalle-promesse consiste à exécuter des instructions de programmation à plusieurs reprises comme une promesse Node.js selon un intervalle prédéfini. L'intervalle prédéfini est fourni par le programmeur en tant que paramètre pour l'invocation de la fonction.

Dans le code, vous pouvez voir que intervalle() exécutera la fonction jaser() à la ligne 49 Puis à la ligne 50, il vérifiera que le paramètre count est passé à la classe ' blabber () function n'est pas nulle et que la valeur actuelle de l'itération de l'appel d'intervalle est supérieure au paramètre count. (La valeur de l'itération est injectée automatiquement dans le intervalle() fonction au moment de l’exécution. Si le nombre existe et que l'itération est supérieure à la valeur de la valeur de comptage, le flux client est annulé, amenant effectivement SimpleServiceClient.blabber () à une halte. (Ligne 55) Sinon, intervalle() continue de s'exécuter. Dans ce cas intervalle() est configuré pour s'exécuter toutes les 1000 millisecondes dans le cadre de la intervalle() déclaration de la fonction à la ligne 58.

le jaser() la fonction à la ligne 41 n'est rien de plus qu'un wrapper de la méthode stream.write () qui à son tour envoie un objet JSON au serveur via le flux HTTP / 2 pré-établi. Cet objet JSON contient une valeur pour le message propriété de l'objet. le index stream.write () la propriété est définie sur la valeur actuelle de la variable cnt à la ligne 43. La variable cnt est un compteur incrémental interne avec le blabber () une fonction,

Le résultat est un objet JSON envoyé sur le flux client qui pourrait ressembler à ceci:

{message: "I like cheese", index: 4}

Essentiellement, le client envoie des données au serveur via HTTP / 2 et le serveur répond avec des données via HTTP / 2. Il s'agit du comportement de base d'un échange de streaming bidirectionnel gRPC.

Mettre tous ensemble

Il y a beaucoup d'avantages à utiliser des bibliothèques et des frameworks pour implémenter gRPC, à la fois du côté serveur et du côté client. Pour de nombreuses entreprises, le gain de temps est une justification suffisante. Pourtant, l'utilisation d'un framework préexistant ou d'un ensemble de bibliothèques tierces telles que le gRPC pour les bibliothèques Node.js que nous avons démontré dans cet article nécessite encore du travail. Il y a beaucoup à maîtriser.

Comme nous l'avons mentionné au début de cet article, chaque framework gRPC spécifique à un langage a sa propre façon d'implémenter la spécification gRPC. Il y a beaucoup de détails nuancés qui doivent être compris. Le temps d'adoption d'un cadre variera en fonction de la qualité de la documentation disponible ainsi que de l'étendue et de la qualité du support que vous rencontrerez parmi la variété de communautés de développeurs qui ont germé dans l'espace gRPC.

La mise en œuvre du projet de démonstration SimpleService a pris beaucoup de temps, bien plus qu'un après-midi de recherche et de codage. Une partie du codage a été réalisée en suivant les tutoriels publiés sur grpc.io. D'autres efforts étaient une question d'essais et d'erreurs. Parfois, nous avions besoin de l'aide d'experts d'un être humain vivant. Heureusement, nous avons pu obtenir des conseils d'experts sur le canal gRPC Gitter. Michael Lumish a été particulièrement utile lorsqu'il s'agissait de fournir des informations et des conseils pour mieux comprendre les subtilités de l'implémentation de Node.js. Sa patience est admirable.

Comme vous pouvez le voir, rien qu'à partir du volume d'informations que nous avons fourni dans cet article, se lancer seul et créer une implémentation gRPC complète à partir de zéro serait une entreprise énorme. Il y a de bonnes raisons de faire valoir que cela dépasse les capacités d'un seul développeur, quelle que soit l'extraordinaire sens technique. Le travail peut être amusant, mais vous auriez du mal à justifier l'avantage d'adopter une approche «roll-your-own» compte tenu des dépenses énormes. Il est préférable d'identifier une mise en œuvre de gRPC qui répond aux besoins actuels, puis de mordre la balle pour absorber la courbe d'apprentissage importante. Cela peut prendre du temps, mais c'est loin du temps que vous auriez à investir pour repartir de zéro.

Le gRPC est une technologie importante. L'adoption continue de croître. Les entreprises acceptent la complexité nécessaire pour faire de la technologie un ajout utile et productif à leurs piles technologiques. Espérons que les informations fournies dans cet article vous fourniront une direction ainsi qu'une inspiration pour adopter une implémentation gRPC qui fonctionne pour vous.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *