1. 概要

この記事では、 ApacheThriftと呼ばれるRPCフレームワークを使用してクロスプラットフォームのクライアントサーバーアプリケーションを開発する方法を説明します。

カバーします:

  • IDLを使用したデータ型とサービスインターフェイスの定義
  • ライブラリをインストールし、さまざまな言語のソースを生成する
  • 定義されたインターフェースを特定の言語で実装する
  • クライアント/サーバーソフトウェアの実装

例に直接進みたい場合は、セクション5に進んでください。

2. ApacheThrift

Apache Thriftは元々Facebook開発チームによって開発され、現在はApacheによって保守されています。

クロスプラットフォームオブジェクトのシリアル化/逆シリアル化プロセスを管理するProtocolBuffers と比較して、Thriftは主にシステムのコンポーネント間の通信レイヤーに焦点を当てています。

Thriftは、特別なインターフェイス記述言語(IDL)を使用して、 .thrift ファイルとして保存され、後で通信するクライアントおよびサーバーソフトウェアのソースコードを生成するためのコンパイラーによる入力として使用されるデータタイプとサービスインターフェイスを定義します。さまざまなプログラミング言語で。

プロジェクトでApacheThriftを使用するには、次のMaven依存関係を追加します。

<dependency>
    <groupId>org.apache.thrift</groupId>
    <artifactId>libthrift</artifactId>
    <version>0.10.0</version>
</dependency>

最新バージョンはMavenリポジトリにあります。

3. インターフェイス記述言語

すでに説明したように、 IDL を使用すると、中立的な言語で通信インターフェイスを定義できます。 以下に、現在サポートされているタイプを示します。

3.1. 基本タイプ

  • bool –ブール値(trueまたはfalse)
  • byte –8ビットの符号付き整数
  • i16 –16ビットの符号付き整数
  • i32 –32ビットの符号付き整数
  • i64 –64ビットの符号付き整数
  • double –64ビット浮動小数点数
  • string –UTF-8エンコーディングを使用してエンコードされたテキスト文字列

3.2. 特殊タイプ

  • binary –エンコードされていないバイトのシーケンス
  • オプション–Java8のオプションタイプ

3.3. 構造体

Thrift structs は、OOP言語のクラスと同等ですが、継承はありません。 struct には、厳密に型指定されたフィールドのセットがあり、それぞれが識別子として一意の名前を持っています。 フィールドにはさまざまな注釈(数値フィールドID、オプションのデフォルト値など)を付けることができます。

3.4. コンテナ

倹約コンテナは強く型付けされたコンテナです:

  • list –要素の順序付きリスト
  • set –順序付けされていない一意の要素のセット
  • 地図 –値に対する厳密に一意のキーのマップ

コンテナ要素は、任意の有効なThriftタイプにすることができます。

3.5. 例外

例外は、ネイティブの例外から継承することを除いて、機能的にstructsと同等です。

3.6. サービス

サービスは、実際にはThriftタイプを使用して定義された通信インターフェースです。 これらは名前付き関数のセットで構成され、それぞれにパラメーターのリストと戻り値のタイプがあります。

4. ソースコード生成

4.1. 言語サポート

現在サポートされている言語の長いリストがあります:

  • C ++
  • C#
  • 行け
  • Haskell
  • Java
  • Javascript
  • Node.js
  • Perl
  • PHP
  • Python
  • ルビー

完全なリストはここで確認できます。

4.2. ライブラリの実行可能ファイルの使用

最新バージョンをダウンロードし、必要に応じてビルドしてインストールし、次の構文を使用するだけです。

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

上記のコマンドで、 [LANGUAGE] はサポートされている言語の1つであり、[FILENAME]はIDL定義のファイルです。

-rフラグに注意してください。 特定の.thriftファイルに含まれていることに気付いたら、Thriftにコードを再帰的に生成するように指示します。

4.3. Mavenプラグインの使用

pom.xmlファイルにプラグインを追加します。

