RPC 编程完整攻略
1. 什么是 RPC?
RPC(Remote Procedure Call,远程过程调用)是一种允许程序调用远程服务器上的函数,就像调用本地函数一样的技术。它隐藏了底层的网络通信,让分布式系统开发更简单。
2. RPC 的基本原理
RPC 通过客户端和服务器之间的通信来实现:
-
客户端调用 RPC 代理,就像调用本地函数一样。
-
代理序列化(编码)请求数据并发送给服务器。
-
服务器解码数据,执行对应的函数,并返回结果。
-
客户端接收返回值,解码并提供给调用方。
3. RPC 的组成
3.1. 客户端
-
发送 RPC 请求
-
处理服务器返回的响应
3.2. 服务器
-
监听请求
-
解析并执行对应的远程函数
-
返回结果
3.3. 通信协议
RPC 需要一种方式在客户端和服务器之间传输数据:
-
HTTP(RESTful 风格的 RPC,如 gRPC-Web)
-
TCP/UDP(高性能 RPC,如 gRPC、Thrift、Dubbo)
-
消息队列(MQ)(异步 RPC,如 RabbitMQ)
3.4. 序列化方式
-
JSON(可读性高,但数据冗余)
-
Protobuf(gRPC 常用,二进制格式,性能高)
-
MessagePack(比 JSON 更紧凑)
-
Thrift(Facebook 开发,支持多种语言)
4. 常见的 RPC 框架
框架 | 语言支持 | 传输协议 | 序列化格式 | 特点 |
---|---|---|---|---|
gRPC | 多语言 | HTTP/2 | Protobuf | 高性能、流式传输 |
Thrift | 多语言 | TCP | Thrift | 轻量级、高扩展 |
Dubbo | Java | TCP/HTTP | Hessian | 阿里巴巴开发,适用于微服务 |
JSON-RPC | 多语言 | HTTP | JSON | 轻量级 |
XML-RPC | 多语言 | HTTP | XML | 早期广泛使用 |
5. RPC 实战
这里以 Node.js(客户端) + Go(服务器)+ gRPC 为例,搭建一个简单的 RPC 服务。
5.1. 安装 gRPC
npm install @grpc/grpc-js @grpc/proto-loader
go install google.golang.org/grpc/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
5.2. 定义 Protobuf
创建 service.proto
:
syntax = "proto3";
package demo;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
5.3. 生成代码
protoc --go_out=. --go-grpc_out=. service.proto
5.4. 实现 gRPC 服务器(Go)
创建 server.go
:
package main
import (
"context"
"fmt"
"net"
pb "path/to/generated/proto"
"google.golang.org/grpc"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + req.Name}, nil
}
func main() {
listener, _ := net.Listen("tcp", ":50051")
grpcServer := grpc.NewServer()
pb.RegisterGreeterServer(grpcServer, &server{})
fmt.Println("gRPC Server started on port 50051")
grpcServer.Serve(listener)
}
5.5. 实现 gRPC 客户端(Node.js)
创建 client.js
:
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('service.proto');
const proto = grpc.loadPackageDefinition(packageDefinition).demo;
const client = new proto.Greeter('localhost:50051', grpc.credentials.createInsecure());
client.SayHello({ name: 'Alice' }, (err, response) => {
if (err) console.error(err);
console.log('Response:', response.message);
});
5.6. 运行
go run server.go # 启动服务器
node client.js # 运行客户端
客户端会输出:
Response: Hello Alice
6. RPC 进阶
6.1. 负载均衡
-
gRPC 支持客户端负载均衡
-
Dubbo 使用注册中心(如 ZooKeeper)进行服务发现
-
Nginx 也可用于 RPC 负载均衡
6.2. 安全性
-
TLS/SSL 加密(gRPC 支持)
-
身份验证(JWT、OAuth2)
-
防重放攻击(使用 nonce)
6.3. 性能优化
-
连接池(减少 TCP 连接开销)
-
缓存(减少重复计算)
-
流式 RPC(适用于长连接)
7. RPC vs REST
对比项 | RPC | REST |
---|---|---|
调用方式 | 方法调用 | 资源操作(CRUD) |
协议 | TCP/HTTP2 | HTTP/1.1 |
性能 | 高(小数据包) | 低(文本格式) |
适用场景 | 内部微服务 | Web API |
8. 总结
-
RPC 是分布式系统的核心技术,可以让远程调用像本地调用一样。
-
gRPC、Thrift、Dubbo 是主流的 RPC 解决方案。
-
选择合适的序列化协议(Protobuf/JSON)提高性能。
-
关注安全性(TLS、身份认证)和高可用(负载均衡)。
9. 进一步学习
-
官方文档:
-
开源项目: