基于HTTP的分布式缓存
目的:通过main 函数启动 HTTP Server测试API
Cache HTTP 服务端
分布式缓存需要实现节点间通信,建立基于 HTTP 的通信机制是比较常见和简单的做法。如果一个节点启动了 HTTP 服务,那么这个节点就可以被其他节点访问。
具体流程
- 默认通信地址前缀是
defaultBasePath = "/_gocache/"
。
- 首先判断url路径中是否包含 basePath。
- 把groupname/key字符截断为groupname和key。
- 通过groupname获取Group对象。
- 使用Group对象方法和key来获取key对应的缓存值。
- 将缓存值作为http body进行响应。
代码http.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package Cache
import ( "net/http" "strings" )
const defaultBasePath = "/_gocache/"
type HttpPool struct { self string basePath string }
func NewHTTPPool(self string) *HttpPool { return &HttpPool{ self: self, basePath: defaultBasePath, } }
func (hp *HttpPool) ServeHTTP(resp http.ResponseWriter, req *http.Request) { url := req.URL.Path if !strings.HasPrefix(url, hp.basePath) { panic("http request path is invalid") }
path := url[len(hp.basePath):]
parts := strings.SplitN(path, "/", 2) groupName := parts[0] key := parts[1]
group := GetGroup(groupName) if group == nil { http.Error(resp, "no such group: "+groupName, http.StatusNotFound) return }
byteview, err := group.Get(key) if err != nil { http.Error(resp, err.Error(), http.StatusInternalServerError) return } resp.Header().Set("Content-Type", "application/octet-stream") resp.Write(byteview.ByteSlice()) }
|
测试
- 使用 map 模拟了数据源 db。
- 创建一个名为 scores 的 Group,若缓存为空,回调函数会从 db 中获取数据并返回。
- 使用 http.ListenAndServe 在 9999 端口启动了 HTTP 服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package main
import ( "Cache/Cache" "fmt" "log" "net/http" )
var db = map[string]string{ "Tom": "630", "Jack": "589", "Sam": "567", }
func main() { Cache.NewGroup("scores", 2<<10, Cache.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:9999" peers := Cache.NewHTTPPool(addr) log.Println("gocache is running at", addr) log.Fatal(http.ListenAndServe(addr, peers)) }
|
测试API
总结
通过main 函数启动 HTTP Server测试API。