3. HTTP 服务端

Kesa...大约 1 分钟golang

https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/GeeCache/day3-http-serveropen in new window

DAY3-HTTP-SERVER
│  go.mod
│  go.work
│  main.go
│  
└─geecache
    │  byteview.go
    │  cache.go
    │  geecache.go
    │  geecache_test.go
    │  go.mod
    │  http.go
    │
    └─lru
            lru.go
            lru_test.go

1. HTTP 服务端

分布式缓存需要实现节点间的通信,可以基于 HTTP 建立通信机制。

1.1 http

const defaultBasePath = "/geecache/"

var _ http.Handler = (*HTTPPool)(nil)

// HTTPPool implements PeerPicker for a pool of HTTP peers
type HTTPPool struct {
	self     string // 自己的地址,主机+端口
	basePath string // 节点间通讯地址的前缀
}

func NewHTTPPool(addr string) *HTTPPool {
	return &HTTPPool{
		self:     addr,
		basePath: defaultBasePath,
	}
}

func (p *HTTPPool) Log(format string, v ...any) {
	log.Printf("[Server %s] %s", p.self, fmt.Sprintf(format, v...))
}

func (p *HTTPPool) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	path := req.URL.Path
	if !strings.HasPrefix(path, p.basePath) {
		panic("HTTPPool serving unexpected path: " + path)
	}
	p.Log("%s %s", req.Method, path)

	// /<basepath>/<groupname>/<key> required
	parts := strings.SplitN(path[len(p.basePath):], "/", 2)
	if len(parts) != 2 {
		http.Error(w, "bad request", http.StatusBadRequest)
		return
	}

	groupName := parts[0]
	key := parts[1]

	group := GetGroup(groupName)
	if group == nil {
		http.Error(w, "no such group: "+groupName, http.StatusNotFound)
		return
	}

	view, err := group.Get(key)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

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

HTTPPool

  • self:当前主机的地址,例如:http://example.com:8000
  • basePath:节点间通讯地址前缀,默认为defaultBasePath;例如:http://example.com:8000/geecache/...

ServeHTTP流程:

  1. 检查请求路径
  2. 从请求路径中解析出group namekey
  3. 通过group name获取 group
  4. 通过key获取 value
  5. 将 value 写入 http response

2. Demo 测试


var db = map[string]string{
	"Tom":  "630",
	"Jack": "589",
	"Sam":  "567",
}

func main() {
	geecache.NewGroup(
		"score",
		2<<10,
		geecache.GetterFunc(func(key string) ([]byte, error) {
			log.Println("[SlowDB] search key", key)
			if v, ok := db[key]; ok {
				return []byte(v), nil
			}
			return nil, fmt.Errorf("%s not exist", key)
		}))

	addr := "localhost:8000"
	peers := geecache.NewHTTPPool(addr)
	log.Println("geecache is running at", addr)
	log.Fatal(http.ListenAndServe(addr, peers))
}

D:\tmp>curl http://localhost:8000/geecache/score/Tom
630
D:\tmp>curl http://localhost:8000/geecache/score/
key is required
D:\tmp>curl http://localhost:8000/geecache/score/Alice
Alice not exist

Reference

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