transport 模块
transport 模块,是网络通信层。 go-mirco 定义好了相关接口
比如,你自己的网络库实现 go-mirco 定义好的这些接口,即可作为 transport 插件
transport 相关接口
transport 所有接口定义都在: transport/transport.go
主要定义了如下接口:
1. 协议
type Message struct {
Header map[string]string
Body []byte
}
go-mirco 其他模块看到的协议,都要是 Message
transport 层内部使用什么协议是自由的。
2. Socket 对象定义
type Socket interface {
Recv(*Message) error
Send(*Message) error
Close() error
Local() string
Remote() string
}
Socket 定义了网络会话对象必须要实现的接口
3. Client 对象定义
type Client interface {
Socket
}
Client 定义了客户端对象接口
4. Listener 对象定义
type Listener interface {
Addr() string
Close() error
Accept(func(Socket)) error
}
Listener 定义了服务器端对象接口
5. Transport 对象定义
type Transport interface {
Init(...Option) error
Options() Options
Dial(addr string, opts ...DialOption) (Client, error)
Listen(addr string, opts ...ListenOption) (Listener, error)
String() string
}
type Option func(*Options)
type DialOption func(*DialOptions)
type ListenOption func(*ListenOptions)
Transport 是 Transport 模块的使用面板。包括:
- 初始化,设置 Option
- 建立连接,返回 Client 对象
- 开始监听,返回 Listener 对象
transport 模块使用例子
介绍了 go-micro 的接口定义后,我们再看下如何使用这些接口
下面代码摘自 transport/memory/memory_test.go
func TestMemoryTransport(t *testing.T) {
tr := NewTransport()
// bind / listen
l, err := tr.Listen("localhost:8080")
if err != nil {
t.Fatalf("Unexpected error listening %v", err)
}
defer l.Close()
// accept
go func() {
if err := l.Accept(func(sock transport.Socket) {
for {
var m transport.Message
if err := sock.Recv(&m); err != nil {
return
}
t.Logf("Server Received %s", string(m.Body))
if err := sock.Send(&transport.Message{
Body: []byte(`pong`),
}); err != nil {
return
}
}
}); err != nil {
t.Fatalf("Unexpected error accepting %v", err)
}
}()
// dial
c, err := tr.Dial("localhost:8080")
if err != nil {
t.Fatalf("Unexpected error dialing %v", err)
}
defer c.Close()
// send <=> receive
for i := 0; i < 3; i++ {
if err := c.Send(&transport.Message{
Body: []byte(`ping`),
}); err != nil {
return
}
var m transport.Message
if err := c.Recv(&m); err != nil {
return
}
t.Logf("Client Received %s", string(m.Body))
}
}
上面摘录的测试代码用例,实际上可用于任何 transport 插件。
transport 模块目录文件介绍
下面是目录文件,注释在右侧
.
├── grpc // transport grpc 插件
│ ├── grpc.go // transport 接口实现代码
│ ├── grpc_test.go // 测试用例
│ ├── handler.go
│ ├── proto // transport.proto 定义了`transport grpc 插件`网络层内部通信协议
│ │ ├── transport.micro.go // 自动生成
│ │ ├── transport.pb.go // 自动生成
│ │ └── transport.proto // 网络层内部通信协议
│ └── socket.go // socket 接口、 client 接口以及 listener 接口实现
├── http // transport http 插件
│ ├── http.go // transport 接口实现代码。这里只是包裹下,真正实现在外面 http_*.go
│ ├── http_test.go // 测试用例
│ └── options.go // 提供额外的 http 服务接口(福利)
├── http_proxy.go // transport http 插件,建立连接细节
├── http_transport.go // transport http 插件,transport 接口、 socket 接口、 client 接口以及 listener 接口实现
├── http_transport_test.go // 测试用例
├── memory // transport memory 插件
│ ├── memory.go // transport memory 插件,transport 接口、 socket 接口、 client 接口以及 listener 接口实现
│ └── memory_test.go // 测试用例
├── options.go // transport http 插件,相关 option
├── quic // transport quic 插件
│ └── quic.go // transport quic 插件,transport 接口、 socket 接口、 client 接口以及 listener 接口实现
└── transport.go // transport 模块接口定义
其他说明
- transport 模块非常底层,独立性很强,甚至可以直接拿出来当网络层来用
- transport 模块代码相当清晰简单
- go-micro 内置对 http 、 grpc 、 quic 这几个库做封装
- go-micro 内置的 transport memory 插件,是非常经典的使用 golang chan 的例子。强烈推荐阅读
- transport memory 插件涉及 mock 编程模式,后续会专门介绍
- 读者不熟悉 http 、grpc 、 quic 等库 API 的,可以跳读,不妨碍理解 transport 模块内容