From 0486fdeeb8731d52d1eb1f993f2369cd00c5fb3e Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Wed, 28 Feb 2018 17:45:18 +0800 Subject: [PATCH 1/7] fix health status with tls enabled --- server/api/label.go | 2 +- server/api/server.go | 5 +++++ server/api/store.go | 25 ++++++++++++++----------- server/api/util.go | 14 ++++++++++---- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/server/api/label.go b/server/api/label.go index 890ecfeffab..390c94124b3 100644 --- a/server/api/label.go +++ b/server/api/label.go @@ -76,7 +76,7 @@ func (h *labelsHandler) GetStores(w http.ResponseWriter, r *http.Request) { stores := cluster.GetStores() storesInfo := &storesInfo{ - Stores: make([]*storeInfo, 0, len(stores)), + Stores: make([]*StoreInfo, 0, len(stores)), } stores = filter.filter(stores) diff --git a/server/api/server.go b/server/api/server.go index 42247847412..24dc5494af5 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -38,5 +38,10 @@ func NewHandler(svr *server.Server) http.Handler { engine.UseHandler(router) + tlsConfig, _ := svr.GetSecurityConfig().ToTLSConfig() + client = &http.Client{Transport: &http.Transport{ + TLSClientConfig: tlsConfig, + }} + return engine } diff --git a/server/api/store.go b/server/api/store.go index b2c8ebf9f59..41374f5df90 100644 --- a/server/api/store.go +++ b/server/api/store.go @@ -28,12 +28,14 @@ import ( "github.com/unrolled/render" ) -type metaStore struct { +// MetaStore contains meta information about a store. +type MetaStore struct { *metapb.Store StateName string `json:"state_name"` } -type storeStatus struct { +// StoreStatus contains status about a store. +type StoreStatus struct { Capacity typeutil.ByteSize `json:"capacity,omitempty"` Available typeutil.ByteSize `json:"available,omitempty"` LeaderCount int `json:"leader_count,omitempty"` @@ -53,9 +55,10 @@ type storeStatus struct { Uptime *typeutil.Duration `json:"uptime,omitempty"` } -type storeInfo struct { - Store *metaStore `json:"store"` - Status *storeStatus `json:"status"` +// StoreInfo contains information about a store. +type StoreInfo struct { + Store *MetaStore `json:"store"` + Status *StoreStatus `json:"status"` } const ( @@ -63,13 +66,13 @@ const ( downStateName = "Down" ) -func newStoreInfo(store *core.StoreInfo, maxStoreDownTime time.Duration) *storeInfo { - s := &storeInfo{ - Store: &metaStore{ +func newStoreInfo(store *core.StoreInfo, maxStoreDownTime time.Duration) *StoreInfo { + s := &StoreInfo{ + Store: &MetaStore{ Store: store.Store, StateName: store.State.String(), }, - Status: &storeStatus{ + Status: &StoreStatus{ Capacity: typeutil.ByteSize(store.Stats.GetCapacity()), Available: typeutil.ByteSize(store.Stats.GetAvailable()), LeaderCount: store.LeaderCount, @@ -111,7 +114,7 @@ func newStoreInfo(store *core.StoreInfo, maxStoreDownTime time.Duration) *storeI type storesInfo struct { Count int `json:"count"` - Stores []*storeInfo `json:"stores"` + Stores []*StoreInfo `json:"stores"` } type storeHandler struct { @@ -324,7 +327,7 @@ func (h *storesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { stores := cluster.GetStores() storesInfo := &storesInfo{ - Stores: make([]*storeInfo, 0, len(stores)), + Stores: make([]*StoreInfo, 0, len(stores)), } urlFilter, err := newStoreStateFilter(r.URL) diff --git a/server/api/util.go b/server/api/util.go index 4cbb808f85f..b4742888a53 100644 --- a/server/api/util.go +++ b/server/api/util.go @@ -23,6 +23,8 @@ import ( "github.com/juju/errors" ) +var client = &http.Client{} + func readJSON(r io.ReadCloser, data interface{}) error { defer r.Close() @@ -38,8 +40,8 @@ func readJSON(r io.ReadCloser, data interface{}) error { return nil } -func postJSON(cli *http.Client, url string, data []byte) error { - resp, err := cli.Post(url, "application/json", bytes.NewBuffer(data)) +func postJSON(url string, data []byte) error { + resp, err := client.Post(url, "application/json", bytes.NewBuffer(data)) if err != nil { return errors.Trace(err) } @@ -59,7 +61,7 @@ func doDelete(url string) error { if err != nil { return err } - res, err := http.DefaultClient.Do(req) + res, err := client.Do(req) if err != nil { return err } @@ -68,7 +70,11 @@ func doDelete(url string) error { } func doGet(url string) error { - resp, err := http.Get(url) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err + } + resp, err := client.Do(req) if err != nil { return errors.Trace(err) } From ac203475067f9465b71b31d9091e0e37b2282a78 Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Fri, 2 Mar 2018 15:04:47 +0800 Subject: [PATCH 2/7] fix data race --- cmd/pd-server/main.go | 4 ++++ server/api/config_test.go | 35 ++++++++++++++--------------------- server/api/health.go | 2 +- server/api/operator_test.go | 4 ++-- server/api/scheduler_test.go | 3 +-- server/api/server.go | 15 ++++++++++++--- server/api/store_ns_test.go | 3 +-- server/api/store_test.go | 26 +++++++++++++------------- server/api/util.go | 10 +++++----- 9 files changed, 53 insertions(+), 49 deletions(-) diff --git a/cmd/pd-server/main.go b/cmd/pd-server/main.go index 0735a2c5b7b..1932f1f1386 100644 --- a/cmd/pd-server/main.go +++ b/cmd/pd-server/main.go @@ -91,6 +91,10 @@ func main() { log.Fatalf("create server failed: %v", errors.ErrorStack(err)) } + if err = api.InitHTTPClient(svr); err != nil { + log.Fatalf("initial http client for api handler failed: %v", errors.ErrorStack(err)) + } + sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGHUP, diff --git a/server/api/config_test.go b/server/api/config_test.go index ce5e5cb6661..26e73b11304 100644 --- a/server/api/config_test.go +++ b/server/api/config_test.go @@ -14,10 +14,8 @@ package api import ( - "bytes" "encoding/json" "math/rand" - "net/http" "time" . "github.com/pingcap/check" @@ -27,11 +25,6 @@ import ( var _ = Suite(&testConfigSuite{}) type testConfigSuite struct { - hc *http.Client -} - -func (s *testConfigSuite) SetUpSuite(c *C) { - s.hc = newHTTPClient() } func checkConfigResponse(c *C, body []byte, cfgs []*server.Config) { @@ -47,7 +40,7 @@ func (s *testConfigSuite) TestConfigAll(c *C) { defer clean() addr := cfgs[rand.Intn(len(cfgs))].ClientUrls + apiPrefix + "/api/v1/config" - resp, err := s.hc.Get(addr) + resp, err := doGet(addr) c.Assert(err, IsNil) cfg := &server.Config{} err = readJSON(resp.Body, cfg) @@ -56,7 +49,7 @@ func (s *testConfigSuite) TestConfigAll(c *C) { r := map[string]int{"max-replicas": 5} postData, err := json.Marshal(r) c.Assert(err, IsNil) - err = postJSON(s.hc, addr, postData) + err = postJSON(addr, postData) c.Assert(err, IsNil) l := map[string]interface{}{ "location-labels": "zone,rack", @@ -64,10 +57,10 @@ func (s *testConfigSuite) TestConfigAll(c *C) { } postData, err = json.Marshal(l) c.Assert(err, IsNil) - err = postJSON(s.hc, addr, postData) + err = postJSON(addr, postData) c.Assert(err, IsNil) - resp, err = s.hc.Get(addr) + resp, err = doGet(addr) newCfg := &server.Config{} err = readJSON(resp.Body, newCfg) c.Assert(err, IsNil) @@ -85,7 +78,7 @@ func (s *testConfigSuite) TestConfigSchedule(c *C) { defer clean() addr := cfgs[rand.Intn(len(cfgs))].ClientUrls + apiPrefix + "/api/v1/config/schedule" - resp, err := s.hc.Get(addr) + resp, err := doGet(addr) c.Assert(err, IsNil) sc := &server.ScheduleConfig{} readJSON(resp.Body, sc) @@ -93,10 +86,10 @@ func (s *testConfigSuite) TestConfigSchedule(c *C) { sc.MaxStoreDownTime.Duration = time.Second postData, err := json.Marshal(sc) postAddr := cfgs[rand.Intn(len(cfgs))].ClientUrls + apiPrefix + "/api/v1/config/schedule" - err = postJSON(s.hc, postAddr, postData) + err = postJSON(postAddr, postData) c.Assert(err, IsNil) - resp, err = s.hc.Get(addr) + resp, err = doGet(addr) c.Assert(err, IsNil) sc1 := &server.ScheduleConfig{} readJSON(resp.Body, sc1) @@ -112,7 +105,7 @@ func (s *testConfigSuite) TestConfigReplication(c *C) { defer clean() addr := cfgs[rand.Intn(len(cfgs))].ClientUrls + apiPrefix + "/api/v1/config/replicate" - resp, err := s.hc.Get(addr) + resp, err := doGet(addr) c.Assert(err, IsNil) rc := &server.ReplicationConfig{} @@ -124,15 +117,15 @@ func (s *testConfigSuite) TestConfigReplication(c *C) { rc1 := map[string]int{"max-replicas": 5} postData, err := json.Marshal(rc1) postAddr := cfgs[rand.Intn(len(cfgs))].ClientUrls + apiPrefix + "/api/v1/config/replicate" - err = postJSON(s.hc, postAddr, postData) + err = postJSON(postAddr, postData) c.Assert(err, IsNil) rc.LocationLabels = []string{"zone", "rack"} rc2 := map[string]string{"location-labels": "zone,rack"} postData, err = json.Marshal(rc2) - err = postJSON(s.hc, postAddr, postData) + err = postJSON(postAddr, postData) - resp, err = s.hc.Get(addr) + resp, err = doGet(addr) c.Assert(err, IsNil) rc3 := &server.ReplicationConfig{} @@ -149,7 +142,7 @@ func (s *testConfigSuite) TestConfigLabelProperty(c *C) { addr := svr.GetAddr() + apiPrefix + "/api/v1/config/label-property" loadProperties := func() server.LabelPropertyConfig { - res, err := s.hc.Get(addr) + res, err := doGet(addr) c.Assert(err, IsNil) var cfg server.LabelPropertyConfig err = readJSON(res.Body, &cfg) @@ -166,7 +159,7 @@ func (s *testConfigSuite) TestConfigLabelProperty(c *C) { `{"type": "bar", "action": "set", "label-key": "host", "label-value": "h1"}`, } for _, cmd := range cmds { - _, err := s.hc.Post(addr, "application/json", bytes.NewBufferString(cmd)) + err := postJSON(addr, []byte(cmd)) c.Assert(err, IsNil) } cfg = loadProperties() @@ -182,7 +175,7 @@ func (s *testConfigSuite) TestConfigLabelProperty(c *C) { `{"type": "bar", "action": "delete", "label-key": "host", "label-value": "h1"}`, } for _, cmd := range cmds { - _, err := s.hc.Post(addr, "application/json", bytes.NewBufferString(cmd)) + err := postJSON(addr, []byte(cmd)) c.Assert(err, IsNil) } cfg = loadProperties() diff --git a/server/api/health.go b/server/api/health.go index f3b22a67b2c..aa4451de4d3 100644 --- a/server/api/health.go +++ b/server/api/health.go @@ -56,7 +56,7 @@ func (h *healthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Health: true, } for _, cURL := range member.ClientUrls { - if err := doGet(fmt.Sprintf("%s%s%s", cURL, apiPrefix, pingAPI)); err != nil { + if _, err := doGet(fmt.Sprintf("%s%s%s", cURL, apiPrefix, pingAPI)); err != nil { h.Health = false } } diff --git a/server/api/operator_test.go b/server/api/operator_test.go index e19ff705be6..e5b0a831f5d 100644 --- a/server/api/operator_test.go +++ b/server/api/operator_test.go @@ -64,7 +64,7 @@ func (s *testOperatorSuite) TestAddRemovePeer(c *C) { c.Assert(strings.Contains(operator, "operator not found"), IsTrue) mustPutStore(c, s.svr, 3, metapb.StoreState_Up, nil) - err := postJSON(&http.Client{}, fmt.Sprintf("%s/operators", s.urlPrefix), []byte(`{"name":"add-peer", "region_id": 1, "store_id": 3}`)) + err := postJSON(fmt.Sprintf("%s/operators", s.urlPrefix), []byte(`{"name":"add-peer", "region_id": 1, "store_id": 3}`)) c.Assert(err, IsNil) operator = mustReadURL(c, regionURL) c.Assert(strings.Contains(operator, "add peer 1 on store 3"), IsTrue) @@ -72,7 +72,7 @@ func (s *testOperatorSuite) TestAddRemovePeer(c *C) { err = doDelete(regionURL) c.Assert(err, IsNil) - err = postJSON(&http.Client{}, fmt.Sprintf("%s/operators", s.urlPrefix), []byte(`{"name":"remove-peer", "region_id": 1, "store_id": 2}`)) + err = postJSON(fmt.Sprintf("%s/operators", s.urlPrefix), []byte(`{"name":"remove-peer", "region_id": 1, "store_id": 2}`)) c.Assert(err, IsNil) operator = mustReadURL(c, regionURL) c.Log(operator) diff --git a/server/api/scheduler_test.go b/server/api/scheduler_test.go index 63d3de0d87b..1367aac7a06 100644 --- a/server/api/scheduler_test.go +++ b/server/api/scheduler_test.go @@ -16,7 +16,6 @@ package api import ( "encoding/json" "fmt" - "net/http" . "github.com/pingcap/check" "github.com/pingcap/kvproto/pkg/metapb" @@ -90,7 +89,7 @@ func (s *testScheduleSuite) testAddAndRemoveScheduler(name, createdName string, if createdName == "" { createdName = name } - err := postJSON(&http.Client{}, s.urlPrefix, body) + err := postJSON(s.urlPrefix, body) c.Assert(err, IsNil) handler := s.svr.GetHandler() sches, err := handler.GetSchedulers() diff --git a/server/api/server.go b/server/api/server.go index 24dc5494af5..225f9e55448 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -17,6 +17,7 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/juju/errors" "github.com/pingcap/pd/server" "github.com/urfave/negroni" ) @@ -38,10 +39,18 @@ func NewHandler(svr *server.Server) http.Handler { engine.UseHandler(router) - tlsConfig, _ := svr.GetSecurityConfig().ToTLSConfig() + return engine +} + +// InitHTTPClient initials a http client for api handler. +func InitHTTPClient(svr *server.Server) error { + tlsConfig, err := svr.GetSecurityConfig().ToTLSConfig() + if err != nil { + return errors.Trace(err) + } + client = &http.Client{Transport: &http.Transport{ TLSClientConfig: tlsConfig, }} - - return engine + return nil } diff --git a/server/api/store_ns_test.go b/server/api/store_ns_test.go index 246f7dda3bd..dab03b36306 100644 --- a/server/api/store_ns_test.go +++ b/server/api/store_ns_test.go @@ -16,7 +16,6 @@ package api import ( "encoding/json" "fmt" - "net/http" . "github.com/pingcap/check" "github.com/pingcap/kvproto/pkg/metapb" @@ -90,6 +89,6 @@ func (s *testStoreNsSuite) TestCreateNamespace(c *C) { body := map[string]string{"namespace": "test"} b, err := json.Marshal(body) c.Assert(err, IsNil) - err = postJSON(&http.Client{}, fmt.Sprintf("%s/classifier/table/namespaces", s.urlPrefix), b) + err = postJSON(fmt.Sprintf("%s/classifier/table/namespaces", s.urlPrefix), b) c.Assert(err, IsNil) } diff --git a/server/api/store_test.go b/server/api/store_test.go index ef0cfba0143..92f70601f7f 100644 --- a/server/api/store_test.go +++ b/server/api/store_test.go @@ -81,7 +81,7 @@ func (s *testStoreSuite) TearDownSuite(c *C) { s.cleanup() } -func checkStoresInfo(c *C, ss []*storeInfo, want []*metapb.Store) { +func checkStoresInfo(c *C, ss []*StoreInfo, want []*metapb.Store) { c.Assert(len(ss), Equals, len(want)) mapWant := make(map[uint64]*metapb.Store) for _, s := range want { @@ -117,15 +117,15 @@ func (s *testStoreSuite) TestStoresList(c *C) { func (s *testStoreSuite) TestStoreGet(c *C) { url := fmt.Sprintf("%s/store/1", s.urlPrefix) - info := new(storeInfo) + info := new(StoreInfo) err := readJSONWithURL(url, info) c.Assert(err, IsNil) - checkStoresInfo(c, []*storeInfo{info}, s.stores[:1]) + checkStoresInfo(c, []*StoreInfo{info}, s.stores[:1]) } func (s *testStoreSuite) TestStoreLabel(c *C) { url := fmt.Sprintf("%s/store/1", s.urlPrefix) - var info storeInfo + var info StoreInfo err := readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.Labels, HasLen, 0) @@ -134,7 +134,7 @@ func (s *testStoreSuite) TestStoreLabel(c *C) { labels := map[string]string{"zone": "cn", "host": "local"} b, err := json.Marshal(labels) c.Assert(err, IsNil) - err = postJSON(&http.Client{}, url+"/label", b) + err = postJSON(url+"/label", b) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) @@ -148,7 +148,7 @@ func (s *testStoreSuite) TestStoreLabel(c *C) { labels = map[string]string{"zack": "zack1", "Host": "host1"} b, err = json.Marshal(labels) c.Assert(err, IsNil) - err = postJSON(&http.Client{}, url+"/label", b) + err = postJSON(url+"/label", b) c.Assert(err, IsNil) expectLabel := map[string]string{"zone": "cn", "zack": "zack1", "host": "host1"} @@ -190,30 +190,30 @@ func (s *testStoreSuite) TestStoreDelete(c *C) { func (s *testStoreSuite) TestStoreSetState(c *C) { url := fmt.Sprintf("%s/store/1", s.urlPrefix) - info := storeInfo{} + info := StoreInfo{} err := readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.State, Equals, metapb.StoreState_Up) // Set to Offline. - info = storeInfo{} - err = postJSON(&http.Client{}, url+"/state?state=Offline", nil) + info = StoreInfo{} + err = postJSON(url+"/state?state=Offline", nil) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.State, Equals, metapb.StoreState_Offline) // Invalid state. - info = storeInfo{} - err = postJSON(&http.Client{}, url+"/state?state=Foo", nil) + info = StoreInfo{} + err = postJSON(url+"/state?state=Foo", nil) c.Assert(err, NotNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.State, Equals, metapb.StoreState_Offline) // Set back to Up. - info = storeInfo{} - err = postJSON(&http.Client{}, url+"/state?state=Up", nil) + info = StoreInfo{} + err = postJSON(url+"/state?state=Up", nil) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) diff --git a/server/api/util.go b/server/api/util.go index b4742888a53..02c984e797c 100644 --- a/server/api/util.go +++ b/server/api/util.go @@ -69,17 +69,17 @@ func doDelete(url string) error { return nil } -func doGet(url string) error { +func doGet(url string) (*http.Response, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { - return err + return nil, err } resp, err := client.Do(req) if err != nil { - return errors.Trace(err) + return nil, errors.Trace(err) } if resp.StatusCode != http.StatusOK { - return errors.Errorf("http get url %s return code %d", url, resp.StatusCode) + return nil, errors.Errorf("http get url %s return code %d", url, resp.StatusCode) } - return nil + return resp, nil } From f4bec2939fd2905002e23adcb985a37e5077f0db Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Fri, 2 Mar 2018 16:30:12 +0800 Subject: [PATCH 3/7] reuse dialClient in redriector --- server/api/redirector.go | 16 +++------------- server/api/server.go | 7 +++++-- server/api/util.go | 8 +++----- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/server/api/redirector.go b/server/api/redirector.go index 9272c585fb7..f52fcb45a58 100644 --- a/server/api/redirector.go +++ b/server/api/redirector.go @@ -14,7 +14,6 @@ package api import ( - "crypto/tls" "io/ioutil" "net/http" "net/url" @@ -68,12 +67,7 @@ func (h *redirector) ServeHTTP(w http.ResponseWriter, r *http.Request, next http return } - tlsConfig, err := h.s.GetSecurityConfig().ToTLSConfig() - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - newCustomReverseProxies(urls, tlsConfig).ServeHTTP(w, r) + newCustomReverseProxies(urls).ServeHTTP(w, r) } type customReverseProxies struct { @@ -81,13 +75,9 @@ type customReverseProxies struct { client *http.Client } -func newCustomReverseProxies(urls []url.URL, tlsConfig *tls.Config) *customReverseProxies { +func newCustomReverseProxies(urls []url.URL) *customReverseProxies { p := &customReverseProxies{ - client: &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: tlsConfig, - }, - }, + client: dialClient, } p.urls = append(p.urls, urls...) diff --git a/server/api/server.go b/server/api/server.go index 225f9e55448..883a9e3606e 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -24,6 +24,8 @@ import ( const apiPrefix = "/pd" +var dialClient = &http.Client{} + // NewHandler creates a HTTP handler for API. func NewHandler(svr *server.Server) http.Handler { engine := negroni.New() @@ -49,8 +51,9 @@ func InitHTTPClient(svr *server.Server) error { return errors.Trace(err) } - client = &http.Client{Transport: &http.Transport{ - TLSClientConfig: tlsConfig, + dialClient = &http.Client{Transport: &http.Transport{ + TLSClientConfig: tlsConfig, + DisableKeepAlives: true, }} return nil } diff --git a/server/api/util.go b/server/api/util.go index 02c984e797c..e1135cc1065 100644 --- a/server/api/util.go +++ b/server/api/util.go @@ -23,8 +23,6 @@ import ( "github.com/juju/errors" ) -var client = &http.Client{} - func readJSON(r io.ReadCloser, data interface{}) error { defer r.Close() @@ -41,7 +39,7 @@ func readJSON(r io.ReadCloser, data interface{}) error { } func postJSON(url string, data []byte) error { - resp, err := client.Post(url, "application/json", bytes.NewBuffer(data)) + resp, err := dialClient.Post(url, "application/json", bytes.NewBuffer(data)) if err != nil { return errors.Trace(err) } @@ -61,7 +59,7 @@ func doDelete(url string) error { if err != nil { return err } - res, err := client.Do(req) + res, err := dialClient.Do(req) if err != nil { return err } @@ -74,7 +72,7 @@ func doGet(url string) (*http.Response, error) { if err != nil { return nil, err } - resp, err := client.Do(req) + resp, err := dialClient.Do(req) if err != nil { return nil, errors.Trace(err) } From 37a0f86faaee8c489031a6887076bac170fdb1fd Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Fri, 2 Mar 2018 16:36:56 +0800 Subject: [PATCH 4/7] unexport --- server/api/store.go | 28 ++++++++++++++-------------- server/api/store_test.go | 26 +++++++++++++------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/server/api/store.go b/server/api/store.go index 41374f5df90..f15037a0e5c 100644 --- a/server/api/store.go +++ b/server/api/store.go @@ -28,14 +28,14 @@ import ( "github.com/unrolled/render" ) -// MetaStore contains meta information about a store. -type MetaStore struct { +// metaStore contains meta information about a store. +type metaStore struct { *metapb.Store StateName string `json:"state_name"` } -// StoreStatus contains status about a store. -type StoreStatus struct { +// storeStatus contains status about a store. +type storeStatus struct { Capacity typeutil.ByteSize `json:"capacity,omitempty"` Available typeutil.ByteSize `json:"available,omitempty"` LeaderCount int `json:"leader_count,omitempty"` @@ -55,10 +55,10 @@ type StoreStatus struct { Uptime *typeutil.Duration `json:"uptime,omitempty"` } -// StoreInfo contains information about a store. -type StoreInfo struct { - Store *MetaStore `json:"store"` - Status *StoreStatus `json:"status"` +// storeInfo contains information about a store. +type storeInfo struct { + Store *metaStore `json:"store"` + Status *storeStatus `json:"status"` } const ( @@ -66,13 +66,13 @@ const ( downStateName = "Down" ) -func newStoreInfo(store *core.StoreInfo, maxStoreDownTime time.Duration) *StoreInfo { - s := &StoreInfo{ - Store: &MetaStore{ +func newStoreInfo(store *core.StoreInfo, maxStoreDownTime time.Duration) *storeInfo { + s := &storeInfo{ + Store: &metaStore{ Store: store.Store, StateName: store.State.String(), }, - Status: &StoreStatus{ + Status: &storeStatus{ Capacity: typeutil.ByteSize(store.Stats.GetCapacity()), Available: typeutil.ByteSize(store.Stats.GetAvailable()), LeaderCount: store.LeaderCount, @@ -114,7 +114,7 @@ func newStoreInfo(store *core.StoreInfo, maxStoreDownTime time.Duration) *StoreI type storesInfo struct { Count int `json:"count"` - Stores []*StoreInfo `json:"stores"` + Stores []*storeInfo `json:"stores"` } type storeHandler struct { @@ -327,7 +327,7 @@ func (h *storesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { stores := cluster.GetStores() storesInfo := &storesInfo{ - Stores: make([]*StoreInfo, 0, len(stores)), + Stores: make([]*storeInfo, 0, len(stores)), } urlFilter, err := newStoreStateFilter(r.URL) diff --git a/server/api/store_test.go b/server/api/store_test.go index 92f70601f7f..ef0cfba0143 100644 --- a/server/api/store_test.go +++ b/server/api/store_test.go @@ -81,7 +81,7 @@ func (s *testStoreSuite) TearDownSuite(c *C) { s.cleanup() } -func checkStoresInfo(c *C, ss []*StoreInfo, want []*metapb.Store) { +func checkStoresInfo(c *C, ss []*storeInfo, want []*metapb.Store) { c.Assert(len(ss), Equals, len(want)) mapWant := make(map[uint64]*metapb.Store) for _, s := range want { @@ -117,15 +117,15 @@ func (s *testStoreSuite) TestStoresList(c *C) { func (s *testStoreSuite) TestStoreGet(c *C) { url := fmt.Sprintf("%s/store/1", s.urlPrefix) - info := new(StoreInfo) + info := new(storeInfo) err := readJSONWithURL(url, info) c.Assert(err, IsNil) - checkStoresInfo(c, []*StoreInfo{info}, s.stores[:1]) + checkStoresInfo(c, []*storeInfo{info}, s.stores[:1]) } func (s *testStoreSuite) TestStoreLabel(c *C) { url := fmt.Sprintf("%s/store/1", s.urlPrefix) - var info StoreInfo + var info storeInfo err := readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.Labels, HasLen, 0) @@ -134,7 +134,7 @@ func (s *testStoreSuite) TestStoreLabel(c *C) { labels := map[string]string{"zone": "cn", "host": "local"} b, err := json.Marshal(labels) c.Assert(err, IsNil) - err = postJSON(url+"/label", b) + err = postJSON(&http.Client{}, url+"/label", b) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) @@ -148,7 +148,7 @@ func (s *testStoreSuite) TestStoreLabel(c *C) { labels = map[string]string{"zack": "zack1", "Host": "host1"} b, err = json.Marshal(labels) c.Assert(err, IsNil) - err = postJSON(url+"/label", b) + err = postJSON(&http.Client{}, url+"/label", b) c.Assert(err, IsNil) expectLabel := map[string]string{"zone": "cn", "zack": "zack1", "host": "host1"} @@ -190,30 +190,30 @@ func (s *testStoreSuite) TestStoreDelete(c *C) { func (s *testStoreSuite) TestStoreSetState(c *C) { url := fmt.Sprintf("%s/store/1", s.urlPrefix) - info := StoreInfo{} + info := storeInfo{} err := readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.State, Equals, metapb.StoreState_Up) // Set to Offline. - info = StoreInfo{} - err = postJSON(url+"/state?state=Offline", nil) + info = storeInfo{} + err = postJSON(&http.Client{}, url+"/state?state=Offline", nil) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.State, Equals, metapb.StoreState_Offline) // Invalid state. - info = StoreInfo{} - err = postJSON(url+"/state?state=Foo", nil) + info = storeInfo{} + err = postJSON(&http.Client{}, url+"/state?state=Foo", nil) c.Assert(err, NotNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) c.Assert(info.Store.State, Equals, metapb.StoreState_Offline) // Set back to Up. - info = StoreInfo{} - err = postJSON(url+"/state?state=Up", nil) + info = storeInfo{} + err = postJSON(&http.Client{}, url+"/state?state=Up", nil) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) From a9a8b88eae4d3f6aa0aaeb8b1851a0be44840d8d Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Fri, 2 Mar 2018 16:43:50 +0800 Subject: [PATCH 5/7] disable keep alive --- server/api/server.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/api/server.go b/server/api/server.go index 883a9e3606e..a072b6bc461 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -24,7 +24,11 @@ import ( const apiPrefix = "/pd" -var dialClient = &http.Client{} +var dialClient = &http.Client{ + Transport: &http.Transport{ + DisableKeepAlives: true, + }, +} // NewHandler creates a HTTP handler for API. func NewHandler(svr *server.Server) http.Handler { From 48b7dc1836ce664c783aa3938e891848191ad8ee Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Fri, 2 Mar 2018 16:52:50 +0800 Subject: [PATCH 6/7] fix test --- server/api/label.go | 2 +- server/api/store_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/api/label.go b/server/api/label.go index 390c94124b3..890ecfeffab 100644 --- a/server/api/label.go +++ b/server/api/label.go @@ -76,7 +76,7 @@ func (h *labelsHandler) GetStores(w http.ResponseWriter, r *http.Request) { stores := cluster.GetStores() storesInfo := &storesInfo{ - Stores: make([]*StoreInfo, 0, len(stores)), + Stores: make([]*storeInfo, 0, len(stores)), } stores = filter.filter(stores) diff --git a/server/api/store_test.go b/server/api/store_test.go index ef0cfba0143..8a4bd3d0f89 100644 --- a/server/api/store_test.go +++ b/server/api/store_test.go @@ -134,7 +134,7 @@ func (s *testStoreSuite) TestStoreLabel(c *C) { labels := map[string]string{"zone": "cn", "host": "local"} b, err := json.Marshal(labels) c.Assert(err, IsNil) - err = postJSON(&http.Client{}, url+"/label", b) + err = postJSON(url+"/label", b) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) @@ -148,7 +148,7 @@ func (s *testStoreSuite) TestStoreLabel(c *C) { labels = map[string]string{"zack": "zack1", "Host": "host1"} b, err = json.Marshal(labels) c.Assert(err, IsNil) - err = postJSON(&http.Client{}, url+"/label", b) + err = postJSON(url+"/label", b) c.Assert(err, IsNil) expectLabel := map[string]string{"zone": "cn", "zack": "zack1", "host": "host1"} @@ -197,7 +197,7 @@ func (s *testStoreSuite) TestStoreSetState(c *C) { // Set to Offline. info = storeInfo{} - err = postJSON(&http.Client{}, url+"/state?state=Offline", nil) + err = postJSON(url+"/state?state=Offline", nil) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) @@ -205,7 +205,7 @@ func (s *testStoreSuite) TestStoreSetState(c *C) { // Invalid state. info = storeInfo{} - err = postJSON(&http.Client{}, url+"/state?state=Foo", nil) + err = postJSON(url+"/state?state=Foo", nil) c.Assert(err, NotNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) @@ -213,7 +213,7 @@ func (s *testStoreSuite) TestStoreSetState(c *C) { // Set back to Up. info = storeInfo{} - err = postJSON(&http.Client{}, url+"/state?state=Up", nil) + err = postJSON(url+"/state?state=Up", nil) c.Assert(err, IsNil) err = readJSONWithURL(url, &info) c.Assert(err, IsNil) From 8c8c3c8718e080f39ff95e860023c2e22e1a2c7e Mon Sep 17 00:00:00 2001 From: Connor1996 Date: Mon, 5 Mar 2018 15:11:10 +0800 Subject: [PATCH 7/7] address comment --- server/api/health.go | 4 +++- server/api/util.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/server/api/health.go b/server/api/health.go index aa4451de4d3..2b739145ea4 100644 --- a/server/api/health.go +++ b/server/api/health.go @@ -56,9 +56,11 @@ func (h *healthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Health: true, } for _, cURL := range member.ClientUrls { - if _, err := doGet(fmt.Sprintf("%s%s%s", cURL, apiPrefix, pingAPI)); err != nil { + resp, err := doGet(fmt.Sprintf("%s%s%s", cURL, apiPrefix, pingAPI)) + if err != nil { h.Health = false } + resp.Body.Close() } healths = append(healths, h) } diff --git a/server/api/util.go b/server/api/util.go index e1135cc1065..4fe270e5a3c 100644 --- a/server/api/util.go +++ b/server/api/util.go @@ -70,7 +70,7 @@ func doDelete(url string) error { func doGet(url string) (*http.Response, error) { req, err := http.NewRequest("GET", url, nil) if err != nil { - return nil, err + return nil, errors.Trace(err) } resp, err := dialClient.Do(req) if err != nil {