RPC介绍及Go示例

最近在学MIT6.824的lab1——MapReduce,发现其中使用到了RPC来让work和coordinator之间通信,故而乘机学习一下。

介绍

RPC(Remote Procedure Call,远程过程调用)是一种在分布式系统中进行进程间通信的协议。它允许一个程序(客户端)调用另一个程序(服务器)上的函数或过程,就像调用本地函数一样,而不必关心底层网络细节。

在 RPC 中,客户端和服务器可以在不同的机器上,甚至在不同的网络上。RPC 提供了一种抽象,使得远程调用看起来就像是本地调用一样。通过 RPC,程序可以通过网络传输数据和调用远程函数,使得分布式系统中的组件可以协同工作。

其整体流程如下图所示:

RPC流程

对于RPC需要关注的主要有三点:

  • 通信协议: RPC可以基于TCP或者HTTP协议,一般而言TCP的协议更快
  • 寻址: 远程提供服务器需要提供服务所在地址,例如IP和端口
  • 数据序列化: 远程调用无法依据内存进行参数和结果传递,所以需要规定序列化的格式,例如Json格式

常用的RPC框架有如下这些:

  • Thrift:thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。
  • gRPC:一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
  • Dubbo:Dubbo是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。Dubbo是阿里巴巴内部的SOA服务化治理方案的核心框架,Dubbo自2011年开源后,已被许多非阿里系公司使用。
  • Spring Cloud:Spring Cloud由众多子项目组成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系统及微服务常用的工具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性token、全局锁、选主、分布式会话和集群状态等,满足了构建微服务所需的所有解决方案。Spring Cloud基于Spring Boot, 使得开发部署极其简单。

GO语言示例

在 Go 语言中,标准库提供了一个 net/rpc 包,用于实现 RPC。基本的使用流程包括注册对象、注册服务、处理请求等。以下是一个简单的 Go RPC 例子:

package main

import (
	"net"
	"net/rpc"
)

// 定义一个用于 RPC 的对象
type MyService struct{}

// 定义一个 RPC 方法
func (s *MyService) Multiply(args *Args, reply *int) error {
	*reply = args.A * args.B
	return nil
}

// 定义传递给 RPC 方法的参数结构
type Args struct {
	A, B int
}

func main() {
	// 注册服务
	rpc.Register(new(MyService))

	// 创建监听器
	listener, err := net.Listen("tcp", ":1234")
	if err != nil {
		panic(err)
	}

	// 处理连接
	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		go rpc.ServeConn(conn)
	}
}

在该例子中,MyService 结构体中的 Multiply 方法被注册为 RPC 服务。通过监听端口 1234,该服务可以接收客户端的 RPC 调用请求。客户端可以通过 net/rpc 包中的函数来发起远程调用。RPC 在分布式系统中广泛用于实现不同节点之间的通信和协作。

以下是一个简单的 Go RPC 客户端的调用代码示例,程序需要确保 RPC 客户端的网络协议和端口与服务器端一致,这样它们才能正确地进行通信。在这个例子中,服务器端监听的是 TCP 端口 1234。:

package main

import (
	"fmt"
	"net/rpc"
)

// 定义传递给 RPC 方法的参数结构
type Args struct {
	A, B int
}

func main() {
	// 连接 RPC 服务器
	client, err := rpc.Dial("tcp", "localhost:1234")
	if err != nil {
		panic(err)
	}
	defer client.Close()

	// 准备 RPC 调用的参数
	args := Args{3, 4}

	// 调用 Multiply 方法
	var result int
	err = client.Call("MyService.Multiply", args, &result)
	if err != nil {
		panic(err)
	}

	// 打印结果
	fmt.Printf("Result of 3 * 4: %d\n", result)
}

在这个例子中,rpc.Dial 函数用于连接到服务器,然后通过 client.Call 方法调用远程的 Multiply 方法。在调用过程中,需要传递参数结构 Args 和一个用于接收结果的变量。最后,打印出调用结果:

Result of 3 * 4: 12

参考链接

  • https://jaminzhang.github.io/architecture/RPC-Introduction/
  • https://zhuanlan.zhihu.com/p/187560185
  • https://cloud.tencent.com/developer/article/2021745
  • ChatGPT
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值