Apache Thrift RPCサーバー。 Friends C ++およびJava

こんにちは同僚。

このトピックでは、Thriftを自分の工芸品にすばやく固定する方法について説明します。

Thriftは、システムコンポーネント間のプロセス間通信を整理するための技術です。 Facebookのどこかで開発されました。 バイナリプロトコルでRPCサービスを作成するための言語間フレームワークです。 このソリューションを使用すると、異なる言語C#、C ++、Delphi、Erlang、Go、Java、PHP、Python、Rubyなどで記述されたコンポーネントを「友達にする」ことができます。 サービスおよびデータ署名の記述は、特別なIDL言語を使用して実行されます。 このテクノロジーは、本質的にはCOMと似ていますが、コンポーネント登録によるこのすべてのバインディングはありません。 また、COMはWindows専用のテクノロジーであり、Thriftはクロスプラットフォームであることを忘れないでください。



一般的に、私は実験して、ネイティブC ++コードの生産性が少し上がることを期待して、JavaからC ++への負荷計算ロジックの一部を抽出し、RESTよりも高速であることを期待して、Thrift RPCを試してみることにしました。

あるべきことに、タンバリンと熊手がいくつかありました!



したがって、最初に次のすべてを配置する必要があります。

1.すべてが関連しているため、Boostをサポートします

$ sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev
      
      







2. thrift tarball apache.softded.ru/thrift/0.9.0/thrift-0.9.0.tar.gzをダウンロードします

展開し、configureを実行してからアセンブルします。



 $ ./configure $ make $ sudo make install
      
      







それはすべてのようです...あなたはthrift tarballに付属しているチュートリアルからコードを生成しようとすることさえできます



 $ thrift --gen cpp tutorial.thrift
      
      







thriftコマンドはC ++ラッパーを生成し、gen-cppディレクトリーに注意深く配置します。 Java、PHPなどでも同じことができます...

生成されたソースをコンパイルしてコンパイルしようとします



 $ g++ -Wall -I/usr/local/include/thrift *.cpp -L/usr/local/lib -lthrift -o something
      
      







エラー:「uint32_t」は型に名前を付けていません

uint32_tに関連付けられているリサイクルライブラリに小さなゴキブリがあります。 これは、「#include <stdint.h>」を「Thrift.h」に追加することで処理されます。または(何よりも)特別なコンパイラオプション-DHAVE_NETINET_IN_H -DHAVE_INTTYPES_H



これは次のようになります。



 $ g++ -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -Wall -I/usr/local/include/thrift *.cpp -L/usr/local/lib -lthrift -o something
      
      







それだけで、何かと呼ばれる実行可能ファイルが登場しました。

開始して取得: 共有ライブラリのロード中のエラー:libthrift.so.0:共有オブジェクトファイルを開けません:そのようなファイルまたはディレクトリはありません

この問題を解決するためのいくつかのエレガントな方法があるかもしれませんが、/ usr / local / libから/ libにthriftファイルをコピーすることで真正面から解決しました



これで、例が開始されました。 したがって、すべてが適切に配置され、すべてが機能します。



これで、RPCサーバーを作成できます。

そのタスクは、キーと値のリポジトリになることです。 長い(数十万)ビットマスクを保存します。 それらを追加し(AND)、クライアントにインデックスの配列を与えます。 はい、Redisはほぼ同じことを実行できますが、私には適していません。



完全なコードはこちら: github.com/2anikulin/fast-hands.git



thrift定義ファイルにデータとサービスの署名を記述します

 namespace cpp fasthands namespace java fasthands namespace php fasthands namespace perl fasthands exception InvalidOperation { 1: i32 what, 2: string why } service FastHandsService { i32 put(1:i32 key, 2:binary value), binary get(1:i32 key), list <i32> bitAnd(1:list<i32> keys) throws (1:InvalidOperation ouch) }
      
      







そして、ラッパーを生成します。

C ++実装

このコードはRPCサーバーを作成して起動します



 #define PORT 9090 #define THREAD_POOL_SIZE 15 int main() { printf("FastHands Server started\n"); shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); shared_ptr<FastHandsHandler> handler(new FastHandsHandler()); shared_ptr<TProcessor> processor(new FastHandsServiceProcessor(handler)); shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(THREAD_POOL_SIZE); shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory()); threadManager->threadFactory(threadFactory); threadManager->start(); TNonblockingServer server(processor, protocolFactory, PORT, threadManager); server.serve(); printf("done.\n"); return 0; }
      
      







FastHandsHandlerクラス-適用されるすべての機能が実装されます

これはヘッダーファイルです。

 class FastHandsHandler : virtual public FastHandsServiceIf { public: FastHandsHandler(); int32_t put(const int32_t key, const std::string& value); void get(std::string& _return, const int32_t key); void bitAnd(std::vector<int32_t> & _return, const std::vector<int32_t> & keys); private: void appendBitPositions(std::vector<int32_t> & positions, unsigned char bits, int offset); private: std::map<int32_t, std::string> m_store; };
      
      







収集しようとすると、別のエラーが発生します: c ++ undefined reference to apache :: thrift :: server :: TNonblockingServer

実際、チュートリアルとは異なり、私のサーバーは非同期であり、TNonblockingServerクラスを使用しています。 コードをビルドするには、追加のライブラリ-lthriftnb -leventを追加します



つまり、アセンブリは次のようになります。

 g++ -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -Wall -I/usr/local/include/thrift *.cpp -L/usr/local/lib -lthrift -lthriftnb -levent -o something
      
      







今ではすべてが順調です。 コードはコンパイル、リンクされ、出力ファイルは何かと呼ばれます

Javaのラッパーを生成し、そのようなクライアントを作成します



 import fasthands.FastHandsService; import fasthands.InvalidOperation; import org.apache.thrift.TException; import org.apache.thrift.transport.TFramedTransport; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; public class JavaClient { public static void main(String [] args) { TTransport transport = new TFramedTransport(new TSocket("localhost", 9090)); TProtocol protocol = new TBinaryProtocol(transport); final FastHandsService.Client client = new FastHandsService.Client(protocol); final List<Integer> filters = new ArrayList<Integer>(); try { transport.open(); int count = 12500; byte bt[] = new byte[count]; for (int i =0; i < count; i++) { bt[i] = (byte)0xFF; } for (int i = 0; i < 50; i++) { client.put(i, ByteBuffer.wrap(bt)) ; filters.add(i); } List<Integer> list = client.bitAnd(filters); System.out.println(list.size()); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } transport.close(); } }
      
      







結果は何ですか。

興味深いテクノロジーであり、トランスポート機能をC ++の裸のコードに固定するのに悪い方法ではありません。 しかし、RESTよりもはるかに高速であるとは言いません。バイナリデータもhttp経由で美しく送信されます。 C ++でJavaから取得したコードのパフォーマンスに関しては、奇跡は発生しませんでした。これは、シリアル化+トランスポートレベルの費用のため、1.2〜1.4倍高速です。



All Articles