From 02c694aabf30689058d7cf20c03f41e6e6d6a69b Mon Sep 17 00:00:00 2001 From: husharp Date: Mon, 18 Dec 2023 11:46:10 +0800 Subject: [PATCH] address comment Signed-off-by: husharp --- client/http/api.go | 2 +- server/api/micro_service.go | 91 --------------- server/api/router.go | 4 - server/apiv2/handlers/micro_service.go | 106 ++++++++++++++++++ server/apiv2/router.go | 1 + tests/integrations/mcs/members/member_test.go | 2 +- 6 files changed, 109 insertions(+), 97 deletions(-) delete mode 100644 server/api/micro_service.go create mode 100644 server/apiv2/handlers/micro_service.go diff --git a/client/http/api.go b/client/http/api.go index 7db874f13c6d..c955bc6dfefd 100644 --- a/client/http/api.go +++ b/client/http/api.go @@ -76,7 +76,7 @@ const ( Status = "/pd/api/v1/status" Version = "/pd/api/v1/version" // Micro Service - microServicePrefix = "/pd/api/v1/ms" + microServicePrefix = "/pd/api/v2/ms" ) // RegionByID returns the path of PD HTTP API to get region by ID. diff --git a/server/api/micro_service.go b/server/api/micro_service.go deleted file mode 100644 index 8d36b03f9d89..000000000000 --- a/server/api/micro_service.go +++ /dev/null @@ -1,91 +0,0 @@ -package api - -import ( - "fmt" - "net/http" - - "github.com/gorilla/mux" - "github.com/pingcap/log" - "github.com/tikv/pd/pkg/mcs/discovery" - "github.com/tikv/pd/server" - "github.com/unrolled/render" - "go.uber.org/zap" -) - -type microServiceHandler struct { - svr *server.Server - rd *render.Render -} - -func newMicroServiceHandlerHandler(svr *server.Server, rd *render.Render) *microServiceHandler { - return µServiceHandler{ - svr: svr, - rd: rd, - } -} - -// @Tags members -// @Summary Get all members of the cluster for the specified service. -// @Produce json -// @Success 200 {object} []string -// @Router /ms/members/{service} [get] -func (h *microServiceHandler) GetMembers(w http.ResponseWriter, r *http.Request) { - if !h.svr.IsAPIServiceMode() { - h.rd.JSON(w, http.StatusServiceUnavailable, "not support micro service") - return - } - - if service := mux.Vars(r)["service"]; len(service) > 0 { - resps, err := discovery.GetMembers(service, h.svr.GetClient()) - if err != nil { - h.rd.JSON(w, http.StatusInternalServerError, err.Error()) - return - } - if resps == nil { - h.rd.JSON(w, http.StatusNotFound, fmt.Sprintf("no members for %s", service)) - return - } - - var addrs []string - for _, resp := range resps.Responses { - for _, keyValue := range resp.GetResponseRange().GetKvs() { - var entry discovery.ServiceRegistryEntry - if err = entry.Deserialize(keyValue.Value); err != nil { - log.Info("deserialize failed", zap.String("key", string(keyValue.Key)), zap.Error(err)) - } - addrs = append(addrs, entry.ServiceAddr) - } - } - h.rd.JSON(w, http.StatusOK, addrs) - return - } - - h.rd.JSON(w, http.StatusInternalServerError, "please specify service") -} - -// @Tags Primary -// @Summary Get the primary of the cluster for the specified service. -// @Produce json -// @Success 200 {object} pdpb.Member -// @Router /ms/primary/{service} [get] -func (h *microServiceHandler) GetPrimary(w http.ResponseWriter, r *http.Request) { - if !h.svr.IsAPIServiceMode() { - h.rd.JSON(w, http.StatusServiceUnavailable, "not support micro service") - return - } - if service := mux.Vars(r)["service"]; len(service) > 0 { - primary, _, err := discovery.GetMCSPrimary(service, h.svr.GetClient(), r.URL.Query().Get("keyspace_id")) - if err != nil { - h.rd.JSON(w, http.StatusInternalServerError, err.Error()) - return - } - if primary == nil { - h.rd.JSON(w, http.StatusNotFound, fmt.Sprintf("no primary for %s", service)) - return - } - h.rd.JSON(w, http.StatusOK, primary) - return - } - - h.rd.JSON(w, http.StatusInternalServerError, "please specify service") -} diff --git a/server/api/router.go b/server/api/router.go index 718fad81dba8..d3c8f10cbf2d 100644 --- a/server/api/router.go +++ b/server/api/router.go @@ -295,10 +295,6 @@ func createRouter(prefix string, svr *server.Server) *mux.Router { registerFunc(apiRouter, "/leader/resign", leaderHandler.ResignLeader, setMethods(http.MethodPost), setAuditBackend(localLog, prometheus)) registerFunc(apiRouter, "/leader/transfer/{next_leader}", leaderHandler.TransferLeader, setMethods(http.MethodPost), setAuditBackend(localLog, prometheus)) - msHandler := newMicroServiceHandlerHandler(svr, rd) - registerFunc(apiRouter, "/ms/members/{service}", msHandler.GetMembers, setMethods(http.MethodGet), setAuditBackend(prometheus)) - registerFunc(apiRouter, "/ms/primary/{service}", msHandler.GetPrimary, setMethods(http.MethodGet), setAuditBackend(prometheus)) - statsHandler := newStatsHandler(svr, rd) registerFunc(clusterRouter, "/stats/region", statsHandler.GetRegionStatus, setMethods(http.MethodGet), setAuditBackend(prometheus)) diff --git a/server/apiv2/handlers/micro_service.go b/server/apiv2/handlers/micro_service.go new file mode 100644 index 000000000000..1bb4a95a47a2 --- /dev/null +++ b/server/apiv2/handlers/micro_service.go @@ -0,0 +1,106 @@ +// Copyright 2023 TiKV Project Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handlers + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/pingcap/log" + "github.com/tikv/pd/pkg/mcs/discovery" + "github.com/tikv/pd/server" + "github.com/tikv/pd/server/apiv2/middlewares" + "go.uber.org/zap" +) + +// RegisterMicroService registers microservice handler to the router. +func RegisterMicroService(r *gin.RouterGroup) { + router := r.Group("ms") + router.Use(middlewares.BootstrapChecker()) + router.GET("members/:service", GetMembers) + router.GET("primary/:service", GetPrimary) +} + +// @Tags members +// @Summary Get all members of the cluster for the specified service. +// @Produce json +// @Success 200 {object} []string +// @Router /ms/members/{service} [get] +func GetMembers(c *gin.Context) { + log.Info("Get members") + svr := c.MustGet(middlewares.ServerContextKey).(*server.Server) + if !svr.IsAPIServiceMode() { + c.AbortWithStatusJSON(http.StatusServiceUnavailable, "not support micro service") + return + } + + if service := c.Param("service"); len(service) > 0 { + resps, err := discovery.GetMembers(service, svr.GetClient()) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, err.Error()) + return + } + if resps == nil { + c.AbortWithStatusJSON(http.StatusNotFound, fmt.Sprintf("no members for %s", service)) + return + } + + var addrs []string + for _, resp := range resps.Responses { + for _, keyValue := range resp.GetResponseRange().GetKvs() { + var entry discovery.ServiceRegistryEntry + if err = entry.Deserialize(keyValue.Value); err != nil { + log.Info("deserialize failed", zap.String("key", string(keyValue.Key)), zap.Error(err)) + } + addrs = append(addrs, entry.ServiceAddr) + } + } + c.IndentedJSON(http.StatusOK, addrs) + return + } + + c.AbortWithStatusJSON(http.StatusInternalServerError, "please specify service") +} + +// @Tags Primary +// @Summary Get the primary of the cluster for the specified service. +// @Produce json +// @Success 200 {object} pdpb.Member +// @Router /ms/primary/{service} [get] +func GetPrimary(c *gin.Context) { + log.Info("GetPrimary") + svr := c.MustGet(middlewares.ServerContextKey).(*server.Server) + if !svr.IsAPIServiceMode() { + c.AbortWithStatusJSON(http.StatusServiceUnavailable, "not support micro service") + return + } + if service := c.Param("service"); len(service) > 0 { + keyspaceID, _ := c.GetQuery("keyspace_id") + primary, _, err := discovery.GetMCSPrimary(service, svr.GetClient(), keyspaceID) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, err.Error()) + return + } + if primary == nil { + c.AbortWithStatusJSON(http.StatusNotFound, fmt.Sprintf("no primary for %s", service)) + return + } + c.IndentedJSON(http.StatusOK, primary) + return + } + + c.AbortWithStatusJSON(http.StatusInternalServerError, "please specify service") +} diff --git a/server/apiv2/router.go b/server/apiv2/router.go index 383d336caaef..fd3ce38c0e4c 100644 --- a/server/apiv2/router.go +++ b/server/apiv2/router.go @@ -64,5 +64,6 @@ func NewV2Handler(_ context.Context, svr *server.Server) (http.Handler, apiutil. root := router.Group(apiV2Prefix) handlers.RegisterKeyspace(root) handlers.RegisterTSOKeyspaceGroup(root) + handlers.RegisterMicroService(root) return router, group, nil } diff --git a/tests/integrations/mcs/members/member_test.go b/tests/integrations/mcs/members/member_test.go index 1aa718b3e4dc..adb39b971eaa 100644 --- a/tests/integrations/mcs/members/member_test.go +++ b/tests/integrations/mcs/members/member_test.go @@ -93,6 +93,7 @@ func (suite *memberTestSuite) TestPrimary() { leader, err := suite.dialClient.GetMicroServicePrimary(suite.ctx, "tso") re.NotNil(leader) re.NoError(err) + leader, err = suite.dialClient.GetMicroServicePrimary(suite.ctx, "scheduling") re.NotNil(leader) re.NoError(err) @@ -100,7 +101,6 @@ func (suite *memberTestSuite) TestPrimary() { func (suite *memberTestSuite) TestMembers() { re := suite.Require() - members, err := suite.dialClient.GetMicroServiceMembers(suite.ctx, "tso") re.NoError(err) re.Len(members, utils.DefaultKeyspaceGroupReplicaCount)