こんにちは、今回はRustでgRPCサーバを実装し、ScyllaDBと連携する方法を紹介します。最近、マイクロサービスアーキテクチャや高性能なデータ処理が求められる場面が増えてきています。その中で、gRPCとScyllaDBを組み合わせることで、高速かつスケーラブルなサービスを構築することができます。
gRPCとは
gRPCはGoogleが開発したRPC(Remote Procedure Call)フレームワークで、高性能かつ双方向の通信を可能にします。Protocol Buffersを使用してインターフェースを定義し、各種プログラミング言語で自動的にコード生成が可能です。
より詳細な説明は、以下のリンクを参照してください。
- gRPC
- gRPC vs REST: Understanding gRPC, OpenAPI and REST and when to use them in API design | Google Cloud Blog
- マイクロサービス × gRPCの すゝめ #grpc-gateway - Qiita
- マイクロサービス間通信におけるgRPCとRESTの比較 #REST-API - Qiita
ScyllaDBとは
ScyllaDBは高性能なNoSQLデータベースで、Apache Cassandraと互換性があります。低レイテンシと高スループットを実現しており、大規模なデータ処理に適しています。
より詳細な説明は、以下のリンクを参照してください。
- ScyllaDB | Monstrously Fast + Scalable NoSQL
- Apache Cassandra vs. Redis vs. ScyllaDB Comparison
- NoSQL Database Comparison | ScyllaDB
実装概要
今回は、256次元のベクトルを保存・取得するgRPCサーバをRustで実装し、そのデータストアとしてScyllaDBを使用します。
全体の構成
-
Protoファイルの定義:
vector.proto
でgRPCのサービスとメッセージを定義します。 -
Rustでサーバ実装:
tonic
とscylla
クレートを使用して、サーバを実装します。 - ScyllaDBのセットアップ:Dockerを使用してScyllaDBを起動し、必要なキー空間とテーブルを作成します。
リポジトリはこちらです:makinzm/hajimeteno-tonic
実装の詳細
Protoファイルの定義
src/proto/hello.proto
では、以下のサービスとメッセージを定義しています。
syntax = "proto3";
package vector;
service VectorService {
rpc GetVector (VectorRequest) returns (VectorResponse);
rpc InsertVector (InsertVectorRequest) returns (InsertVectorResponse);
rpc GetVectorByKey (GetVectorByKeyRequest) returns (VectorResponse);
rpc InsertSample (InsertSampleRequest) returns (InsertSampleResponse);
}
message VectorRequest {
int32 id = 1;
}
message VectorResponse {
int32 id = 1;
repeated float vector = 2;
}
message InsertVectorRequest {
string key = 1;
repeated float vector = 2;
}
message InsertVectorResponse {
bool success = 1;
}
message GetVectorByKeyRequest {
string key = 1;
}
message InsertSampleRequest {
int32 id = 1;
}
message InsertSampleResponse {
bool success = 1;
}
サーバの実装
src/main.rs
でサーバの実装を行います。
package名がvec
であるprotoファイルをbuild.rs
でビルドしているため、tonic::include_proto!
マクロを使用して、vector
パッケージをインクルードすることができます。
pub mod vector {
tonic::include_proto!("vector");
}
ここでpub mod
の名称は,protoファイルのpackage名と一致している必要があります。(次の変更を加えると失敗することに注意してください: failure example by makinzm · Pull Request #1 · makinzm/hajimeteno-tonic)
ScyllaDBのセットアップ
ScyllaDBをDockerで起動します。
docker pull scylladb/scylla:latest
docker run --name scylladb -d -p 9042:9042 scylladb/scylla:latest
キー空間とテーブルを作成します。
docker exec -it scylladb cqlsh
CREATE KEYSPACE IF NOT EXISTS vector_keyspace WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
CREATE TABLE IF NOT EXISTS vector_keyspace.vectors (
id int PRIMARY KEY,
key text,
vector list<float>
);
サーバの起動
Rustの環境をセットアップし、サーバをビルド・起動します。
cargo build
cargo run
動作確認
grpcurl
を使用して、gRPCサーバにリクエストを送信します。
サンプルデータの挿入
grpcurl -plaintext -import-path src/proto -proto vector.proto -d '{
"id": 100
}' localhost:50051 vector.VectorService/InsertSample
期待されるレスポンス:
{
"success": true
}
ベクトルの取得
grpcurl -plaintext -import-path src/proto -proto vector.proto -d '{
"id": 100
}' localhost:50051 vector.VectorService/GetVector
取得結果(とても長いので一部抜粋しています)
{
"id": 100,
"vector": [
0.48001575,
0.6714103,
0.16986275,
(中略していますが、実際は256次元のベクトルが返却されます)
0.82636607
]
}
まとめ
今回、RustでgRPCサーバを実装し、ScyllaDBと連携する方法を紹介しました。gRPCとScyllaDBを組み合わせることで、高性能でスケーラブルなサービスを構築できます。コードの各部分で気をつけるべき点や、実際の動作確認方法も含めて解説しました。
今後の展望
- 認証機能の追加:セキュアな通信を実現するために、TLSや認証機能の追加。
- 負荷試験の実施:大量のリクエストを送信して、サーバの性能を評価。