当前位置: 首页 > news >正文

《Go语言高级编程》RPC 入门

《Go语言高级编程》RPC 入门

一、什么是 RPC?

RPC(Remote Procedure Call,远程过程调用)是分布式系统中不同节点间的通信方式,允许程序像调用本地函数一样调用远程服务的方法。
Go 语言的标准库 net/rpc 提供了基础的 RPC 实现,基于网络(如 TCP)通信,支持服务注册、方法调用和数据编码。

二、RPC 版 “Hello, World” 示例
1. 服务端实现
// 定义服务类型及方法(需满足 RPC 规则:公开方法、两参数、第二参数为指针、返回 error)
type HelloService struct {}func (p *HelloService) Hello(request string, reply *string) error {*reply = "hello:" + requestreturn nil
}func main() {// 注册服务,方法会被放在 "HelloService" 命名空间下rpc.RegisterName("HelloService", new(HelloService))// 监听 TCP 连接listener, err := net.Listen("tcp", ":1234")if err != nil {log.Fatal("ListenTCP error:", err)}// 接受单个连接并提供服务conn, err := listener.Accept()if err != nil {log.Fatal("Accept error:", err)}rpc.ServeConn(conn)
}
2. 客户端实现
func main() {// 拨号连接服务端client, err := rpc.Dial("tcp", "localhost:1234")if err != nil {log.Fatal("dialing:", err)}// 调用服务方法(参数:服务名.方法名、请求参数、响应指针)var reply stringerr = client.Call("HelloService.Hello", "hello", &reply)if err != nil {log.Fatal(err)}fmt.Println(reply) // 输出:hello:hello
}
关键点说明:
  • RPC 方法规则:必须为公开方法(首字母大写),有两个可序列化参数,第二参数为指针,返回 error
  • 服务注册rpc.RegisterName 将方法注册到指定命名空间,便于客户端调用。
  • 通信流程:服务端监听连接,客户端拨号后通过 Call 方法远程调用。
三、更安全的 RPC 接口设计
1. 接口规范定义
// 定义服务名、接口和注册函数,解耦服务实现与调用
const HelloServiceName = "path/to/pkg.HelloService"type HelloServiceInterface interface {Hello(request string, reply *string) error
}func RegisterHelloService(svc HelloServiceInterface) error {return rpc.RegisterName(HelloServiceName, svc)
}
2. 客户端封装
// 封装客户端接口,简化调用并提供类型安全保障
type HelloServiceClient struct {*rpc.Client
}// 确保 HelloServiceClient 实现接口
var _ HelloServiceInterface = (*HelloServiceClient)(nil)func DialHelloService(network, address string) (*HelloServiceClient, error) {c, err := rpc.Dial(network, address)if err != nil {return nil, err}return &HelloServiceClient{Client: c}, nil
}func (p *HelloServiceClient) Hello(request string, reply *string) error {return p.Client.Call(HelloServiceName+".Hello", request, reply)
}
3. 客户端调用(简化版)
func main() {client, err := DialHelloService("tcp", "localhost:1234")if err != nil {log.Fatal("dialing:", err)}var reply stringerr = client.Hello("hello", &reply)if err != nil {log.Fatal(err)}fmt.Println(reply)
}
优势:
  • 接口隔离:服务端和客户端通过接口规范解耦,便于团队分工。
  • 类型安全:编译器确保服务实现和客户端调用符合接口定义,减少错误。
  • 可维护性:服务名和方法名通过常量管理,避免硬编码。
四、跨语言 RPC(基于 JSON 编码)

Go 标准库默认使用 gob 编码(Go 特有),若需跨语言调用,可改用 JSON 编码:

