Arbeiten mit Apache Thrift
1. Überblick
In diesem Artikel erfahren Sie, wie Sie mithilfe des RPC-FrameworksApache Thrift plattformübergreifende Client-Server-Anwendungen entwickeln.
Wir werden abdecken:
-
Definieren von Datentypen und Serviceschnittstellen mit IDL
-
Installation der Bibliothek und Generierung der Quellen für verschiedene Sprachen
-
Implementierung der definierten Schnittstellen in einer bestimmten Sprache
-
Implementieren von Client / Server-Software
Wenn Sie direkt zu Beispielen gehen möchten, fahren Sie direkt mit Abschnitt 5 fort.
2. Apache Thrift
Apache Thrift wurde ursprünglich vom Facebook-Entwicklerteam entwickelt und wird derzeit von Apache verwaltet.
Im Vergleich zuProtocol Buffers, die plattformübergreifende Objektserialisierungs- / Deserialisierungsprozesse verwalten,Thrift mainly focuses on the communication layer between components of your system.
Thrift verwendet eine spezielle Interface Description Language (IDL), um Datentypen und Dienstschnittstellen zu definieren, die als.thrift-Dateien gespeichert und später vom Compiler als Eingabe zum Generieren des Quellcodes von Client- und Serversoftware verwendet werden, die über unterschiedliche Programmierungen kommunizieren Sprachen.
Fügen Sie die folgende Maven-Abhängigkeit hinzu, um Apache Thrift in Ihrem Projekt zu verwenden:
org.apache.thrift
libthrift
0.10.0
Die neueste Version finden Sie inMaven repository.
3. Schnittstelle Beschreibung Sprache
Wie bereits beschrieben, ermöglichtIDL die Definition von Kommunikationsschnittstellen in einer neutralen Sprache. Nachfolgend finden Sie die aktuell unterstützten Typen.
3.1. Basistypen
-
bool - ein boolescher Wert (wahr oder falsch)
-
byte - eine 8-Bit-Ganzzahl mit Vorzeichen
-
i16 - eine 16-Bit-Ganzzahl mit Vorzeichen
-
i32 - eine 32-Bit-Ganzzahl mit Vorzeichen
-
i64 - eine 64-Bit-Ganzzahl mit Vorzeichen
-
double - eine 64-Bit-Gleitkommazahl
-
string - eine Textzeichenfolge, die mit UTF-8-Codierung codiert wurde
3.2. Spezielle Typen
-
binary - eine Folge von nicht codierten Bytes
-
optional - derOptional-Typ von Java 8
3.3. Strukturen
Thriftstructs entsprechen Klassen in OOP-Sprachen, jedoch ohne Vererbung. Einstruct hat eine Reihe stark typisierter Felder, die jeweils einen eindeutigen Namen als Bezeichner haben. Felder können verschiedene Anmerkungen enthalten (numerische Feld-IDs, optionale Standardwerte usw.).
3.4. Behälter
Gebrauchtcontainer sind stark typisierte Container:
-
list - eine geordnete Liste von Elementen
-
set - eine ungeordnete Menge eindeutiger Elemente
-
map<type1,type2> - eine Karte streng eindeutiger Schlüssel zu Werten
Containerelemente können von jedem gültigen Thrift-Typ sein.
3.5. Ausnahmen
Ausnahmen entsprechen funktionalstructs, erben jedoch von den nativen Ausnahmen.
3.6. Dienstleistungen
Services sind Kommunikationsschnittstellen, die mithilfe von Thrift-Typen definiert werden. Sie bestehen aus einer Reihe benannter Funktionen mit jeweils einer Liste von Parametern und einem Rückgabetyp.
4. Quellcode-Generierung
4.1. Sprachunterstützung
Es gibt eine lange Liste der derzeit unterstützten Sprachen:
-
C++
-
C#
-
Go
-
Haskell
-
Java
-
Javascript
-
Node.js
-
Perl
-
PHP
-
Python
-
Ruby
Sie können die vollständige Listehere überprüfen.
4.2. Verwenden der ausführbaren Datei der Bibliothek
Laden Sie einfach dielatest version herunter, erstellen und installieren Sie sie bei Bedarf und verwenden Sie die folgende Syntax:
cd path/to/thrift
thrift -r --gen [LANGUAGE] [FILENAME]
In den oben festgelegten Befehlen ist[LANGUAGE] eine der unterstützten Sprachen und[FILENAME] eine Datei mit IDL-Definition.
Beachten Sie das-r-Flag. Es weist Thrift an, rekursiv Code zu generieren, sobald es feststellt, dass er in einer bestimmten.thrift-Datei enthalten ist.
4.3. Verwenden des Maven Plugins
Fügen Sie das Plugin in die Dateipom.xmlein:
org.apache.thrift.tools
maven-thrift-plugin
0.1.11
path/to/thrift
thrift-sources
generate-sources
compile
Danach führen Sie einfach den folgenden Befehl aus:
mvn clean install
Beachten Sie, dass dieses Plugin keine weitere Wartung mehr benötigt. Bitte besuchen Siethis page für weitere Informationen.
5. Beispiel einer Client-Server-Anwendung
5.1. Thrift-Datei definieren
Schreiben wir einen einfachen Dienst mit Ausnahmen und Strukturen:
namespace cpp com.example.thrift.impl
namespace java com.example.thrift.impl
exception InvalidOperationException {
1: i32 code,
2: string description
}
struct CrossPlatformResource {
1: i32 id,
2: string name,
3: optional string salutation
}
service CrossPlatformService {
CrossPlatformResource get(1:i32 id) throws (1:InvalidOperationException e),
void save(1:CrossPlatformResource resource) throws (1:InvalidOperationException e),
list getList() throws (1:InvalidOperationException e),
bool ping() throws (1:InvalidOperationException e)
}
Wie Sie sehen, ist die Syntax ziemlich einfach und selbsterklärend. Wir definieren eine Reihe von Namespaces (pro Implementierungssprache), einen Ausnahmetyp, eine Struktur und schließlich eine Service-Schnittstelle, die von verschiedenen Komponenten gemeinsam genutzt werden.
Speichern Sie es dann einfach alsservice.thrift-Datei.
5.2. Code kompilieren und generieren
Jetzt ist es Zeit, einen Compiler auszuführen, der den Code für uns generiert:
thrift -r -out generated --gen java /path/to/service.thrift
Wie Sie vielleicht sehen, haben wir ein spezielles Flag-out hinzugefügt, um das Ausgabeverzeichnis für generierte Dateien anzugeben. Wenn Sie keine Fehler erhalten haben, enthält das Verzeichnisgenerated3 Dateien:
-
CrossPlatformResource.java
-
CrossPlatformService.java
-
InvalidOperationException.java
Generieren Sie eine C ++ - Version des Dienstes, indem Sie Folgendes ausführen:
thrift -r -out generated --gen cpp /path/to/service.thrift
Jetzt erhalten wir zwei verschiedene gültige Implementierungen (Java und C ++) der gleichen Service-Schnittstelle.
5.3. Hinzufügen einer Service-Implementierung
Obwohl Thrift den größten Teil der Arbeit für uns erledigt hat, müssen wir noch unsere eigenen Implementierungen derCrossPlatformService schreiben. Dazu müssen wir nur eineCrossPlatformService.Iface-Schnittstelle implementieren:
public class CrossPlatformServiceImpl implements CrossPlatformService.Iface {
@Override
public CrossPlatformResource get(int id)
throws InvalidOperationException, TException {
return new CrossPlatformResource();
}
@Override
public void save(CrossPlatformResource resource)
throws InvalidOperationException, TException {
saveResource();
}
@Override
public List getList()
throws InvalidOperationException, TException {
return Collections.emptyList();
}
@Override
public boolean ping() throws InvalidOperationException, TException {
return true;
}
}
5.4. Server schreiben
Wie bereits erwähnt, möchten wir eine plattformübergreifende Client-Server-Anwendung erstellen, daher benötigen wir einen Server dafür. Das Tolle an Apache Thrift ist, dass es über ein eigenes Client-Server-Kommunikations-Framework verfügt, das die Kommunikation zu einem Kinderspiel macht:
public class CrossPlatformServiceServer {
public void start() throws TTransportException {
TServerTransport serverTransport = new TServerSocket(9090);
server = new TSimpleServer(new TServer.Args(serverTransport)
.processor(new CrossPlatformService.Processor<>(new CrossPlatformServiceImpl())));
System.out.print("Starting the server... ");
server.serve();
System.out.println("done.");
}
public void stop() {
if (server != null && server.isServing()) {
System.out.print("Stopping the server... ");
server.stop();
System.out.println("done.");
}
}
}
Als erstes muss eine Transportschicht mit der Implementierung der Schnittstelle vonTServerTransport(oder genauer gesagt der abstrakten Klasse) definiert werden. Da es sich um einen Server handelt, müssen wir einen Port zum Abhören bereitstellen. Dann müssen wir eineTServer-Instanz definieren und eine der verfügbaren Implementierungen auswählen:
-
TSimpleServer - für einfachen Server
-
TThreadPoolServer - für Multithread-Server
-
TNonblockingServer - für nicht blockierende Multithread-Server
Stellen Sie schließlich eine Prozessorimplementierung für den ausgewählten Server bereit, die bereits von Thrift für uns generiert wurde, d. H. CrossPlatofformService.Processor Klasse.
5.5. Einen Client schreiben
Und hier ist die Implementierung des Kunden:
TTransport transport = new TSocket("localhost", 9090);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
CrossPlatformService.Client client = new CrossPlatformService.Client(protocol);
boolean result = client.ping();
transport.close();
Aus Sicht des Kunden sind die Aktionen ziemlich ähnlich.
Definieren Sie zunächst den Transport und verweisen Sie ihn auf unsere Serverinstanz. Wählen Sie dann das geeignete Protokoll aus. Der einzige Unterschied besteht darin, dass wir hier die Client-Instanz initialisieren, die wiederum bereits von Thrift generiert wurde, d. H. CrossPlatformService.Client Klasse.
Da es auf den Dateidefinitionen von.thriftbasiert, können wir die dort beschriebenen Methoden direkt aufrufen. In diesem Beispiel führtclient.ping() einen Remote-Anruf an den Server durch, der mittrue antwortet.
6. Fazit
In diesem Artikel haben wir Ihnen die grundlegenden Konzepte und Schritte für die Arbeit mit Apache Thrift gezeigt und gezeigt, wie Sie ein Arbeitsbeispiel erstellen, das die Thrift-Bibliothek verwendet.
Wie üblich sind alle Beispiele immer inthe GitHub repository zu finden.