Skip to content

Commit

Permalink
✨ feat: Day7 使用 Protobuf 通信
Browse files Browse the repository at this point in the history
1. 使用 Protobuf 通信
2. 添加运行脚本
  • Loading branch information
p3ddd committed Apr 7, 2022
1 parent 151c2ec commit d06f648
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 18 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
## 分布式缓存

#### 一致性哈希
1.为了解决资源限制的问题,实现了 LRU 缓存淘汰算法

对于给定的 key,每次都选择同一个节点
2.实现了单机并发,并给用户提供了自定义数据源的回调函数

3.实现了 HTTP 服务端

4.实现了一致性哈希算法,解决远程节点的挑选问题

节点固定时:
5.创建 HTTP 客户端,实现了多节点间的通信

把 key 的每一个字符的 ASCII 码加起来,除以 10 取余数
6.实现了 singleflight 解决缓存击穿的问题

hash('Tom') % 10
7.使用 protobuf 库,优化了节点间通信的性能

#### 一致性哈希

对于给定的 key,每次都选择同一个节点

#### 防止缓存击穿

Expand Down
11 changes: 9 additions & 2 deletions geecache.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package geecache

import (
"fmt"
"geecache/pb"
"geecache/singleflight"
"log"
"sync"
Expand Down Expand Up @@ -109,11 +110,17 @@ func (g *Group) load(key string) (value ByteView, err error) {

// getFromPeer 使用实现了 PeerGetter 接口的 httpGetter 从访问远程节点,获取缓存值
func (g *Group) getFromPeer(peer PeerGetter, key string) (ByteView, error) {
bytes, err := peer.Get(g.name, key)
// bytes, err := peer.Get(g.name, key)
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: bytes}, nil
return ByteView{b: res.Value}, nil
}

func (g *Group) getLocally(key string) (ByteView, error) {
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module geecache

go 1.18

require google.golang.org/protobuf v1.28.0 // indirect
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
26 changes: 16 additions & 10 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package geecache
import (
"fmt"
"geecache/consistenthash"
"geecache/pb"
"io/ioutil"
"log"
"net/http"
"net/url"
"strings"
"sync"

"google.golang.org/protobuf/proto"
)

const (
Expand Down Expand Up @@ -62,14 +65,13 @@ func (p *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

view, err := group.Get(key)
body, err := proto.Marshal(&pb.Response{Value: view.ByteSlice()})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/octet-stream")
w.Write(view.ByteSlice())
// log.Println(view.ByteSlice())
w.Write(body)
}

// Set updates the pool's list of peers
Expand Down Expand Up @@ -101,29 +103,33 @@ type httpGetter struct {
baseURL string
}

func (h *httpGetter) Get(group string, key string) ([]byte, error) {
func (h *httpGetter) Get(in *pb.Request, out *pb.Response) error {
u := fmt.Sprintf(
"%v%v/%v",
h.baseURL,
url.QueryEscape(group),
url.QueryEscape(key),
url.QueryEscape(in.GetGroup()),
url.QueryEscape(in.GetKey()),
)
res, err := http.Get(u)
if err != nil {
return nil, err
return err
}
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("server returned: %v", res.Status)
return fmt.Errorf("server returned: %v", res.Status)
}

bytes, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("reading response body: %v", err)
return fmt.Errorf("reading response body: %v", err)
}

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

return bytes, nil
return nil
}

var _ PeerGetter = (*httpGetter)(nil)
File renamed without changes.
14 changes: 14 additions & 0 deletions main/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
trap "rm cache_server;kill 0" EXIT

go build -o cache_server.exe
./cache_server.exe -port=8001 &
./cache_server.exe -port=8002 &
./cache_server.exe -port=8003 -api=1&

sleep 2
echo ">>> start test"
curl "http:https://localhost:9999/api?key=Tom" &
curl "http:https://localhost:9999/api?key=Tom" &
curl "http:https://localhost:9999/api?key=Tom" &

wait
217 changes: 217 additions & 0 deletions pb/pb.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions pb/pb.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

package pb;

option go_package = "../pb";

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

message Response {
bytes value = 1;
}

service GroupCache {
rpc Get(Request) returns (Response);
}
Loading

0 comments on commit d06f648

Please sign in to comment.