在分布式系统里,服务之间到底是怎么"像函数调用一样通信"的?
本文从 gRPC 的设计思想讲起,系统梳理它的能力、优缺点和真实使用场景,并用 C++ 实现一个完整可跑的 gRPC 服务端和客户端,一步到位,帮你真正理解 gRPC 在工程中的价值。
Github: github.com/grpc/grpc 官方文档:grpc.io/docs/langua...

为什么越来越多的系统在用 gRPC?
在早期的服务通信中,我们最常见的方案无非两种:
一种是 HTTP + JSON ,简单直观,但性能和规范性始终是瓶颈;
另一种是自己造 RPC 轮子,成本高、维护难、协议混乱。
gRPC 的出现,本质上就是在解决一个问题:
如何让跨进程、跨机器的服务调用,像本地函数调用一样自然?
gRPC 是 Google 开源的一套高性能 RPC 框架,核心特点有三个:
- 基于 HTTP/2
- 使用 Protocol Buffers 作为接口描述和序列化协议
- 强约束的接口定义
这三个设计,决定了 gRPC 天生就不是"写给小脚本用的",而是面向中大型系统、微服务架构的通信基础设施。
优点和缺点
优点:
- 性能好,延迟低
- 接口规范清晰,适合团队协作
- 工具链成熟,自动生成代码
- 对微服务非常友好
缺点:
- 学习成本高于 REST
- 调试不如 HTTP 直观
- 对浏览器不友好(需要 gRPC-Web)
- protobuf 一旦设计不好,后期改动成本高
一句话总结:
gRPC 非常适合"服务与服务之间",但并不适合"直接暴露给人类使用"。
C++ gRPC 实战:从 0 到跑起来
下面用一个最简单的 HelloService,演示完整流程。
安装 gRPC 环境
bash
sudo apt-get update
sudo apt-get install -y build-essential autoconf libtool pkg-config
# 安装 protobuf 编译器
sudo apt-get install -y libprotobuf-dev protobuf-compiler
# 安装 gRPC 库和插件
sudo apt-get install -y libgrpc++-dev libgrpc-dev
定义 proto 文件(hello.proto)
proto
syntax = "proto3";
package hello;
service HelloService {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
生成 C++ 代码:
bash
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` hello.proto
protoc --cpp_out=. hello.proto
C++ 服务端实现
cpp
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "hello.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
class HelloServiceImpl final : public hello::HelloService::Service {
public:
Status SayHello(ServerContext* context,
const hello::HelloRequest* request,
hello::HelloReply* reply) override {
reply->set_message("Hello, " + request->name());
return Status::OK;
}
};
int main() {
std::string server_address("0.0.0.0:50051");
HelloServiceImpl service;
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();
return 0;
}
编译并启动服务
bash
# 单文件编译
g++ -std=c++11 main.cpp hello.pb.cc hello.grpc.pb.cc \
-o hello_server \
`pkg-config --cflags --libs grpc++ grpc protobuf` \
-lgrpc++_reflection \
-lpthread
# 运行
./hello_server
C++ 客户端调用测试
c
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "hello.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
class HelloClient {
public:
HelloClient(std::shared_ptr<Channel> channel)
: stub_(hello::HelloService::NewStub(channel)) {}
std::string SayHello(const std::string& name) {
hello::HelloRequest request;
request.set_name(name);
hello::HelloReply reply;
ClientContext context;
Status status = stub_->SayHello(&context, request, &reply);
if (status.ok()) {
return reply.message();
} else {
return "RPC failed";
}
}
private:
std::unique_ptr<hello::HelloService::Stub> stub_;
};
int main() {
HelloClient client(
grpc::CreateChannel("localhost:50051",
grpc::InsecureChannelCredentials()));
std::cout << client.SayHello("gRPC C++") << std::endl;
return 0;
}
编译并运行
bash
# 单文件编译
g++ -std=c++11 main.cpp hello.pb.cc hello.grpc.pb.cc \
-o hello_client \
`pkg-config --cflags --libs grpc++ grpc protobuf` \
-lgrpc++_reflection \
-lpthread
# 运行
./hello_client
启动服务端,再运行客户端,你会看到:
Hello, gRPC C++
写在最后
很多人学 gRPC,卡在"看懂文档,却不知道怎么落地"。
真正跑通一次 C++ 服务端和客户端,你会发现:
gRPC 并不神秘,它只是把"服务调用"这件事,做得更像工程,而不是脚本。
如果你正在做 分布式系统、微服务、基础设施,gRPC 值得你认真掌握。