// ProtoGetter is the interface that must be implemented by a peer. type ProtoGetter interface { Get(ctx context.Context, in *pb.GetRequest, out *pb.GetResponse) error }
// HTTPPool implements PeerPicker for a pool of HTTP peers. type HTTPPool struct { // Context optionally specifies a context for the server to use when it // receives a request. // If nil, the server uses the request's context Context func(*http.Request)context.Context
// Transport optionally specifies an http.RoundTripper for the client // to use when it makes a request. // If nil, the client uses http.DefaultTransport. Transport func(context.Context)http.RoundTripper
// this peer's base URL, e.g. "https://example.net:8000" self string
// opts specifies the options. opts HTTPPoolOptions
mu sync.Mutex // guards peers and httpGetters peers *consistenthash.Map httpGetters map[string]*httpGetter // keyed by e.g. "http://10.0.0.2:8008" }
// Set updates the pool's list of peers. // Each peer value should be a valid base URL, // for example "http://example.net:8000". func(p *HTTPPool)Set(peers ...string) { p.mu.Lock() defer p.mu.Unlock() p.peers = consistenthash.New(p.opts.Replicas, p.opts.HashFn) p.peers.Add(peers...) p.httpGetters = make(map[string]*httpGetter, len(peers)) for _, peer := range peers { p.httpGetters[peer] = &httpGetter{transport: p.Transport, baseURL: peer + p.opts.BasePath} } }
// Fetch the value for this group/key. group := GetGroup(groupName) if group == nil { http.Error(w, "no such group: "+groupName, http.StatusNotFound) return }
调用 group 中的 Get 方法获取 key 相应的数据。Get 方法会从本地或者远程节点中获取数据,并将缓存数据返回。
1 2 3 4 5 6 7
group.Stats.ServerRequests.Add(1) var value []byte err := group.Get(ctx, key, AllocatingByteSliceSink(&value)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return }
将获取到的数据,以 protobuf 消息的方式,写入的 HTTP 响应体中。
1 2 3 4 5 6 7 8
// Write the value to the response body as a proto message. body, err := proto.Marshal(&pb.GetResponse{Value: value}) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/x-protobuf") w.Write(body)