Werken met Apache Thrift

1. Overzicht

In dit artikel zullen we ontdekken hoe we platformonafhankelijke client-servertoepassingen kunnen ontwikkelen met behulp van het RPC-framework genaamd Apache Thrift.

We behandelen:

  • Datatypes en service-interfaces definiëren met IDL
  • De bibliotheek installeren en de bronnen voor verschillende talen genereren
  • Implementatie van de gedefinieerde interfaces in een bepaalde taal
  • Implementeren van client / server-software

Als je direct naar voorbeelden wilt gaan, ga dan direct naar sectie 5.

2. Apache Thrift

Apache Thrift is oorspronkelijk ontwikkeld door het ontwikkelingsteam van Facebook en wordt momenteel onderhouden door Apache.

In vergelijking met protocolbuffers, die platformonafhankelijke objectserialisering / deserialisatieprocessen beheren, Thrift richt zich vooral op de communicatielaag tussen componenten van uw systeem.

Thrift gebruikt een speciale Interface Description Language (IDL) om gegevenstypen en service-interfaces te definiëren die worden opgeslagen als .spaarzaamheid bestanden en later gebruikt als invoer door de compiler voor het genereren van de broncode van client- en serversoftware die communiceren via verschillende programmeertalen.

Om Apache Thrift in uw project te gebruiken, voegt u deze Maven-afhankelijkheid toe:

 org.apache.thrift libthrift 0.10.0 

Je kunt de nieuwste versie vinden in de Maven-repository.

3. Interface Beschrijving Taal

Zoals reeds beschreven, maakt IDL het mogelijk om communicatie-interfaces in een neutrale taal te definiëren. Hieronder vindt u de momenteel ondersteunde typen.

3.1. Basistypen

  • bool - een booleaanse waarde (true of false)
  • byte - een 8-bits geheel getal met teken
  • i16 - een 16-bits geheel getal met teken
  • i32 - een 32-bits geheel getal met teken
  • i64 - een 64-bits geheel getal met teken
  • dubbele - een 64-bits drijvende-kommagetal
  • draad - een tekstreeks gecodeerd met UTF-8-codering

3.2. Speciale soorten

  • binair - een reeks niet-gecodeerde bytes
  • optioneel - een Java 8's Optioneel type

3.3. Structs

