7. 使用 protobuf

Kesa...大约 2 分钟golang

https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/GeeCache/day7-protobufopen in new window

DAY7-PROTOBUF
│  go.mod
│  go.work
│  go.work.sum
│  main.go
│  run.sh
│  
└─geecache
    │  byteview.go
    │  cache.go
    │  consistenthash.go
    │  consistenthash_test.go
    │  geecache.go
    │  geecache_test.go
    │  go.mod
    │  go.sum
    │  http.go
    │  peers.go
    │
    ├─consistenthash
    │      consistenthash.go
    │      consistenthash_test.go
    │
    ├─geecachepb
    │      geecachepb.pb.go
    │      geecachepb.proto
    │
    ├─lru
    │      lru.go
    │      lru_test.go
    │
    └─singleflight
            singleflight.go

1. protobuf

protobuf 即 Protocol Buffers,Google 开发的一种数据描述语言,是一种轻便高效的结构化数据存储格式,与语言、平台无关,可扩展可序列化。protobuf 以二进制方式存储,占用空间小。

protobuf 广泛地应用于远程过程调用(RPC) 的二进制传输,使用 protobuf 的目的非常简单,为了获得更高的性能。传输前使用 protobuf 编码,接收方再进行解码,可以显著地降低二进制传输的大小。另外一方面,protobuf 可非常适合传输结构化数据,便于通信字段的扩展。

使用 protobuf 一般分为以下 2 步:

  • 按照 protobuf 的语法,在 .proto 文件中定义数据结构,并使用 protoc 生成 Go 代码(.proto 文件是跨平台的,还可以生成 C、Java 等其他源码文件)。
  • 在项目代码中引用生成的 Go 代码。

2. 使用 protobuf

2.1 定义消息类型

syntax = "proto3";

package geecachepb;
option go_package = "./";

message Request {
  string group = 1;
  string key = 2;
}

message Response {
  bytes value = 1;
}

service GroupCache {
  rpc Get(Request) returns (Response);
}
  • Request
    • group:分组名
    • key:key
  • Responsebytes,字节数组
  • GroupCache:服务
    • Get:服务接口

2.2 生成代码

下载protochttps://github.com/protocolbuffers/protobuf/releases/tag/v24.4open in new window

安装插件:

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

生成:

$ protoc --go_out=. *.proto
$ ls 
geecachepb.pb.go  geecachepb.proto

2.3 使用接口

修改peers.go/PeerGetter

// PeerGetter is the interface that must be implemented by a peer
type PeerGetter interface {
	Get(in *pb.Request, out *pb.Response) error	
}
func (h *httpGetter) Get(in *pb.Request, out *pb.Response) error {
	...
	bytes, err := io.ReadAll(res.Body)
	if err != nil {
		return fmt.Errorf("reading response body: %v", err)
	}

	if err = proto.Unmarshal(bytes, out); err != nil {
		return fmt.Errorf("decoding respose body: %v", err)
	}

	return nil
}
func (g *Group) getFromPeer(peer PeerGetter, key string) (ByteView, error) {
	req := &pb.Request{
		Group: g.name,
		Key:   key,
	}
	res := &pb.Response{}
	err := peer.Get(req, res)
	if err != nil {
		return ByteView{}, err
	}

	return ByteView{b: res.Value}, nil
}

3. 测试

$ ./run.sh 
go: downloading github.com/golang/protobuf v1.5.0
go: downloading google.golang.org/protobuf v1.31.0
2023/10/11 07:48:54 geecache is running at http://localhost:8002
2023/10/11 07:48:54 geecache is running at http://localhost:8001
2023/10/11 07:48:54 geecache is running at http://localhost:8003
2023/10/11 07:48:54 fontend server is running at http://localhost:9999
>>> start test
2023/10/11 07:48:55 [Server http://localhost:8003] Pick peer http://localhost:8001
2023/10/11 07:48:55 [Server http://localhost:8001] GET /geecache/scores/Tom
2023/10/11 07:48:55 [SlowDB] search key Tom
630630

Reference

  1. https://geektutu.com/post/geecache-day7.htmlopen in new window
上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.2