rpc简介

什么是 RPC(Remote Procedure Call)?

RPC(远程过程调用) 是一种计算机通信协议,它允许程序在不同的计算机上像调用本地函数一样,调用远程服务。开发者无需关注底层通信细节(如网络传输),而是通过调用函数接口完成任务。

通俗解释

可以把 RPC 想象成:

  1. 打电话:你拨打远程服务的“电话”(方法),告诉它你需要什么。
  2. 收快递:远程服务处理后,将结果返回给你。

RPC 的通信过程

RPC 通信大致分为以下几步:

  1. 客户端调用接口:客户端程序像调用本地函数一样发起调用。
  2. 封装请求数据:RPC 框架将调用请求的数据序列化(如 JSON 或 Protobuf)并通过网络发送到服务端。
  3. 服务端接收请求:服务端 RPC 框架反序列化数据并调用相应的函数处理。
  4. 服务端返回结果:服务端将处理结果序列化后通过网络返回。
  5. 客户端接收结果:客户端 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)
}

运行流程

  1. 运行服务端:启动服务端程序,监听指定端口等待客户端连接。
  2. 运行客户端:启动客户端程序,连接服务端并调用远程方法。

服务端输出

Server is running on port 1234...

客户端输出

Result of Add: 30
Result of Divide: 5

其他 RPC 框架

除了 Go 标准库的 net/rpc,还有一些更强大的第三方 RPC 框架:

  1. gRPC

    • 基于 HTTP/2 和 Protocol Buffers。
    • 高性能、跨语言。
    • 支持流式通信。
  2. Thrift

    • Apache 提供的跨语言 RPC 框架。
  3. JSON-RPC

    • 基于 JSON 的轻量级协议。

RPC是应用层上的接口抽象,不限于具体传输协议(可以基于 HTTP/TCP)。

posted @ 2024-12-23 11:48  牛马chen  阅读(20)  评论(0编辑  收藏  举报