3. HTTP 服务端
...大约 1 分钟
https://github.com/dreamjz/golang-notes/tree/main/books/7-days-golang/GeeCache/day3-http-server
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
流程:
- 检查请求路径
- 从请求路径中解析出
group name
和key
- 通过
group name
获取group
- 通过
key
获取 value - 将 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
Powered by Waline v2.15.2