在 gRPC 中,反射允许客户端在运行时查询服务器的接口信息,而无需事先知道服务的定义。这对于工具(如 gRPC CLI)或动态客户端很有用。在 C++ 中,gRPC 提供了一个反射服务,可以与服务器一起注册,以支持此功能。
以下是一个演示如何在 C++ 中启用 gRPC 反射的代码示例:
1. 设置 gRPC 反射服务
首先,确保已经安装了 gRPC 并且其版本支持反射(gRPC 1.3.0 及以上版本支持反射服务)。
2. 定义 proto 文件
定义一个简单的 .proto 文件,如下所示:
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
3. 生成 gRPC 代码
使用 protoc 生成 gRPC 和协议缓冲区的 C++ 代码。
protoc --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=which grpc_cpp_plugin helloworld.proto
4. 实现 C++ 服务器并启用反射
在服务器实现中启用反射服务,并注册的服务:
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include "helloworld.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
// 实现服务
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
// 启用反射服务
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
// 注册反射服务
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}
5. 运行服务器
编译并运行服务器:
g++ -std=c++11 server.cpp -o server -lgrpc++ -lgrpc -lprotobuf -lpthread
./server
当服务器启动后,它不仅提供了 Greeter 服务,还同时启用了 gRPC 的反射服务。
6. 使用 gRPC CLI 进行反射
gRPC 提供了一个命令行工具 grpc_cli,它可以利用反射服务来查询服务器的接口。
首先,确保已经安装 grpc_cli。然后可以运行以下命令来查询服务器上可用的服务:
grpc_cli ls localhost:50051
这将列出服务器上所有可用的服务。
还可以列出某个服务的方法:
grpc_cli ls localhost:50051 helloworld.Greeter -l
甚至可以调用服务:
grpc_cli call localhost:50051 helloworld.Greeter.SayHello "name: 'World'"