net/rpc 介绍与源代码分析

net/rpc 库

net/rpc 库是 golang 官方内置的 rpc 库

其源代码就位于: $GOROOT/src/net/rpc ,比如 /usr/local/go/src/net/rpc/

net/rpc 具有良好的代码结构,众多开源库网络层实现,均采用相同的编程模式,比如 gRPC 、 go-micro

因此不免有点小激动,记录一二

背景

看过不少 rpc 库都是使用 golang 的 reflection 库做 rpc 功能,包括 gRPC 、 go-micro 、 公司内部项目 1 rpc

很少想过直接复用 net/rpc

官方的 net/rpc 库,不深入看代码的话,可能会被定性为:

  • 内置 net 库处理
  • 使用 gob 编解码网络数据

因此,无法复用 net/rpc 库

实际上官方的 net/rpc 具备很好的编程模式,可以做到:

  • 可以自定义网络层
  • 可以自定义网络数据编解码

代码结构

                +------------------+
                |                  |
                |     rpc Logic    |
                |                  |
                +-----+-----+------+
                      ^     |
                      |     |
1. get data by codec  |     |
                      |     |
                      |     | 2. put data to codec
                      |     |
                      |     v
                +-----+-----+------+                               +----------------------+
                |                  |  codec have abstract IO layer |                      |
                |       Codec      +-------------------------------+  io.ReadWriteCloser  |
                |                  |                               |                      |
                +------------------+                               +-----------+----------+
                                                                               |
                                                          +--------------------+--------------------+
                                                          |                    |                    |
                                                          |                    |                    |
                                                  +-------+--------+   +-------+--------+   +-------+--------+
                                                  |                |   |                |   |                |
                                                  |   net/Conn     |   |  bytes.Buffer  |   | other your want|
                                                  |                |   |                |   |                |
                                                  +----------------+   +----------------+   +----------------+

  • net/rpc 库的 rpc 逻辑通过 codec (编解码器),使之与 IO 层无关

  • IO 层使用了抽象的接口 io.ReadWriteCloser

    type ReadWriteCloser interface {
    	Reader
    	Writer
    	Closer
    }
    
    • IO 层具体实现,可以是 TCP socket
    • 文件 IO
    • 或者内存 buffer
    • 其他任何实现 io.ReadWriteCloser 的对象
  • net/rpc 库 tcp net 、gob 相关代码,都在一个文件中,因此看上去比较混乱,实际上代码结构很清晰

  • 该经典编程模式在众多开源中均采用,比如 gRPC 、 go-micro

源代码分析

1. 目录文件

linux 下通常位于 /usr/local/go/src/net/rpc/

/usr/local/go/src/net/rpc/
├── client.go					// rpc 客户端
├── client_test.go
├── debug.go
├── jsonrpc						// 例子, 自定义网络数据编解码;也可以看做 jsonrpc
│   ├── all_test.go
│   ├── client.go
│   └── server.go
├── server.go					// rpc 服务器
└── server_test.go
2. net/rpc/server.go
  • 包含 RPC 注册,都是反射库的相关知识,略
  • 包含 net 库初始化接收消息等,常见网络库写法,略
  • gob 消息编解码,略
  • 最最核心代码,如下 2 个函数:
    // ServeCodec is like ServeConn but uses the specified codec to
    // decode requests and encode responses.
    func (server *Server) ServeCodec(codec ServerCodec) {
    	// 略,与 ServeRequest 的差不多,这里就不显示了
    }
    // ServeRequest is like ServeCodec but synchronously serves a single request.
    // It does not close the codec upon completion.
    func (server *Server) ServeRequest(codec ServerCodec) error {
    	sending := new(sync.Mutex)
    	service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
    	if err != nil {
    		// 错误处理,分支逻辑,略
    	}
    	service.call(server, sending, nil, mtype, req, argv, replyv, codec)
    	return nil
    }
    
    • server.readRequest(codec) , 通过 codec ,获取要调用的函数名,进而获取方法对象
    • server.readRequest(codec)` , 通过 codec ,同时也获取了函数参数对象
    • service.call 基于反射调用 rpc 方法
3. net/rpc/client.go

与 net/rpc/server.go 类似,代码上是同步调用

代码分析, 略

自定义 Codec 、 IO 的例子

笔者在理解 net/rpc 代码,同时写了下测试例子,并调试,以便更好的阅读代码,及用于其他

github 地址: https://github.com/fananchong/test_golang_rpc

个人认为,这是 golang 编写 rpc 代码的最简方式

欢迎 star

发布了129 篇原创文章 · 获赞 73 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/u013272009/article/details/98090041