Spaarzaamheid structs zijn het equivalent van klassen in OOP-talen, maar zonder overerving. EEN struct heeft een reeks sterk getypte velden, elk met een unieke naam als identificatie. Velden kunnen verschillende annotaties hebben (numerieke veld-ID's, optionele standaardwaarden, enz.).

3.4. Containers

Kringloopcontainers zijn sterk getypeerde containers:

  • lijst - een geordende lijst met elementen
  • set - een ongeordende set unieke elementen
  • kaart - een kaart met strikt unieke sleutels tot waarden

Containerelementen kunnen van elk geldig Thrift-type zijn.

3.5. Uitzonderingen

Uitzonderingen zijn functioneel gelijk aan structs, behalve dat ze erven van de inheemse uitzonderingen.

3.6. Diensten

Services zijn eigenlijk communicatie-interfaces die zijn gedefinieerd met behulp van Thrift-typen. Ze bestaan ​​uit een set benoemde functies, elk met een lijst met parameters en een retourtype.

4. Genereren van broncodes

4.1. Taalondersteuning

Er is een lange lijst met momenteel ondersteunde talen:

  • C ++
  • C #
  • Gaan
  • Haskell
  • Java
  • Javascript
  • Node.js
  • Perl
  • Php
  • Python
  • Robijn

Je kunt de volledige lijst hier bekijken.

4.2. Met behulp van het uitvoerbare bestand van de bibliotheek

Download gewoon de nieuwste versie, bouw en installeer deze indien nodig, en gebruik de volgende syntaxis:

cd path / to / thrift thrift -r --gen [LANGUAGE] [FILENAME]

In de bovenstaande opdrachten, [TAAL] is een van de ondersteunde talen en [BESTANDSNAAM] is een bestand met IDL-definitie.

Merk op -r vlag. Het vertelt Thrift om recursief code te genereren zodra het opmerkt dat een gegeven is opgenomen .spaarzaamheid het dossier.

4.3. Maven-plug-in gebruiken

Voeg de plug-in toe aan uw pom.xml het dossier:

 org.apache.thrift.tools maven-thrift-plugin 0.1.11 path / to / thrift thrift-sources genereren-bronnen compileren 

Voer daarna de volgende opdracht uit:

mvn schone installatie

Merk op dat deze plug-in geen verder onderhoud meer heeft. Bezoek deze pagina voor meer informatie.

5. Voorbeeld van een Client-Server-applicatie

5.1. Thrift-bestand definiëren

Laten we een eenvoudige service schrijven met uitzonderingen en structuren:

namespace cpp com.baeldung.thrift.impl namespace java com.baeldung.thrift.impl uitzondering InvalidOperationException {1: i32-code, 2: stringbeschrijving} struct CrossPlatformResource {1: i32 id, 2: stringnaam, 3: optionele stringaanhef} service CrossPlatformService {CrossPlatformResource get (1: i32 id) worpen (1: InvalidOperationException e), void save (1: CrossPlatformResource resource) worpen (1: InvalidOperationException e), lijst getList () worpen (1: InvalidOperationException e), bool ping ( ) gooit (1: InvalidOperationException e)}

Zoals u kunt zien, is de syntaxis vrij eenvoudig en spreekt voor zich. We definiëren een set naamruimten (per implementatietaal), een uitzonderingstype, een struct en tot slot een service-interface die over verschillende componenten wordt gedeeld.

Bewaar het dan gewoon als een service.thrift het dossier.

5.2. Een code samenstellen en genereren

Nu is het tijd om een ​​compiler uit te voeren die de code voor ons zal genereren:

thrift -r -out gegenereerd --gen java /path/to/service.thrift

Zoals je misschien ziet, hebben we een speciale vlag toegevoegd -uit om de uitvoermap voor gegenereerde bestanden op te geven. Als u geen foutmeldingen heeft gekregen, kan het gegenereerd directory bevat 3 bestanden:

  • CrossPlatformResource.java
  • CrossPlatformService.java
  • InvalidOperationException.java

Laten we een C ++ -versie van de service genereren door het volgende uit te voeren:

thrift -r -out gegenereerd --gen cpp /path/to/service.thrift

Nu krijgen we 2 verschillende geldige implementaties (Java en C ++) van dezelfde service-interface.

5.3. Een service-implementatie toevoegen

Hoewel Thrift het meeste werk voor ons heeft gedaan, moeten we nog steeds onze eigen implementaties van het CrossPlatformService. Om dat te doen, hoeven we alleen maar een CrossPlatformService.Iface koppel:

openbare klasse CrossPlatformServiceImpl implementeert CrossPlatformService.Iface {@Override openbare CrossPlatformResource get (int id) gooit InvalidOperationException, TException {retourneer nieuwe CrossPlatformResource (); } @Override public void save (CrossPlatformResource resource) gooit InvalidOperationException, TException {saveResource (); } @Override openbare lijst getList () gooit InvalidOperationException, TException {return Collections.emptyList (); } @Override openbare booleaanse ping () gooit InvalidOperationException, TException {return true; }}

5.4. Een server schrijven

Zoals we al zeiden, we willen een platformonafhankelijke client-servertoepassing bouwen, dus we hebben er een server voor nodig. Het mooie van Apache Thrift is dat het zijn eigen client-server communicatieraamwerk heeft, waardoor communicatie een fluitje van een cent wordt:

openbare klasse CrossPlatformServiceServer {public void start () gooit TTransportException {TServerTransport serverTransport = nieuwe TServerSocket (9090); server = nieuwe TSimpleServer (nieuwe TServer.Args (serverTransport) .processor (nieuwe CrossPlatformService.Processor (nieuwe CrossPlatformServiceImpl ()))); System.out.print ("De server starten ..."); server.serve (); System.out.println ("klaar."); } public void stop () {if (server! = null && server.isServing ()) {System.out.print ("De server stoppen ..."); server.stop (); System.out.println ("klaar."); }}} 

Het eerste is om een ​​transportlaag te definiëren met de implementatie van TServerTransport interface (of abstracte klasse, om precies te zijn). Omdat we het over een server hebben, moeten we een poort bieden om naar te luisteren. Dan moeten we een TServer instantie en kies een van de beschikbare implementaties:

  • TSimpleServer - voor eenvoudige server
  • TThreadPoolServer - voor multi-threaded server
  • TNonblockingServer - voor niet-blokkerende multi-threaded server

En tot slot, zorg voor een processorimplementatie voor de gekozen server die al voor ons is gegenereerd door Thrift, d.w.z. CrossPlatofformService.Processor klasse.

5.5. Een klant schrijven

En hier is de implementatie van de klant:

TTransport transport = nieuwe TSocket ("localhost", 9090); transport.open (); TProtocol protocol = nieuw TBinaryProtocol (transport); CrossPlatformService.Client client = nieuwe CrossPlatformService.Client (protocol); booleaans resultaat = client.ping (); transport.close ();

Vanuit het perspectief van de klant zijn de acties redelijk vergelijkbaar.

Definieer allereerst het transport en wijs het naar onze serverinstantie, en kies vervolgens het geschikte protocol. Het enige verschil is dat we hier de clientinstantie initialiseren die, nogmaals, al werd gegenereerd door Thrift, d.w.z. CrossPlatformService.Client klasse.

Omdat het is gebaseerd op .spaarzaamheid bestandsdefinities kunnen we direct de methoden aanroepen die daar worden beschreven. In dit specifieke voorbeeld client.ping () zal een externe oproep doen naar de server die zal reageren met waar.

6. Conclusie

In dit artikel hebben we je de basisconcepten en stappen laten zien bij het werken met Apache Thrift, en we hebben laten zien hoe je een werkend voorbeeld kunt maken dat gebruikmaakt van de Thrift-bibliotheek.

Zoals gewoonlijk zijn alle voorbeelden altijd te vinden in de GitHub-repository.


$config[zx-auto] not found$config[zx-overlay] not found