Petite pub : je travaille chez WI (http://wi.co/). Nous révolutionnons la façon dont les gens travaillent en dehors de la Silicon Valley. Si cela vous intéresse, n'hésitez pas à consulter notre page « Carrières » (http://wi.co/careers) ou envoyez-moi un e-mail à l'adresse [email protected]

À propos de Thrift : si vous ne connaissez pas RPC ou Thrift, vous pouvez consulter la page https://thrift.apache.org/

Bon, l’un des problèmes dont j’ai entendu parler est le suivant : « Bon, on met nos API Thrift à la disposition de fournisseurs tiers, et il faut qu’elles soient faciles à utiliser. » Maintenant, vous avez le choix entre :

  1. Mettez à disposition les points de terminaison Thrift, formez les utilisateurs de votre API à l'utilisation de Thrift et aidez-les à résoudre d'éventuels problèmes.
  2. Vous gérez une bibliothèque qui sert d'enveloppe aux différents services Thrift pour chaque langage et chaque plateforme que vous souhaitez prendre en charge.
  3. Mettre en place un moyen de convertir manuellement entre le format JSON lisible par l'utilisateur en Thrift et inversement, et assurez sa maintenance pour chaque structure, service et fonction.

Si ces options ne vous semblent pas très attrayantes, vous avez raison : elles peuvent demander beaucoup de travail. Mais existe-t-il une autre solution ?

Dans l'article ci-dessous, j'utiliserai le fichier Thrift simple suivant :

À présent, Thrift prend en charge un JSONProtocol qui transmet les données au format JSON entre le client et le serveur (c’est ce que nous utilisons pour notre interface web). Cependant, il suffit de jeter un œil aux données envoyées pour comprendre qu’il ne sera pas possible de les exposer à des tiers :

Et cela concerne un appel très simple : login(email, mot de passe).

Le JSON Thrift utilise tout un vocabulaire spécifique pour analyser en détail l'appel, notamment les types de chaque argument ou champ, la longueur des tableaux ou des ensembles, le numéro de clé de chaque champ dans une structure, etc.

Nous avons donc trouvé un moyen de convertir du JSON lisible par l'utilisateur en Thrift sans :

  1. Ajouter tout un tas de termes techniques
  2. Effectuer des opérations de maintenance. Toute modification apportée aux définitions de Thrift devrait être automatiquement prise en compte.

Voici un exemple de ce même appel utilisant la nouvelle méthode :

C'est bien plus lisible !

Le format est simple. Les valeurs de la clé « method » doivent correspondre exactement au nom de la méthode tel qu'il apparaît dans la définition Thrift. L'objet « arguments » contient la liste des arguments. Les clés de cet objet correspondent elles aussi aux noms des paramètres de la fonction tels qu'ils apparaissent dans la définition Thrift.

Voici un exemple de réponse :

Exemple d'exception définie par l'API qui a été levée :

Notez qu'il prend également facilement en charge les structures (et les structures imbriquées les unes dans les autres). Ci-dessus, ` currentUser` est une structure. En JSON, il s'agit simplement d'un objet JSON dont les clés correspondent aux noms des champs de la définition de la structure Thrift.

Par ailleurs, « err » (l'exception) est également une structure, car dans Thrift, les exceptions ne sont qu'un type particulier de structures.

Furthermore, note that the success object itself is a struct. Its is an auto generated struct whose name is usually <MethodName>_result (in this case login_result). You can see it if you ever peek into the generated code for any other language. It has two fields: result for a successful call and err for any api defined error that was thrown.

Similarly, the arguments is also an auto generated Struct, usually call <MethodName>_args (in this case login_args). Its fields are simply the function arguments. Thus, this format follows very closely to how actual Thrift works.

Il existe un générateur JSON pour Thrift, qui génère toutes les métadonnées du

  1. Services : nom, liste des fonctions
  2. Fonctions : nom, liste d'arguments
  3. Structures : nom, champs avec leurs noms et leurs types

Vous trouverez ci-dessous un exemple des métadonnées générées pour le fichier Thrift ci-dessus.

J'ai utilisé ces métadonnées dans un nouveau protocole. Un protocole définit la manière dont Thrift effectue le marshalling et le démarshalling des données. Le problème est que les protocoles dans Thrift sont fortement typés. Ils doivent pouvoir transmettre le type exact du champ (ou le type d'élément du tableau, ou encore les types de clé et de valeur de la carte), ainsi que d'autres informations telles que la taille de la carte ou du tableau. C'est pourquoi le JSONProtocol de Thrift contient autant de jargon technique. Il véhicule précisément ces informations.

Ce nouveau protocole, le « HumanReadableJsonProtocol », utilise le JSON envoyé par le client ainsi que les métadonnées fournies par le générateur JSON de Thrift pour déterminer précisément quelle fonction a été appelée, quels arguments ont été transmis et quels sont leurs types exacts.

Par exemple, dans l’appel ci-dessus, il recherchera d’abord les métadonnées correspondant à la méthode de connexion. Ensuite, pour chaque clé de l’objet `arguments`dans le JSON client, il trouvera la clé associée dans le tableau `arguments` des métadonnées. En fonction du type, il l’analysera (s’il s’agit d’une structure, d’une liste ou d’une carte, il continuera à récurer jusqu’à atteindre un type de base — int, string, boolean, double, etc.). Par exemple, dans ce cas, il recherchera dans les métadonnées un objet dontla valeur « name » est «email », constatera que son type est String, puis vérifiera que la valeur de «email » dans l’objet `arguments` du JSON client est également de type String. Il en va de même pour« password ».

Ce nouveau protocole `HumanReadableJsonProtocol` reste fortement typé. Si vous envoyez une clé dont la valeur ne correspond pas correctement au type défini dans les métadonnées, une erreur sera générée.

Voici l'erreur qui s'affiche dans ce cas précis, lorsque j'ai essayé de saisir un nombre au lieu d'une chaîne de caractères dans le champ « mot de passe » :

Notez que ce JSON comporte une clé « exception », alors que les exemples précédents comportaient une clé « result » suivie soit de « success », soit de « error ». Ce fonctionnement est similaire à la manière dont Thrift traite les différents types de réponse. On obtient soit un « Result », soit une « Exception ». « Result » signifie que l’appel a abouti et qu’aucune erreur autre que celles définies par l’API (celles figurant dans la signature de la méthode) n’a été levée. Ainsi, « Result » comporte deux champs : l’un pour le succès, qui contient le résultat positif de l’appel, et l’autre pour l’erreur, qui contient l’erreur définie par l’API qui a été levée. « Exception » contient toute autre erreur (y compris les erreurs Thrift telles que des données corrompues, l’impossibilité d’analyser les données, des types incorrects, etc.).

Comme il s'agit simplement d'un protocole (une méthode de sérialisation/désérialisation des données), le code généré par Thrift qui l'utilise gérera automatiquement des aspects tels que les champs obligatoires ou facultatifs.

Ainsi, par exemple, si la requête a un type de contenu « application/json », il vous suffit d'utiliser le protocole `HumanReadableJsonProtocol` pour l'analyser ; sinon, utilisez le protocole standard de votre choix. Vous devrez également indiquer le répertoire dans lequel se trouvent les métadonnées JSON générées.

Enfin, il intègre automatiquement toutes les nouvelles modifications apportées aux définitions Thrift (à condition que vous génériez également le JSON à l'aide du générateur JSON).

Voici le code source du projet : HumanReadableJsonProtocol

Si vous souhaitez obtenir le code de ce projet, ou si vous souhaitez contribuer à son extension à d'autres langues et à la rédaction de tests, n'hésitez pas à me contacter.

Extrait de code « HumanReadableJsonProtocol » en Ruby

Voici un extrait du code qui effectue l'analyse en Ruby :


Encore un peu d'autopromotion : je travaille chez WI (http://wi.co/). Nous révolutionnons la façon dont les gens travaillent en dehors de la Silicon Valley. Si cela vous intéresse, jetez un œil à notre page « Carrières » (http://wi.co/careers) ou envoyez-moi un e-mail à l'adresse [email protected]

Merci à Adam Neary.