gRPC 在 C++ 中:微服务及其他领域的强大工具

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

gRPC 在 C++ 中:何时真正需要(以及何时最好避开它)



想象一下:您正在用 C++ 编写一个高负载的后端。服务器每秒处理数千个请求,数据成批传输,而客户端要求即时响应。使用 JSON 的 REST API 开始变慢——解析消耗 CPU,数据包臃肿,而且为了流式传输数据,您不得不拼凑出临时解决方案。听起来熟悉吗?



这时,gRPC 登场了——这是 Google 开发的一个现代远程过程调用框架。它使用二进制协议(Protobuf),支持流式传输、双向通信,并且比传统的 REST 快得多。但是,像任何强大的工具一样,在 C++ 中使用 gRPC 需要深思熟虑。在本文中,我们将分析何时引入它是金矿,何时它只是额外的麻烦。



本文是为那些已经听说过 gRPC,但想了解 “我需要它吗?” 的 C++ 开发者编写的。没有废话——只有实践、代码和诚实的建议。



什么是 gRPC,为什么 C++ 是它最好的朋友?



gRPC 建立在两大支柱之上:用于数据序列化的 Protocol Buffers (Protobuf) 和用于传输的 HTTP/2。Protobuf 将结构化数据转换为紧凑的二进制格式,其解析速度比 JSON 快一个数量级。而 HTTP/2 允许通过单个连接复用请求,并支持服务器/客户端流式传输。



C++ 在这里如鱼得水:对内存的低级控制、最小的开销、与 Protobuf 的完美集成(从 .proto 文件生成代码)。最终,C++ 上的 gRPC 提供了接近原生套接字交换的性能,同时兼具现成 RPC 框架的便利性。



关于 Protobuf 的简要说明(以便理解)



想象一下,您在文件 user.proto 中描述一个数据结构:



syntax = "proto3";

message User { int32 id = 1; string name = 2; string email = 3;}

service UserService { rpc GetUser (UserRequest) returns (User);}

message UserRequest { int32 user_id = 1;}


然后,protoc 编译器会生成带有序列化/反序列化方法的 C++ 类。您只需调用 user.name(),底层就是一个 20 字节的二进制数据包,而不是 100 多字节的 JSON。



何时应该在 C++ 中选择 gRPC:5 个铁定场景



1. 高负载的微服务架构



如果您有 10-50 个 C++ 微服务不断相互通信,gRPC 是必备之选。原因:低延迟和强类型契约。



示例:支付服务和通知服务。没有 gRPC,您会发送带有字段 "user_id": 123 的 JSON。字段名拼写错误——bug 就会进入生产环境。使用 gRPC,契约在 .proto 文件中被严格定义,编译错误会在构建阶段被捕获。



真实代码: C++ 服务端部分(简化版):



#include <grpcpp/grpcpp.h>#include "user.grpc.pb.h"

class UserServiceImpl final : public UserService::Service { grpc::Status GetUser(grpc::ServerContext* context, const UserRequest* request, User* reply) override { // 模拟数据库查找 reply->set_id(request->user_id()); reply->set_name("Alice"); reply->set_email("alice@example.com"); return grpc::Status::OK; }};

void RunServer() { std::string server_address("0.0.0.0:50051"); UserServiceImpl service;

grpc::ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service);

std::unique_ptr<grpc::Server> server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait();}


客户端调用——甚至更简

博客

书籍推荐