micro/go-micro 介绍与源代码分析(四): transport 模块

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 模块内容
发布了129 篇原创文章 · 获赞 73 · 访问量 16万+

猜你喜欢

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