1. 服务端(JSON 版本)
func main() {rpc.RegisterName("HelloService", new(HelloService))listener, err := net.Listen("tcp", ":1234")if err != nil {log.Fatal("ListenTCP error:", err)}// 支持多个连接,每个连接使用 JSON 编解码器for {conn, err := listener.Accept()if err != nil {log.Fatal("Accept error:", err)}go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))}
}
2. 客户端(JSON 版本)
func main() {// 手动建立 TCP 连接conn, err := net.Dial("tcp", "localhost:1234")if err != nil {log.Fatal("net.Dial:", err)}// 使用 JSON 编解码器创建客户端client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))var reply stringerr = client.Call("HelloService.Hello", "hello", &reply)if err != nil {log.Fatal(err)}fmt.Println(reply)
}
3. 数据格式(JSON)
  • 请求格式{"method":"服务名.方法名","params":["参数"],"id":调用编号}
    示例:{"method":"HelloService.Hello","params":["hello"],"id":0}
  • 响应格式{"id":编号,"result":"结果","error":错误信息}
    示例:{"id":0,"result":"hello:hello","error":null}
跨语言原理:

通过标准 JSON 格式交换数据,任何支持 JSON 解析的语言(如 Python、Java)都可按此格式调用 Go 的 RPC 服务。

五、基于 HTTP 的 RPC

将 RPC 服务架设在 HTTP 协议上,便于与 Web 系统集成:

服务端实现
func main() {rpc.RegisterName("HelloService", new(HelloService))// 在 HTTP 路径 /jsonrpc 处理 RPC 请求http.HandleFunc("/jsonrpc", func(w http.ResponseWriter, r *http.Request) {// 构造 IO 读写器,适配 HTTP 请求和响应var conn io.ReadWriteCloser = struct {io.Writerio.ReadCloser}{ReadCloser: r.Body,Writer:     w,}rpc.ServeRequest(jsonrpc.NewServerCodec(conn))})http.ListenAndServe(":1234", nil)
}
客户端调用(通过 curl)
curl localhost:1234/jsonrpc -X POST \--data '{"method":"HelloService.Hello","params":["hello"],"id":0}'
优势:
  • 兼容性强:HTTP 是互联网标准协议,支持浏览器、API 网关等多种客户端。
  • 易于调试:可直接通过浏览器或 curl 工具测试 RPC 接口。
六、核心概念总结
  1. RPC 本质:封装网络通信,使远程调用像本地函数调用一样简单。
  2. Go RPC 关键组件
    • 服务注册rpc.RegisterName 绑定服务名与方法。
    • 编解码器:默认 gob,跨语言可用 jsonrpc
    • 连接处理ServeConn(单连接)、ServeCodec(多连接)。
  3. 设计原则
    • 接口与实现分离,通过规范解耦服务端与客户端。
    • 跨语言场景优先使用标准格式(如 JSON)编码数据。
http://www.lqws.cn/news/554779.html

相关文章:

  • 思科交换机接口显示inactive原因
  • c# 比较两个list 之间元素差异
  • 搭建Flink分布式集群
  • 5 BERT预训练模型
  • WPF XAML 格式化工具(XAML Styler)
  • STM32F103C8T6参数说明
  • 从单体架构到微服务:微服务架构演进与实践
  • Linux【9】-----Linux系统编程(线程池和并发socket编程 c语言)
  • 【安卓Sensor框架-2】应用注册Sensor 流程
  • 【Network Management】ComM模块中的PNState和ChannelState间的关系
  • 从【人工智能】到【计算机视觉】。深度学习引领的未来科技创新与变革
  • 解决cursor无法下载插件等网络问题
  • Level2.11继承
  • Qt-Advanced-Docking-System页面布局
  • Linux通过Crontab实现自启动
  • 大数据在UI前端的应用创新研究:用户偏好的动态调整与优化
  • 深入解析 Electron 架构:主进程 vs 渲染进程
  • 论文降重怎么做?三种自动降重软件使用评测
  • Swift × Android:官方工作组成立意味着什么?
  • 英语日常词汇大全(附音标、释义、短语及例句)
  • Web基础关键_004_CSS(二)
  • cf 禁止http/1.0和http/1.1的访问 是否会更安全?
  • 函数指针与指针函数
  • 如何提取mdd字典中音频文件并转化为mp3
  • 基于社区电商场景的Redis缓存架构实战02-社区电商项目实战
  • 嵌入式单片机中SPI串行外设接口控制与详解
  • cannot import name ‘TextKwargs‘ from ‘transformers.processing_utils‘
  • git使用详解和示例
  • 蓝凌流程引擎流程图格式化实现原理全解
  • 湖北理元理律师事务所:债务优化中的法律理性与人文温度