<plugin>
   <groupId>org.apache.thrift.tools</groupId>
   <artifactId>maven-thrift-plugin</artifactId>
   <version>0.1.11</version>
   <configuration>
      <thriftExecutable>path/to/thrift</thriftExecutable>
   </configuration>
   <executions>
      <execution>
         <id>thrift-sources</id>
         <phase>generate-sources</phase>
         <goals>
            <goal>compile</goal>
         </goals>
      </execution>
   </executions>
</plugin>

その後、次のコマンドを実行します。

mvn clean install

このプラグインはこれ以上メンテナンスされないことに注意してください。 詳細については、このページをご覧ください。

5. クライアントサーバーアプリケーションの例

5.1. スリフトファイルの定義

例外と構造を含むいくつかの簡単なサービスを書いてみましょう。

namespace cpp com.baeldung.thrift.impl
namespace java com.baeldung.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 <CrossPlatformResource> getList() throws (1:InvalidOperationException e),

    bool ping() throws (1:InvalidOperationException e)
}

ご覧のとおり、構文は非常に単純で自明です。 名前のセット(実装言語ごと)、例外タイプ、構造体、そして最後に、さまざまなコンポーネント間で共有されるサービスインターフェイスを定義します。

次に、それをservice.thriftファイルとして保存します。

5.2. コードのコンパイルと生成

次に、コードを生成するコンパイラを実行します。

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

ご覧のとおり、生成されたファイルの出力ディレクトリを指定するために、特別なフラグ-outを追加しました。 エラーが発生しなかった場合、生成されたディレクトリには次の3つのファイルが含まれます。

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

次のコマンドを実行して、C++バージョンのサービスを生成してみましょう。

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

これで、同じサービスインターフェイスの2つの異なる有効な実装(JavaとC ++)を取得できます。

5.3. サービス実装の追加

Thriftがほとんどの作業を行ってくれましたが、それでもCrossPlatformServiceの独自の実装を作成する必要があります。 これを行うには、CrossPlatformService.Ifaceインターフェイスを実装する必要があります。

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<CrossPlatformResource> getList() 
      throws InvalidOperationException, TException {
        return Collections.emptyList();
    }

    @Override
    public boolean ping() throws InvalidOperationException, TException {
        return true;
    }
}

5.4. サーバーの作成

すでに述べたように、クロスプラットフォームのクライアントサーバーアプリケーションを構築したいので、そのためのサーバーが必要です。 Apache Thriftの優れている点は、独自のクライアント/サーバー通信フレームワークを備えていることです。これにより、通信が簡単になります。

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.");
        }
    }
}

まず、 TServerTransport インターフェイス(より正確には抽象クラス)を実装してトランスポート層を定義します。 サーバーについて話しているので、リッスンするポートを提供する必要があります。 次に、 TServer インスタンスを定義し、使用可能な実装の1つを選択する必要があります。

  • TSimpleServer –シンプルなサーバー用
  • TThreadPoolServer –マルチスレッドサーバー用
  • TNonblockingServer –ノンブロッキングマルチスレッドサーバー用

そして最後に、Thriftによってすでに生成されている選択されたサーバーのプロセッサ実装を提供します。 CrossPlatofformService.Processorクラス。

5.5. クライアントを書く

そして、これがクライアントの実装です。

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();

クライアントの観点からは、アクションは非常に似ています。

まず、トランスポートを定義し、それをサーバーインスタンスにポイントしてから、適切なプロトコルを選択します。 唯一の違いは、ここでも、Thriftによってすでに生成されたクライアントインスタンスを初期化することです。 CrossPlatformService.Clientクラス。

.thrift ファイル定義に基づいているため、そこで説明されているメソッドを直接呼び出すことができます。 この特定の例では、 client.ping()は、trueで応答するサーバーへのリモート呼び出しを行います。

6. 結論

この記事では、Apache Thriftを使用する際の基本的な概念と手順を示し、Thriftライブラリーを利用する実用的な例を作成する方法を示しました。

いつものように、すべての例は常にGitHubリポジトリにあります。