diff --git a/executor/memtable_reader.go b/executor/memtable_reader.go index 882ab3c638b52..33b2b46ee4e9d 100644 --- a/executor/memtable_reader.go +++ b/executor/memtable_reader.go @@ -180,9 +180,9 @@ func (e *clusterConfigRetriever) retrieve(_ context.Context, sctx sessionctx.Con var url string switch typ { case "pd": - url = fmt.Sprintf("http://%s%s", statusAddr, pdapi.Config) + url = fmt.Sprintf("%s://%s%s", util.InternalHTTPSchema(), statusAddr, pdapi.Config) case "tikv", "tidb": - url = fmt.Sprintf("http://%s/config", statusAddr) + url = fmt.Sprintf("%s://%s/config", util.InternalHTTPSchema(), statusAddr) default: ch <- result{err: errors.Errorf("unknown node type: %s(%s)", typ, address)} return @@ -194,7 +194,7 @@ func (e *clusterConfigRetriever) retrieve(_ context.Context, sctx sessionctx.Con return } req.Header.Add("PD-Allow-follower-handle", "true") - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { ch <- result{err: errors.Trace(err)} return diff --git a/executor/metrics_reader.go b/executor/metrics_reader.go index 6ce50a1b85560..00756e80c1cd7 100644 --- a/executor/metrics_reader.go +++ b/executor/metrics_reader.go @@ -191,7 +191,7 @@ type queryClient struct { func newQueryClient(addr string) (api.Client, error) { promClient, err := api.NewClient(api.Config{ - Address: fmt.Sprintf("http://%s", addr), + Address: fmt.Sprintf("%s://%s", util.InternalHTTPSchema(), addr), }) if err != nil { return nil, err diff --git a/infoschema/perfschema/tables.go b/infoschema/perfschema/tables.go index 35462ca1ed62a..a15f502eeae09 100644 --- a/infoschema/perfschema/tables.go +++ b/infoschema/perfschema/tables.go @@ -348,7 +348,7 @@ func dataForRemoteProfile(ctx sessionctx.Context, nodeType, uri string, isGorout go func(address string) { util.WithRecovery(func() { defer wg.Done() - url := fmt.Sprintf("http://%s%s", statusAddr, uri) + url := fmt.Sprintf("%s://%s%s", util.InternalHTTPSchema(), statusAddr, uri) req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { ch <- result{err: errors.Trace(err)} @@ -358,7 +358,7 @@ func dataForRemoteProfile(ctx sessionctx.Context, nodeType, uri string, isGorout req.Header.Add("PD-Allow-follower-handle", "true") // TiKV output svg format in default req.Header.Add("Content-Type", "application/protobuf") - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { ch <- result{err: errors.Trace(err)} return diff --git a/infoschema/tables.go b/infoschema/tables.go index 09078aef88035..85d0632ca4500 100755 --- a/infoschema/tables.go +++ b/infoschema/tables.go @@ -1353,13 +1353,13 @@ func GetPDServerInfo(ctx sessionctx.Context) ([]ServerInfo, error) { addr = strings.TrimSpace(addr) // Get PD version - url := fmt.Sprintf("http://%s%s", addr, pdapi.ClusterVersion) + url := fmt.Sprintf("%s://%s%s", util.InternalHTTPSchema(), addr, pdapi.ClusterVersion) req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, errors.Trace(err) } req.Header.Add("PD-Allow-follower-handle", "true") - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { return nil, errors.Trace(err) } @@ -1371,13 +1371,13 @@ func GetPDServerInfo(ctx sessionctx.Context) ([]ServerInfo, error) { version := strings.Trim(strings.Trim(string(pdVersion), "\n"), "\"") // Get PD git_hash - url = fmt.Sprintf("http://%s%s", addr, pdapi.Status) + url = fmt.Sprintf("%s://%s%s", util.InternalHTTPSchema(), addr, pdapi.Status) req, err = http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, errors.Trace(err) } req.Header.Add("PD-Allow-follower-handle", "true") - resp, err = http.DefaultClient.Do(req) + resp, err = util.InternalHTTPClient().Do(req) if err != nil { return nil, errors.Trace(err) } diff --git a/server/http_handler.go b/server/http_handler.go index 4ce555d89116a..1c09174464cd5 100644 --- a/server/http_handler.go +++ b/server/http_handler.go @@ -53,6 +53,7 @@ import ( "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/pdapi" @@ -1013,8 +1014,8 @@ func (h tableHandler) addScatterSchedule(startKey, endKey []byte, name string) e if err != nil { return err } - scheduleURL := fmt.Sprintf("http://%s/pd/api/v1/schedulers", pdAddrs[0]) - resp, err := http.Post(scheduleURL, "application/json", bytes.NewBuffer(v)) + scheduleURL := fmt.Sprintf("%s://%s/pd/api/v1/schedulers", util.InternalHTTPSchema(), pdAddrs[0]) + resp, err := util.InternalHTTPClient().Post(scheduleURL, "application/json", bytes.NewBuffer(v)) if err != nil { return err } @@ -1029,12 +1030,12 @@ func (h tableHandler) deleteScatterSchedule(name string) error { if err != nil { return err } - scheduleURL := fmt.Sprintf("http://%s/pd/api/v1/schedulers/scatter-range-%s", pdAddrs[0], name) + scheduleURL := fmt.Sprintf("%s://%s/pd/api/v1/schedulers/scatter-range-%s", util.InternalHTTPSchema(), pdAddrs[0], name) req, err := http.NewRequest(http.MethodDelete, scheduleURL, nil) if err != nil { return err } - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { return err } @@ -1202,12 +1203,13 @@ func (h tableHandler) handleDiskUsageRequest(schema infoschema.InfoSchema, tbl t startKey = codec.EncodeBytes([]byte{}, startKey) endKey = codec.EncodeBytes([]byte{}, endKey) - statURL := fmt.Sprintf("http://%s/pd/api/v1/stats/region?start_key=%s&end_key=%s", + statURL := fmt.Sprintf("%s://%s/pd/api/v1/stats/region?start_key=%s&end_key=%s", + util.InternalHTTPSchema(), pdAddrs[0], url.QueryEscape(string(startKey)), url.QueryEscape(string(endKey))) - resp, err := http.Get(statURL) + resp, err := util.InternalHTTPClient().Get(statURL) if err != nil { writeError(w, err) return diff --git a/server/http_status.go b/server/http_status.go index 74d29aa818224..b0928c190109f 100644 --- a/server/http_status.go +++ b/server/http_status.go @@ -134,7 +134,7 @@ func (s *Server) startHTTPServer() { host = "localhost" } baseURL := &url.URL{ - Scheme: "http", + Scheme: util.InternalHTTPSchema(), Host: fmt.Sprintf("%s:%s", host, port), } router.HandleFunc("/web/trace", traceapp.HandleTiDB).Name("Trace Viewer") diff --git a/store/helper/helper.go b/store/helper/helper.go index 45983fbf2334e..8033ee4421091 100644 --- a/store/helper/helper.go +++ b/store/helper/helper.go @@ -34,16 +34,13 @@ import ( "github.com/pingcap/tidb/store/tikv" "github.com/pingcap/tidb/store/tikv/tikvrpc" "github.com/pingcap/tidb/tablecodec" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/codec" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/pdapi" "go.uber.org/zap" ) -const ( - protocol = "http://" -) - // Helper is a middleware to get some information from tikv/pd. It can be used for TiDB's http api or mem table. type Helper struct { Store tikv.Storage @@ -127,11 +124,11 @@ func (h *Helper) FetchHotRegion(rw string) (map[uint64]RegionMetric, error) { if len(pdHosts) == 0 { return nil, errors.New("pd unavailable") } - req, err := http.NewRequest("GET", protocol+pdHosts[0]+rw, nil) + req, err := http.NewRequest("GET", util.InternalHTTPSchema()+"://"+pdHosts[0]+rw, nil) if err != nil { return nil, errors.Trace(err) } - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { return nil, errors.Trace(err) } @@ -617,12 +614,12 @@ func (h *Helper) requestPD(method, uri string, body io.Reader, res interface{}) return errors.New("pd unavailable") } - logutil.BgLogger().Debug("RequestPD URL", zap.String("url", protocol+pdHosts[0]+uri)) - req, err := http.NewRequest(method, protocol+pdHosts[0]+uri, body) + logutil.BgLogger().Debug("RequestPD URL", zap.String("url", util.InternalHTTPSchema()+"://"+pdHosts[0]+uri)) + req, err := http.NewRequest(method, util.InternalHTTPSchema()+"://"+pdHosts[0]+uri, body) if err != nil { return errors.Trace(err) } - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { return errors.Trace(err) } @@ -700,11 +697,11 @@ func (h *Helper) GetStoresStat() (*StoresStat, error) { if len(pdHosts) == 0 { return nil, errors.New("pd unavailable") } - req, err := http.NewRequest("GET", protocol+pdHosts[0]+pdapi.Stores, nil) + req, err := http.NewRequest("GET", util.InternalHTTPSchema()+"://"+pdHosts[0]+pdapi.Stores, nil) if err != nil { return nil, errors.Trace(err) } - resp, err := http.DefaultClient.Do(req) + resp, err := util.InternalHTTPClient().Do(req) if err != nil { return nil, errors.Trace(err) } diff --git a/tidb-server/main.go b/tidb-server/main.go index 87a2c0c9378f7..806f14f03f1cf 100644 --- a/tidb-server/main.go +++ b/tidb-server/main.go @@ -51,6 +51,7 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/tikv" "github.com/pingcap/tidb/store/tikv/gcworker" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/domainutil" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" @@ -541,6 +542,8 @@ func setupLog() { } else { grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, os.Stderr)) } + // trigger internal http(s) client init. + util.InternalHTTPClient() } func printInfo() { diff --git a/util/misc.go b/util/misc.go index f60708e7526d9..f727379b0c48c 100644 --- a/util/misc.go +++ b/util/misc.go @@ -19,9 +19,11 @@ import ( "crypto/x509/pkix" "fmt" "io/ioutil" + "net/http" "runtime" "strconv" "strings" + "sync" "time" "github.com/pingcap/errors" @@ -29,6 +31,7 @@ import ( "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tipb/go-tipb" @@ -398,3 +401,37 @@ func IsTLSExpiredError(err error) bool { } return true } + +var ( + internalClientInit sync.Once + internalHTTPClient *http.Client + internalHTTPSchema string +) + +// InternalHTTPClient is used by TiDB-Server to request other components. +func InternalHTTPClient() *http.Client { + internalClientInit.Do(initInternalClient) + return internalHTTPClient +} + +// InternalHTTPSchema specifies use http or https to request other components. +func InternalHTTPSchema() string { + internalClientInit.Do(initInternalClient) + return internalHTTPSchema +} + +func initInternalClient() { + tlsCfg, err := config.GetGlobalConfig().Security.ToTLSConfig() + if err != nil { + logutil.BgLogger().Fatal("could not load cluster ssl", zap.Error(err)) + } + if tlsCfg == nil { + internalHTTPSchema = "http" + internalHTTPClient = http.DefaultClient + return + } + internalHTTPSchema = "https" + internalHTTPClient = &http.Client{ + Transport: &http.Transport{TLSClientConfig: tlsCfg}, + } +}