Etwas Eigenwerbung: Ich arbeite bei WI (http://wi.co/). Wir verändern die Art und Weise, wie Menschen außerhalb des Silicon Valley arbeiten. Wenn du interessiert bist, schau doch mal auf unserer Karriereseite vorbei (http://wi.co/careers) oder schick mir eine E-Mail an [email protected]
Über Thrift: Falls Sie mit RPC oder Thrift noch nicht vertraut sind, sollten Sie vielleicht einen Blick auf https://thrift.apache.org/ werfen.
Ein Problem, von dem ich gehört habe, lautet: „Hey, wir stellen unsere Thrift-APIs Drittanbietern zur Verfügung und möchten, dass sie einfach zu bedienen sind.“ Nun gibt es zwei Möglichkeiten:
- Stellen Sie die Thrift-Endpunkte bereit, schulen Sie Ihre API-Nutzer im Umgang mit Thrift und helfen Sie ihnen bei der Fehlerbehebung.
- Sie pflegen eine Bibliothek, die als Wrapper für die verschiedenen Thrift-Dienste für jede Sprache bzw. Plattform dient, die Sie unterstützen möchten.
- Erstellen Sie eine Möglichkeit, manuell zwischen lesbares JSON in Thrift und umgekehrt zu entwickeln und diese für jede einzelne Struktur, jeden Dienst und jede Funktion zu pflegen.
Wenn Ihnen diese Optionen nicht zusagen, haben Sie recht – sie können ziemlich aufwendig sein. Aber gibt es einen anderen Weg?
In meinem folgenden Artikel werde ich die folgende einfache Thrift-Datei verwenden:
Nun unterstützt Thrift zwar ein JSONProtocol , das Daten als JSON zwischen Client und Server überträgt (das nutzen wir für unser Web-Frontend). Ein Blick auf die gesendeten Daten zeigt jedoch, dass es nicht möglich sein wird, diese für Dritte zugänglich zu machen:
Und das gilt für einen ganz einfachen Aufruf : login(E-Mail, Passwort).
Das Thrift-JSON enthält eine ganze Reihe von Fachbegriffen, mit denen der genaue Aufruf analysiert wird, wie beispielsweise die Typen der einzelnen Argumente/Felder, die Länge von Arrays/Sets, die Schlüsselnummer jedes Feldes in einer Struktur usw.
Also haben wir eine Methode entwickelt, um menschenlesbares JSON in Thrift zu konvertieren, ohne dass:
- Eine ganze Menge Fachjargon hinzufügen
- Wartungsarbeiten durchführen. Alle Änderungen an den Thrift-Definitionen sollten automatisch verfügbar sein.
Ein Beispiel für denselben Aufruf mit der neuen Methode:
Viel besser lesbar!
Das Format ist einfach. Die Werte des Schlüssels „method“ sollten genau dem Namen der Methode in der Thrift-Definition entsprechen. Das Objekt „arguments“ enthält die Liste der Argumente. Die Schlüssel innerhalb des Objekts „arguments“ entsprechen wiederum den Namen der Funktionsparameter in der Thrift-Definition.
Hier ist ein Beispiel für eine Antwort:
Ein Beispiel für eine in der API definierte Ausnahme, die ausgelöst wurde:
Beachten Sie, dass es auch problemlos mit Structs (und in Structs eingebetteten Structs) umgehen kann. Oben ist „currentUser“ ein Struct. In JSON handelt es sich dabei einfach um ein JSON-Objekt, dessen Schlüssel mit den Feldnamen in der Thrift-Struct-Definition übereinstimmen.
Außerdem ist „err“ (die Ausnahme) ebenfalls eine Struktur, da Ausnahmen in Thrift einfach eine besondere Art von Strukturen sind.
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.
Es gibt einen JSON-Generator für Thrift, der alle Metadaten des
- Dienste: Name, Funktionsübersicht
- Funktionen: Name, Argumentliste
- Strukturen: Name, Felder sowie deren Namen und Typen
Nachfolgend finden Sie ein Beispiel für die generierten Metadaten der oben genannten Thrift-Datei.
Ich habe diese Metadaten in einem neuen Protokoll verwendet . Ein Protokoll ist die Art und Weise, wie Thrift Daten marshalled und un-marshalled. Das Problem ist, dass Protokolle in Thrift stark typisiert sind. Es muss in der Lage sein, den genauen Typ des Feldes (oder den Elementtyp des Arrays bzw. den Schlüssel- und Werttyp der Map) sowie weitere Informationen wie die Größe der Map oder des Arrays weiterzugeben. Deshalb enthält das Thrift-JSONProtocol so viel Fachjargon. Es überträgt genau diese Informationen.
Dieses neue Protokoll, das „HumanReadableJsonProtocol“, nutzt das vom Client gesendete JSON zusammen mit den Metadaten des Thrift-JSON-Generators, um genau zu ermitteln, welche Funktion aufgerufen wurde, welche Argumente übermittelt wurden und um welche Typen es sich dabei genau handelt.
Im obigen Aufruf werden beispielsweise zunächst die Metadaten für die Anmeldemethode abgerufen. Anschließend wird für jeden Schlüssel im „arguments“-Objektdes Client-JSONs der zugehörige Schlüssel im „arguments“-Array der Metadaten gesucht. Je nach Typ wird dieser analysiert (handelt es sich um eine Struktur, eine Liste oder eine Map, wird der Vorgang rekursiv fortgesetzt, bis ein Basistyp erreicht wird – int, string, boolean, double usw.). In diesem Fall wird beispielsweise in den Metadaten nach einem Objekt gesucht, dessenWert für „name“ „email“ lautet; es wird festgestellt, dass dessen Typ „String“ ist, und anschließend überprüft, ob der Wert von„email“ im „arguments“-Objekt des Client-JSON ebenfalls ein „String“ ist. Ähnlich verhält es sich mit„password“.
Dieses neue „HumanReadableJsonProtocol“ ist nach wie vor stark typisiert. Wenn Sie einen Schlüssel senden, dessen Wert nicht korrekt dem in den Metadaten definierten Typ entspricht, wird ein Fehler ausgelöst.
Hier ist eine Fehlermeldung, die in einem solchen Fall ausgegeben wird, als ich versucht habe, anstelle einer Zeichenkette eine Zahl in das Passwortfeld einzugeben:
Beachten Sie, dass dieses JSON einen „exception“-Schlüssel enthält, während die oben genannten einen „result“-Schlüssel hatten, auf den entweder „success“ oder „error“ folgte . Dies entspricht der Art und Weise, wie Thrift die verschiedenen Antworttypen behandelt. Man erhält entweder ein „Result“ oder eine „Exception“ zurück. „Result“ bedeutet , dass der Aufruf erfolgreich war und keine anderen Fehler als die in der API definierten Fehler (die in der Methodensignatur aufgeführten) ausgelöst wurden. Daher verfügt „Result“ über zwei Felder: eines für „success“, das das erfolgreiche Ergebnis des Aufrufs enthält, und eines für „error“, das den in der API definierten Fehler enthält, der ausgelöst wurde. „Exception“ enthält alle anderen Fehler (einschließlich Thrift-Fehler wie beschädigte Daten, nicht parsbare Daten, falsche Typen usw.).
Da es sich lediglich um ein Protokoll handelt (eine Methode zum Marshaling und Unmarshaling von Daten), kümmert sich der von Thrift generierte Code, der dieses Protokoll nutzt, automatisch um Aspekte wie erforderliche oder optionale Felder.
Wenn die Anfrage beispielsweise den Content-Type „application/json“ hat , müssen Sie sie lediglich mit dem „HumanReadableJsonProtocol“ analysieren; andernfalls verwenden Sie das von Ihnen üblicherweise verwendete Standardprotokoll. Außerdem müssen Sie das Verzeichnis angeben, in dem sich die generierten JSON-Metadaten befinden.
Schließlich werden alle neuen Änderungen an den Thrift-Definitionen automatisch übernommen (sofern Sie das JSON ebenfalls mit dem JSON-Generator erstellen).
Hier ist der Quellcode zum Projekt: HumanReadableJsonProtocol
Falls Sie den Code dafür haben möchten oder dabei helfen möchten, den Code auf weitere Sprachen auszuweiten und Tests dafür zu schreiben, kontaktieren Sie mich bitte.
HumanReadableJsonProtocol-Codeausschnitt in Ruby
Hier ist ein Ausschnitt aus dem Code, der die Analyse in Ruby durchführt:
Noch mal eine kleine Eigenwerbung: Ich arbeite bei WI (http://wi.co/). Wir verändern die Art und Weise, wie Menschen außerhalb des Silicon Valley arbeiten. Wenn du Interesse hast, schau doch mal auf unserer Karriereseite vorbei (http://wi.co/careers) oder schickt mir eine E-Mail an [email protected]











