github.com/polarismesh/polaris@v1.17.8/apiserver/eurekaserver/access.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package eurekaserver
    19  
    20  import (
    21  	"context"
    22  	"encoding/xml"
    23  	"fmt"
    24  	"net/http"
    25  	"strings"
    26  
    27  	"github.com/emicklei/go-restful/v3"
    28  
    29  	api "github.com/polarismesh/polaris/common/api/v1"
    30  	"github.com/polarismesh/polaris/common/utils"
    31  )
    32  
    33  const (
    34  	ParamAppId      string = "appId"
    35  	ParamInstId     string = "instId"
    36  	ParamValue      string = "value"
    37  	ParamVip        string = "vipAddress"
    38  	ParamSVip       string = "svipAddress"
    39  	HeaderNamespace string = "x-namespace"
    40  )
    41  
    42  // GetEurekaServer eureka web server
    43  func (h *EurekaServer) GetEurekaServer() *restful.WebService {
    44  	ws := new(restful.WebService)
    45  
    46  	ws.Path("/eureka").Consumes(restful.MIME_JSON, restful.MIME_OCTET, restful.MIME_XML).Produces(restful.MIME_JSON,
    47  		restful.MIME_XML)
    48  	h.addDiscoverAccess(ws)
    49  	return ws
    50  }
    51  
    52  // GetEurekaV1Server eureka v1 web server
    53  func (h *EurekaServer) GetEurekaV1Server() *restful.WebService {
    54  	ws := new(restful.WebService)
    55  
    56  	ws.Path("/eureka/v1").Consumes(restful.MIME_JSON, restful.MIME_OCTET, restful.MIME_XML).Produces(restful.MIME_JSON,
    57  		restful.MIME_XML)
    58  	h.addDiscoverAccess(ws)
    59  	return ws
    60  }
    61  
    62  // GetEurekaV2Server eureka v2 web server
    63  func (h *EurekaServer) GetEurekaV2Server() *restful.WebService {
    64  	ws := new(restful.WebService)
    65  
    66  	ws.Path("/eureka/v2").Consumes(restful.MIME_JSON, restful.MIME_OCTET, restful.MIME_XML).Produces(restful.MIME_JSON,
    67  		restful.MIME_XML)
    68  	h.addDiscoverAccess(ws)
    69  	return ws
    70  }
    71  
    72  // addDiscoverAccess 增加服务发现接口
    73  func (h *EurekaServer) addDiscoverAccess(ws *restful.WebService) {
    74  	// Register new application instance
    75  	ws.Route(ws.POST(fmt.Sprintf("/apps/{%s}", ParamAppId)).To(h.RegisterApplication)).
    76  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string"))
    77  	// De-register application instance
    78  	ws.Route(ws.DELETE(fmt.Sprintf("/apps/{%s}/{%s}", ParamAppId, ParamInstId)).To(h.CancelInstance)).
    79  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string")).
    80  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
    81  	// Send application instance heartbeat
    82  	ws.Route(ws.PUT(fmt.Sprintf("/apps/{%s}/{%s}", ParamAppId, ParamInstId)).To(h.RenewInstance)).
    83  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string")).
    84  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
    85  	// Query for all instances
    86  	ws.Route(ws.GET("/apps").To(h.GetAllApplications))
    87  	// Query for all instances(delta)
    88  	ws.Route(ws.GET("/apps/delta").To(h.GetDeltaApplications))
    89  	// Query for all appID instances
    90  	ws.Route(ws.GET(fmt.Sprintf("/apps/{%s}", ParamAppId)).To(h.GetApplication)).
    91  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string"))
    92  	// Query for a specific appID/instanceID
    93  	ws.Route(ws.GET(fmt.Sprintf("/apps/{%s}/{%s}", ParamAppId, ParamInstId)).To(h.GetAppInstance)).
    94  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string")).
    95  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
    96  	// Take instance out of service
    97  	ws.Route(ws.PUT(fmt.Sprintf("/apps/{%s}/{%s}/status", ParamAppId, ParamInstId)).To(h.UpdateStatus)).
    98  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string")).
    99  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
   100  	// Move instance back into service (remove override)
   101  	ws.Route(ws.DELETE(fmt.Sprintf("/apps/{%s}/{%s}/status", ParamAppId, ParamInstId)).To(h.DeleteStatus)).
   102  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string")).
   103  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
   104  	// Query for a specific instanceID
   105  	ws.Route(ws.GET(fmt.Sprintf("/instances/{%s}", ParamInstId)).To(h.GetInstance)).
   106  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
   107  	// Update metadata
   108  	ws.Route(ws.PUT(fmt.Sprintf("/apps/{%s}/{%s}/metadata", ParamAppId, ParamInstId)).To(h.UpdateMetadata)).
   109  		Param(ws.PathParameter(ParamAppId, "applicationId").DataType("string")).
   110  		Param(ws.PathParameter(ParamInstId, "instanceId").DataType("string"))
   111  	// Query for all instances under a particular vip address
   112  	ws.Route(ws.GET(fmt.Sprintf("/vips/{%s}", ParamVip)).To(h.QueryByVipAddress)).
   113  		Param(ws.PathParameter(ParamVip, "vipAddress").DataType("string"))
   114  	// Query for all instances under a particular secure vip address
   115  	ws.Route(ws.GET(fmt.Sprintf("/svips/{%s}", ParamSVip)).To(h.QueryBySVipAddress)).
   116  		Param(ws.PathParameter(ParamSVip, "svipAddress").DataType("string"))
   117  	// Query for handling batch replication request
   118  	ws.Route(ws.POST("/peerreplication/batch").To(h.BatchReplication))
   119  }
   120  
   121  func parseAcceptValue(acceptValue string) map[string]bool {
   122  	var values map[string]bool
   123  	blankValues := strings.Split(acceptValue, ",")
   124  	if len(blankValues) > 0 {
   125  		values = make(map[string]bool, len(blankValues))
   126  		for _, blankValue := range blankValues {
   127  			values[strings.TrimSpace(blankValue)] = true
   128  		}
   129  	}
   130  	return values
   131  }
   132  
   133  // GetAllApplications 全量拉取服务实例信息
   134  func (h *EurekaServer) GetAllApplications(req *restful.Request, rsp *restful.Response) {
   135  	namespace := readNamespaceFromRequest(req, h.namespace)
   136  	appsRespCache := h.workers.Get(namespace).GetCachedAppsWithLoad()
   137  	remoteAddr := req.Request.RemoteAddr
   138  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   139  	if err := writeResponse(parseAcceptValue(acceptValue), appsRespCache, req, rsp); nil != err {
   140  		eurekalog.Errorf("[EurekaServer]fail to write applications, client: %s, err: %v", remoteAddr, err)
   141  	}
   142  }
   143  
   144  func writePolarisStatusCode(req *restful.Request, statusCode uint32) {
   145  	req.SetAttribute(statusCodeHeader, statusCode)
   146  }
   147  
   148  // GetApplication 拉取单个服务实例信息
   149  func (h *EurekaServer) GetApplication(req *restful.Request, rsp *restful.Response) {
   150  	appId := readAppIdFromRequest(req)
   151  
   152  	remoteAddr := req.Request.RemoteAddr
   153  	namespace := readNamespaceFromRequest(req, h.namespace)
   154  	appsRespCache := h.workers.Get(namespace).GetCachedAppsWithLoad()
   155  	apps := appsRespCache.AppsResp.Applications
   156  	app := apps.GetApplication(appId)
   157  	if app == nil {
   158  		eurekalog.Errorf("[EurekaServer]service %s not found, client: %s", appId, remoteAddr)
   159  		writePolarisStatusCode(req, api.NotFoundService)
   160  		writeHeader(http.StatusNotFound, rsp)
   161  		return
   162  	}
   163  
   164  	appResp := ApplicationResponse{Application: app}
   165  	var output interface{}
   166  	output = appResp.Application
   167  
   168  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   169  	if len(acceptValue) > 0 && acceptValue == restful.MIME_JSON {
   170  		output = appResp
   171  	}
   172  	if err := writeEurekaResponse(acceptValue, output, req, rsp); nil != err {
   173  		eurekalog.Errorf("[EurekaServer]fail to write application, client: %s, err: %v", remoteAddr, err)
   174  	}
   175  }
   176  
   177  // GetAppInstance 拉取应用下某个实例的信息
   178  func (h *EurekaServer) GetAppInstance(req *restful.Request, rsp *restful.Response) {
   179  	remoteAddr := req.Request.RemoteAddr
   180  	appId := readAppIdFromRequest(req)
   181  	if len(appId) == 0 {
   182  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   183  			req.Request.RequestURI, remoteAddr, "service name is empty")
   184  		writePolarisStatusCode(req, api.InvalidServiceName)
   185  		writeHeader(http.StatusBadRequest, rsp)
   186  		return
   187  	}
   188  	instId := req.PathParameter(ParamInstId)
   189  	if len(instId) == 0 {
   190  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   191  			req.Request.RequestURI, remoteAddr, "instance id is required")
   192  		writePolarisStatusCode(req, api.InvalidInstanceID)
   193  		writeHeader(http.StatusBadRequest, rsp)
   194  		return
   195  	}
   196  	namespace := readNamespaceFromRequest(req, h.namespace)
   197  	appsRespCache := h.workers.Get(namespace).GetCachedAppsWithLoad()
   198  	apps := appsRespCache.AppsResp.Applications
   199  	app := apps.GetApplication(appId)
   200  	if app == nil {
   201  		eurekalog.Errorf("[EurekaServer]service %s not found, client: %s", appId, remoteAddr)
   202  		writePolarisStatusCode(req, api.NotFoundService)
   203  		writeHeader(http.StatusNotFound, rsp)
   204  		return
   205  	}
   206  	ins := app.GetInstance(instId)
   207  	if ins == nil {
   208  		eurekalog.Errorf("[EurekaServer]instance %s not found, service: %s, client: %s", instId, appId, remoteAddr)
   209  		writePolarisStatusCode(req, api.NotFoundInstance)
   210  		writeHeader(http.StatusNotFound, rsp)
   211  		return
   212  	}
   213  
   214  	insResp := InstanceResponse{InstanceInfo: ins}
   215  	var output interface{}
   216  	output = insResp.InstanceInfo
   217  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   218  	if len(acceptValue) > 0 && acceptValue == restful.MIME_JSON {
   219  		output = insResp
   220  	}
   221  	if err := writeEurekaResponse(acceptValue, output, req, rsp); nil != err {
   222  		eurekalog.Errorf("[EurekaServer]fail to write instance, client: %s, err: %v", remoteAddr, err)
   223  	}
   224  }
   225  
   226  func writeEurekaResponse(acceptValue string, output interface{}, req *restful.Request, rsp *restful.Response) error {
   227  	return writeEurekaResponseWithCode(acceptValue, output, req, rsp, api.ExecuteSuccess)
   228  }
   229  
   230  func writeEurekaResponseWithCode(
   231  	acceptValue string, output interface{}, req *restful.Request, rsp *restful.Response, statusCode uint32) error {
   232  	writePolarisStatusCode(req, statusCode)
   233  	var err error
   234  	if len(acceptValue) > 0 && acceptValue == restful.MIME_JSON {
   235  		err = rsp.WriteAsJson(output)
   236  	} else {
   237  		err = rsp.WriteAsXml(output)
   238  	}
   239  
   240  	return err
   241  }
   242  
   243  const (
   244  	MimeJsonWild = "application/*+json"
   245  )
   246  
   247  func writeResponse(acceptValues map[string]bool, appsRespCache *ApplicationsRespCache,
   248  	req *restful.Request, rsp *restful.Response) error {
   249  	writePolarisStatusCode(req, api.ExecuteSuccess)
   250  	var err error
   251  	if len(acceptValues) > 0 && (hasKey(acceptValues, restful.MIME_JSON) || hasKey(acceptValues, MimeJsonWild)) {
   252  		if len(appsRespCache.JsonBytes) > 0 {
   253  			// 直接使用只读缓存返回
   254  			rsp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
   255  			rsp.WriteHeader(http.StatusOK)
   256  			_, err = rsp.Write(appsRespCache.JsonBytes)
   257  		} else {
   258  			err = rsp.WriteAsJson(appsRespCache.AppsResp)
   259  		}
   260  	} else {
   261  		if len(appsRespCache.XmlBytes) > 0 {
   262  			rsp.Header().Set(restful.HEADER_ContentType, restful.MIME_XML)
   263  			rsp.WriteHeader(http.StatusOK)
   264  			_, err = rsp.Write([]byte(xml.Header))
   265  			if err != nil {
   266  				return err
   267  			}
   268  			_, err = rsp.Write(appsRespCache.XmlBytes)
   269  			return err
   270  		}
   271  		err = rsp.WriteAsXml(appsRespCache.AppsResp.Applications)
   272  	}
   273  	return err
   274  }
   275  
   276  // GetDeltaApplications 增量拉取服务实例信息
   277  func (h *EurekaServer) GetDeltaApplications(req *restful.Request, rsp *restful.Response) {
   278  	namespace := readNamespaceFromRequest(req, h.namespace)
   279  	work := h.workers.Get(namespace)
   280  	appsRespCache := work.GetDeltaApps()
   281  	if nil == appsRespCache {
   282  		ctx := work.StartWorker()
   283  		if nil != ctx {
   284  			<-ctx.Done()
   285  		}
   286  		appsRespCache = work.GetDeltaApps()
   287  	}
   288  	remoteAddr := req.Request.RemoteAddr
   289  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   290  	if err := writeResponse(parseAcceptValue(acceptValue), appsRespCache, req, rsp); nil != err {
   291  		eurekalog.Errorf("[EurekaServer]fail to write delta applications, client: %s, err: %v", remoteAddr, err)
   292  	}
   293  }
   294  
   295  func convertInstancePorts(instance *InstanceInfo) error {
   296  	var err error
   297  	if nil != instance.Port {
   298  		if err = instance.Port.convertPortValue(); nil != err {
   299  			return err
   300  		}
   301  		if err = instance.Port.convertEnableValue(); nil != err {
   302  			return err
   303  		}
   304  	}
   305  	if nil != instance.SecurePort {
   306  		if err = instance.SecurePort.convertPortValue(); nil != err {
   307  			return err
   308  		}
   309  		if err = instance.SecurePort.convertEnableValue(); nil != err {
   310  			return err
   311  		}
   312  	}
   313  	return nil
   314  }
   315  
   316  func checkRegisterRequest(registrationRequest *RegistrationRequest, req *restful.Request, rsp *restful.Response) bool {
   317  	var err error
   318  	remoteAddr := req.Request.RemoteAddr
   319  	if nil == registrationRequest.Instance {
   320  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse register request, uri: %s, client: %s, err: %s",
   321  			req.Request.RequestURI, remoteAddr, "instance content required")
   322  		writePolarisStatusCode(req, api.EmptyRequest)
   323  		writeHeader(http.StatusBadRequest, rsp)
   324  		return false
   325  	}
   326  	if len(registrationRequest.Instance.InstanceId) == 0 && len(registrationRequest.Instance.HostName) == 0 {
   327  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse register request, uri: %s, client: %s, err: %s",
   328  			req.Request.RequestURI, remoteAddr, "instance id required")
   329  		writePolarisStatusCode(req, api.InvalidInstanceID)
   330  		writeHeader(http.StatusBadRequest, rsp)
   331  	}
   332  	err = convertInstancePorts(registrationRequest.Instance)
   333  	if nil != err {
   334  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse instance register request, "+
   335  			"invalid port value, client: %s, err: %v", remoteAddr, err)
   336  		writePolarisStatusCode(req, api.InvalidInstancePort)
   337  		writeHeader(http.StatusBadRequest, rsp)
   338  	}
   339  	return true
   340  }
   341  
   342  // RegisterApplication 服务注册
   343  func (h *EurekaServer) RegisterApplication(req *restful.Request, rsp *restful.Response) {
   344  	remoteAddr := req.Request.RemoteAddr
   345  	appId := readAppIdFromRequest(req)
   346  
   347  	if len(appId) == 0 {
   348  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   349  			req.Request.RequestURI, remoteAddr, "service name is empty")
   350  		writePolarisStatusCode(req, api.InvalidServiceName)
   351  		writeHeader(http.StatusBadRequest, rsp)
   352  		return
   353  	}
   354  	registrationRequest := &RegistrationRequest{}
   355  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_ContentType)
   356  	var err error
   357  	if acceptValue == restful.MIME_XML {
   358  		instance := &InstanceInfo{}
   359  		registrationRequest.Instance = instance
   360  		err = req.ReadEntity(&instance)
   361  	} else {
   362  		err = req.ReadEntity(registrationRequest)
   363  	}
   364  	if nil != err {
   365  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse instance register request, uri: %s, client: %s, err: %v",
   366  			req.Request.RequestURI, remoteAddr, err)
   367  		writePolarisStatusCode(req, api.ParseException)
   368  		writeHeader(http.StatusBadRequest, rsp)
   369  		return
   370  	}
   371  
   372  	if !checkRegisterRequest(registrationRequest, req, rsp) {
   373  		return
   374  	}
   375  
   376  	token, err := getAuthFromEurekaRequestHeader(req)
   377  	if err != nil {
   378  		eurekalog.Infof("[EUREKA-SERVER]instance (instId=%s, appId=%s) get basic auth info fail, code is %d",
   379  			registrationRequest.Instance.InstanceId, appId, api.ExecuteException)
   380  		writePolarisStatusCode(req, api.ExecuteException)
   381  		writeHeader(http.StatusUnauthorized, rsp)
   382  		return
   383  	}
   384  
   385  	ctx := context.WithValue(context.Background(), utils.ContextAuthTokenKey, token)
   386  
   387  	namespace := readNamespaceFromRequest(req, h.namespace)
   388  	eurekalog.Infof(
   389  		"[EUREKA-SERVER]received instance register request, "+
   390  			"client: %s, namespace: %s, instId: %s, appId: %s, ipAddr: %s",
   391  		remoteAddr, namespace, registrationRequest.Instance.InstanceId, appId, registrationRequest.Instance.IpAddr)
   392  	code := h.registerInstances(ctx, namespace, appId, registrationRequest.Instance, false)
   393  	if code == api.ExecuteSuccess || code == api.ExistedResource || code == api.SameInstanceRequest {
   394  		eurekalog.Infof(
   395  			"[EUREKA-SERVER]instance (namespace=%s, instId=%s, appId=%s) has been registered successfully,"+
   396  				" code is %d",
   397  			namespace, registrationRequest.Instance.InstanceId, appId, code)
   398  		writePolarisStatusCode(req, code)
   399  		writeHeader(http.StatusNoContent, rsp)
   400  		return
   401  	}
   402  	eurekalog.Errorf("[EUREKA-SERVER]instance (namespace=%s, instId=%s, appId=%s) has been registered failed, "+
   403  		"code is %d",
   404  		namespace, registrationRequest.Instance.InstanceId, appId, code)
   405  	writePolarisStatusCode(req, code)
   406  	writeHeader(int(code/1000), rsp)
   407  }
   408  
   409  // UpdateStatus 更新服务状态
   410  func (h *EurekaServer) UpdateStatus(req *restful.Request, rsp *restful.Response) {
   411  	remoteAddr := req.Request.RemoteAddr
   412  	appId := readAppIdFromRequest(req)
   413  	if len(appId) == 0 {
   414  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   415  			req.Request.RequestURI, remoteAddr, "service name is empty")
   416  		writePolarisStatusCode(req, api.InvalidServiceName)
   417  		writeHeader(http.StatusBadRequest, rsp)
   418  		return
   419  	}
   420  	instId := req.PathParameter(ParamInstId)
   421  	if len(instId) == 0 {
   422  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   423  			req.Request.RequestURI, remoteAddr, "instance id is required")
   424  		writePolarisStatusCode(req, api.InvalidInstanceID)
   425  		writeHeader(http.StatusBadRequest, rsp)
   426  		return
   427  	}
   428  	status := req.QueryParameter(ParamValue)
   429  	namespace := readNamespaceFromRequest(req, h.namespace)
   430  	eurekalog.Infof("[EUREKA-SERVER]received instance updateStatus request, "+
   431  		"client: %s, namespace: %s, instId: %s, appId: %s, status: %s",
   432  		remoteAddr, namespace, instId, appId, status)
   433  	// check status
   434  	if status == StatusUnknown {
   435  		writePolarisStatusCode(req, api.ExecuteSuccess)
   436  		writeHeader(http.StatusOK, rsp)
   437  		return
   438  	}
   439  	ctx := context.WithValue(context.Background(), sourceFromEureka{}, true)
   440  	code := h.updateStatus(ctx, namespace, appId, instId, status, false)
   441  	writePolarisStatusCode(req, code)
   442  	if code == api.ExecuteSuccess || code == api.NoNeedUpdate {
   443  		eurekalog.Infof("[EUREKA-SERVER] instance (namespace=%s, instId=%s, appId=%s) has been updated successfully",
   444  			namespace, instId, appId)
   445  		writeHeader(http.StatusOK, rsp)
   446  		return
   447  	}
   448  	eurekalog.Errorf("[EUREKA-SERVER] instance (namespace=%s, instId=%s, appId=%s) has been updated failed, "+
   449  		"code is %d",
   450  		namespace, instId, appId, code)
   451  	if code == api.NotFoundResource {
   452  		writeHeader(http.StatusNotFound, rsp)
   453  		return
   454  	}
   455  	writeHeader(int(code/1000), rsp)
   456  }
   457  
   458  // DeleteStatus 关闭强制隔离
   459  func (h *EurekaServer) DeleteStatus(req *restful.Request, rsp *restful.Response) {
   460  	remoteAddr := req.Request.RemoteAddr
   461  	appId := readAppIdFromRequest(req)
   462  	if len(appId) == 0 {
   463  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   464  			req.Request.RequestURI, remoteAddr, "service name is empty")
   465  		writePolarisStatusCode(req, api.InvalidServiceName)
   466  		writeHeader(http.StatusBadRequest, rsp)
   467  		return
   468  	}
   469  	instId := req.PathParameter(ParamInstId)
   470  	if len(instId) == 0 {
   471  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   472  			req.Request.RequestURI, remoteAddr, "instance id is required")
   473  		writePolarisStatusCode(req, api.InvalidInstanceID)
   474  		writeHeader(http.StatusBadRequest, rsp)
   475  		return
   476  	}
   477  
   478  	namespace := readNamespaceFromRequest(req, h.namespace)
   479  
   480  	eurekalog.Infof("[EUREKA-SERVER]received instance status delete request, "+
   481  		"client: %s,namespace=%s, instId=%s, appId=%s",
   482  		remoteAddr, namespace, instId, appId)
   483  
   484  	ctx := context.WithValue(context.Background(), sourceFromEureka{}, true)
   485  	code := h.updateStatus(ctx, namespace, appId, instId, StatusUp, false)
   486  	writePolarisStatusCode(req, code)
   487  	if code == api.ExecuteSuccess {
   488  		eurekalog.Infof("[EUREKA-SERVER]instance status (namespace=%s, instId=%s, appId=%s) "+
   489  			"has been deleted successfully",
   490  			namespace, instId, appId)
   491  		writeHeader(http.StatusOK, rsp)
   492  		return
   493  	}
   494  	eurekalog.Errorf("[EUREKA-SERVER]instance status (namespace=%s, instId=%s, appId=%s) "+
   495  		"has been deleted failed, code is %d",
   496  		namespace, instId, appId, code)
   497  	if code == api.NotFoundResource {
   498  		writeHeader(http.StatusNotFound, rsp)
   499  		return
   500  	}
   501  	writeHeader(int(code/1000), rsp)
   502  }
   503  
   504  // RenewInstance 更新实例状态
   505  func (h *EurekaServer) RenewInstance(req *restful.Request, rsp *restful.Response) {
   506  	remoteAddr := req.Request.RemoteAddr
   507  	appId := readAppIdFromRequest(req)
   508  	if len(appId) == 0 {
   509  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   510  			req.Request.RequestURI, remoteAddr, "service name is empty")
   511  		writePolarisStatusCode(req, api.InvalidServiceName)
   512  		writeHeader(http.StatusBadRequest, rsp)
   513  		return
   514  	}
   515  	instId := req.PathParameter(ParamInstId)
   516  	if len(instId) == 0 {
   517  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   518  			req.Request.RequestURI, remoteAddr, "instance id is required")
   519  		writePolarisStatusCode(req, api.InvalidInstanceID)
   520  		writeHeader(http.StatusBadRequest, rsp)
   521  		return
   522  	}
   523  	namespace := readNamespaceFromRequest(req, h.namespace)
   524  	code := h.renew(context.Background(), namespace, appId, instId, false)
   525  	writePolarisStatusCode(req, code)
   526  	if code == api.ExecuteSuccess || code == api.HeartbeatExceedLimit {
   527  		writeHeader(http.StatusOK, rsp)
   528  		return
   529  	}
   530  	eurekalog.Errorf("[EUREKA-SERVER]instance (namespace=%s, instId=%s, appId=%s) heartbeat failed, code is %d",
   531  		namespace, instId, appId, code)
   532  	if code == api.NotFoundResource {
   533  		writeHeader(http.StatusNotFound, rsp)
   534  		return
   535  	}
   536  	writeHeader(int(code/1000), rsp)
   537  }
   538  
   539  // CancelInstance 实例反注册
   540  func (h *EurekaServer) CancelInstance(req *restful.Request, rsp *restful.Response) {
   541  	appId := readAppIdFromRequest(req)
   542  	remoteAddr := req.Request.RemoteAddr
   543  	if len(appId) == 0 {
   544  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   545  			req.Request.RequestURI, remoteAddr, "service name is empty")
   546  		writePolarisStatusCode(req, api.InvalidServiceName)
   547  		writeHeader(http.StatusBadRequest, rsp)
   548  		return
   549  	}
   550  	instId := req.PathParameter(ParamInstId)
   551  	if len(instId) == 0 {
   552  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   553  			req.Request.RequestURI, remoteAddr, "instance id is required")
   554  		writePolarisStatusCode(req, api.InvalidInstanceID)
   555  		writeHeader(http.StatusBadRequest, rsp)
   556  		return
   557  	}
   558  	namespace := readNamespaceFromRequest(req, h.namespace)
   559  	eurekalog.Infof("[EUREKA-SERVER]received instance deregistered request, "+
   560  		"client: %s, namespace: %s, instId: %s, appId: %s",
   561  		remoteAddr, namespace, instId, appId)
   562  	code := h.deregisterInstance(context.Background(), namespace, appId, instId, false)
   563  	writePolarisStatusCode(req, code)
   564  	if code == api.ExecuteSuccess || code == api.NotFoundResource || code == api.SameInstanceRequest {
   565  		writeHeader(http.StatusOK, rsp)
   566  		eurekalog.Infof("[EUREKA-SERVER]instance (namespace=%s, instId=%s, appId=%s) "+
   567  			"has been deregistered successfully, code is %d",
   568  			namespace, instId, appId, code)
   569  		return
   570  	}
   571  	eurekalog.Errorf("[EUREKA-SERVER]instance (namespace=%s, instId=%s, appId=%s) has been deregistered failed,"+
   572  		" code is %d",
   573  		namespace, instId, appId, code)
   574  	writeHeader(int(code/1000), rsp)
   575  }
   576  
   577  // GetInstance query instance by id
   578  func (h *EurekaServer) GetInstance(req *restful.Request, rsp *restful.Response) {
   579  	remoteAddr := req.Request.RemoteAddr
   580  	instId := req.PathParameter(ParamInstId)
   581  	if len(instId) == 0 {
   582  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   583  			req.Request.RequestURI, remoteAddr, "instance id is required")
   584  		writePolarisStatusCode(req, api.InvalidInstanceID)
   585  		writeHeader(http.StatusBadRequest, rsp)
   586  		return
   587  	}
   588  	namespace := readNamespaceFromRequest(req, h.namespace)
   589  	appsRespCache := h.workers.Get(namespace).GetCachedAppsWithLoad()
   590  	apps := appsRespCache.AppsResp.Applications
   591  	instance := apps.GetInstance(instId)
   592  	if nil == instance {
   593  		writePolarisStatusCode(req, api.NotFoundInstance)
   594  		writeHeader(http.StatusNotFound, rsp)
   595  		return
   596  	}
   597  	insResp := InstanceResponse{InstanceInfo: instance}
   598  	var output interface{}
   599  	output = insResp.InstanceInfo
   600  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   601  	if len(acceptValue) > 0 && acceptValue == restful.MIME_JSON {
   602  		output = insResp
   603  	}
   604  	if err := writeEurekaResponse(acceptValue, output, req, rsp); nil != err {
   605  		eurekalog.Errorf("[EurekaServer]fail to write instance, client: %s, err: %v", remoteAddr, err)
   606  	}
   607  }
   608  
   609  // UpdateMetadata updateStatus instance metadata
   610  func (h *EurekaServer) UpdateMetadata(req *restful.Request, rsp *restful.Response) {
   611  	remoteAddr := req.Request.RemoteAddr
   612  	appId := readAppIdFromRequest(req)
   613  	if len(appId) == 0 {
   614  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   615  			req.Request.RequestURI, remoteAddr, "service name is empty")
   616  		writePolarisStatusCode(req, api.InvalidServiceName)
   617  		writeHeader(http.StatusBadRequest, rsp)
   618  		return
   619  	}
   620  	instId := req.PathParameter(ParamInstId)
   621  	if len(instId) == 0 {
   622  		eurekalog.Errorf("[EUREKA-SERVER] fail to parse request uri, uri: %s, client: %s, err: %s",
   623  			req.Request.RequestURI, remoteAddr, "instance id is required")
   624  		writePolarisStatusCode(req, api.InvalidInstanceID)
   625  		writeHeader(http.StatusBadRequest, rsp)
   626  		return
   627  	}
   628  	namespace := readNamespaceFromRequest(req, h.namespace)
   629  	queryValues := req.Request.URL.Query()
   630  	metadataMap := make(map[string]string, len(queryValues))
   631  	for key, values := range queryValues {
   632  		if len(values) == 0 {
   633  			metadataMap[key] = ""
   634  			continue
   635  		}
   636  		metadataMap[key] = values[0]
   637  	}
   638  	code := h.updateMetadata(context.Background(), namespace, appId, instId, metadataMap)
   639  	writePolarisStatusCode(req, code)
   640  	if code == api.ExecuteSuccess {
   641  		eurekalog.Infof("[EUREKA-SERVER]instance metadata (namespace=%s, instId=%s, appId=%s) has been updated successfully",
   642  			namespace, instId, appId)
   643  		writeHeader(http.StatusOK, rsp)
   644  		return
   645  	}
   646  	eurekalog.Errorf("[EUREKA-SERVER]instance metadata (namespace=%s, instId=%s, appId=%s) has been updated failed, "+
   647  		"code is %d",
   648  		namespace, instId, appId, code)
   649  	if code == api.NotFoundResource {
   650  		writeHeader(http.StatusNotFound, rsp)
   651  		return
   652  	}
   653  	writeHeader(int(code/1000), rsp)
   654  }
   655  
   656  // QueryByVipAddress query for all instances under a particular vip address
   657  func (h *EurekaServer) QueryByVipAddress(req *restful.Request, rsp *restful.Response) {
   658  	remoteAddr := req.Request.RemoteAddr
   659  	vipAddress := req.PathParameter(ParamVip)
   660  	if len(vipAddress) == 0 {
   661  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   662  			req.Request.RequestURI, remoteAddr, "vip address is empty")
   663  		writePolarisStatusCode(req, api.InvalidParameter)
   664  		writeHeader(http.StatusBadRequest, rsp)
   665  		return
   666  	}
   667  
   668  	namespace := readNamespaceFromRequest(req, h.namespace)
   669  	appsRespCache := h.workers.Get(namespace).GetVipApps(VipCacheKey{
   670  		entityType:       entityTypeVip,
   671  		targetVipAddress: formatReadName(vipAddress),
   672  	})
   673  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   674  	if err := writeResponse(parseAcceptValue(acceptValue), appsRespCache, req, rsp); nil != err {
   675  		eurekalog.Errorf("[EurekaServer]fail to write vip applications, client: %s, err: %v", remoteAddr, err)
   676  	}
   677  }
   678  
   679  // QueryBySVipAddress query for all instances under a particular secure vip address
   680  func (h *EurekaServer) QueryBySVipAddress(req *restful.Request, rsp *restful.Response) {
   681  	remoteAddr := req.Request.RemoteAddr
   682  	vipAddress := req.PathParameter(ParamSVip)
   683  	if len(vipAddress) == 0 {
   684  		eurekalog.Errorf("[EurekaServer] fail to parse request uri, uri: %s, client: %s, err: %s",
   685  			req.Request.RequestURI, remoteAddr, "svip address is empty")
   686  		writePolarisStatusCode(req, api.InvalidParameter)
   687  		writeHeader(http.StatusBadRequest, rsp)
   688  		return
   689  	}
   690  	namespace := readNamespaceFromRequest(req, h.namespace)
   691  	appsRespCache := h.workers.Get(namespace).GetVipApps(VipCacheKey{
   692  		entityType:       entityTypeSVip,
   693  		targetVipAddress: formatReadName(vipAddress),
   694  	})
   695  	acceptValue := getParamFromEurekaRequestHeader(req, restful.HEADER_Accept)
   696  	if err := writeResponse(parseAcceptValue(acceptValue), appsRespCache, req, rsp); nil != err {
   697  		eurekalog.Errorf("[EurekaServer]fail to write svip applications, client: %s, err: %v", remoteAddr, err)
   698  	}
   699  }