rpc简介
什么是 RPC(Remote Procedure Call)?
RPC(远程过程调用) 是一种计算机通信协议,它允许程序在不同的计算机上像调用本地函数一样,调用远程服务。开发者无需关注底层通信细节(如网络传输),而是通过调用函数接口完成任务。
通俗解释
可以把 RPC 想象成:
- 打电话:你拨打远程服务的“电话”(方法),告诉它你需要什么。
- 收快递:远程服务处理后,将结果返回给你。
RPC 的通信过程
RPC 通信大致分为以下几步:
- 客户端调用接口:客户端程序像调用本地函数一样发起调用。
- 封装请求数据:RPC 框架将调用请求的数据序列化(如 JSON 或 Protobuf)并通过网络发送到服务端。
- 服务端接收请求:服务端 RPC 框架反序列化数据并调用相应的函数处理。
- 服务端返回结果:服务端将处理结果序列化后通过网络返回。
- 客户端接收结果:客户端 RPC 框架反序列化结果,并将其返回给调用者。
如何用 RPC 进行通信(以 Go 为例)
Go 的标准库提供了对 RPC 的支持,通过 net/rpc
包实现基本的 RPC 通信。
RPC 示例
1. 服务端代码
服务端定义一个结构体和其方法,并注册为 RPC 服务。
package main
import (
"errors"
"fmt"
"net"
"net/rpc"
)
// 定义服务
type Calculator struct{}
// 方法:加法
func (c *Calculator) Add(args *Args, reply *int) error {
*reply = args.A + args.B
return nil
}
// 方法:除法
func (c *Calculator) Divide(args *Args, reply *int) error {
if args.B == 0 {
return errors.New("division by zero")
}
*reply = args.A / args.B
return nil
}
// 参数结构体
type Args struct {
A, B int
}
func main() {
// 注册服务
calculator := new(Calculator)
rpc.Register(calculator)
// 设置监听
listener, err := net.Listen("tcp", ":1234")
if err != nil {
fmt.Println("Error starting server:", err)
return
}
fmt.Println("Server is running on port 1234...")
defer listener.Close()
// 接收客户端请求
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Connection error:", err)
continue
}
go rpc.ServeConn(conn)
}
}
2. 客户端代码
客户端连接到服务端,调用远程方法。
package main
import (
"fmt"
"net/rpc"
)
// 参数结构体
type Args struct {
A, B int
}
func main() {
// 连接 RPC 服务
client, err := rpc.Dial("tcp", "localhost:1234")
if err != nil {
fmt.Println("Error connecting to server:", err)
return
}
defer client.Close()
// 调用远程方法 Add
args := Args{A: 10, B: 20}
var reply int
err = client.Call("Calculator.Add", &args, &reply)
if err != nil {
fmt.Println("Error calling Add:", err)
return
}
fmt.Println("Result of Add:", reply)
// 调用远程方法 Divide
args = Args{A: 20, B: 4}
err = client.Call("Calculator.Divide", &args, &reply)
if err != nil {
fmt.Println("Error calling Divide:", err)
return
}
fmt.Println("Result of Divide:", reply)
}
运行流程
- 运行服务端:启动服务端程序,监听指定端口等待客户端连接。
- 运行客户端:启动客户端程序,连接服务端并调用远程方法。
服务端输出:
Server is running on port 1234...
客户端输出:
Result of Add: 30
Result of Divide: 5
其他 RPC 框架
除了 Go 标准库的 net/rpc
,还有一些更强大的第三方 RPC 框架:
-
gRPC:
- 基于 HTTP/2 和 Protocol Buffers。
- 高性能、跨语言。
- 支持流式通信。
-
Thrift:
- Apache 提供的跨语言 RPC 框架。
-
JSON-RPC:
- 基于 JSON 的轻量级协议。
RPC是应用层上的接口抽象,不限于具体传输协议(可以基于 HTTP/TCP)。