diff --git a/apiserver/grpcserver/config/client_access.go b/apiserver/grpcserver/config/client_access.go index f538b496c..86922c882 100644 --- a/apiserver/grpcserver/config/client_access.go +++ b/apiserver/grpcserver/config/client_access.go @@ -209,6 +209,7 @@ func (g *ConfigGRPCServer) Discover(svr apiconfig.PolarisConfigGRPC_DiscoverServ req := in.GetConfigFile() req.Md5 = wrapperspb.String(in.GetRevision()) out = g.configServer.GetConfigGroupsWithCache(ctx, req) + out.Type = apiconfig.ConfigDiscoverResponse_CONFIG_FILE_GROUPS default: out = api.NewConfigDiscoverResponse(apimodel.Code_InvalidDiscoverResource) } diff --git a/apiserver/grpcserver/config/server.go b/apiserver/grpcserver/config/server.go index eaef332ee..b64266618 100644 --- a/apiserver/grpcserver/config/server.go +++ b/apiserver/grpcserver/config/server.go @@ -129,7 +129,7 @@ func (g *ConfigGRPCServer) allowAccess(method string) bool { // GetClientOpenMethod . func GetClientOpenMethod(protocol string) (map[string]bool, error) { openMethods := []string{"GetConfigFile", "CreateConfigFile", - "UpdateConfigFile", "PublishConfigFile", "WatchConfigFiles", "GetConfigFileMetadataList"} + "UpdateConfigFile", "PublishConfigFile", "WatchConfigFiles", "GetConfigFileMetadataList", "Discover"} openMethod := make(map[string]bool) diff --git a/apiserver/grpcserver/discover/server.go b/apiserver/grpcserver/discover/server.go index f45c94c67..e5fab7ee1 100644 --- a/apiserver/grpcserver/discover/server.go +++ b/apiserver/grpcserver/discover/server.go @@ -108,6 +108,7 @@ func (g *GRPCServer) Run(errCh chan error) { // 注册 v1 版本的 spec discover server apiservice.RegisterPolarisGRPCServer(server, g.v1server) apiservice.RegisterPolarisHeartbeatGRPCServer(server, g.v1server) + apiservice.RegisterPolarisServiceContractGRPCServer(server, g.v1server) openMethod, getErr := utils.GetClientOpenMethod(config.Include, g.GetProtocol()) if getErr != nil { return getErr diff --git a/apiserver/grpcserver/discover/v1/client_access.go b/apiserver/grpcserver/discover/v1/client_access.go index fb4cf3979..14ee828a1 100644 --- a/apiserver/grpcserver/discover/v1/client_access.go +++ b/apiserver/grpcserver/discover/v1/client_access.go @@ -174,6 +174,15 @@ func (g *DiscoverServer) Discover(server apiservice.PolarisGRPC_DiscoverServer) } } +func (g *DiscoverServer) ReportServiceContract(ctx context.Context, in *apiservice.ServiceContract) (*apiservice.Response, error) { + // 需要记录操作来源,提高效率,只针对特殊接口添加operator + rCtx := utils.ConvertGRPCContext(ctx) + rCtx = context.WithValue(rCtx, utils.StringContext("operator"), ParseGrpcOperator(ctx)) + + out := g.namingServer.ReportServiceContract(rCtx, in) + return out, nil +} + // ParseGrpcOperator 构造请求源 func ParseGrpcOperator(ctx context.Context) string { // 获取请求源 diff --git a/apiserver/xdsserverv3/resource/node.go b/apiserver/xdsserverv3/resource/node.go index b4c1c1985..440f155b7 100644 --- a/apiserver/xdsserverv3/resource/node.go +++ b/apiserver/xdsserverv3/resource/node.go @@ -62,10 +62,10 @@ const ( // SidecarRegisterService xds metadata key when node what register service from envoy healthcheck // value example: [{"name":"","ports":{"TCP":[8080],"DUBBO":[28080]},"health_check_path":"","health_check_port":8080,"health_check_ttl":5}] SidecarRegisterService = "sidecar.polarismesh.cn/registerServices" - // SidecarOpenOnDemandFeature . - SidecarOpenOnDemandFeature = "sidecar.polarismesh.cn/openOnDemand" // SidecarTLSModeTag . SidecarTLSModeTag = "sidecar.polarismesh.cn/tlsMode" + // SidecarOpenOnDemandFeature . + SidecarOpenOnDemandFeature = "sidecar.polarismesh.cn/openOnDemand" // SidecarConnectServerEndpoint report xds server the envoy xds on-demand cds server endpoint info SidecarODCDSServerEndpoint = "sidecar.polarismesh.cn/odcdsServerEndpoint" ) diff --git a/cache/api/types.go b/cache/api/types.go index f96cfc50c..99cdbe0a6 100644 --- a/cache/api/types.go +++ b/cache/api/types.go @@ -248,6 +248,8 @@ type ( Query(filter map[string]string, offset, limit uint32) ([]*model.EnrichServiceContract, uint32, error) // ListVersions . ListVersions(service, namespace string) []*model.EnrichServiceContract + // Get . + Get(req *model.ServiceContract) *model.EnrichServiceContract } ) diff --git a/cache/mock/cache_mock.go b/cache/mock/cache_mock.go index a3c83f4a3..4617428cf 100644 --- a/cache/mock/cache_mock.go +++ b/cache/mock/cache_mock.go @@ -955,6 +955,20 @@ func (mr *MockServiceContractCacheMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockServiceContractCache)(nil).Close)) } +// Get mocks base method. +func (m *MockServiceContractCache) Get(req *model.ServiceContract) *model.EnrichServiceContract { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", req) + ret0, _ := ret[0].(*model.EnrichServiceContract) + return ret0 +} + +// Get indicates an expected call of Get. +func (mr *MockServiceContractCacheMockRecorder) Get(req interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServiceContractCache)(nil).Get), req) +} + // Initialize mocks base method. func (m *MockServiceContractCache) Initialize(c map[string]interface{}) error { m.ctrl.T.Helper() @@ -2090,6 +2104,21 @@ func (mr *MockConfigGroupCacheMockRecorder) Initialize(c interface{}) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Initialize", reflect.TypeOf((*MockConfigGroupCache)(nil).Initialize), c) } +// ListGroups mocks base method. +func (m *MockConfigGroupCache) ListGroups(namespace string) ([]*model.ConfigFileGroup, string) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListGroups", namespace) + ret0, _ := ret[0].([]*model.ConfigFileGroup) + ret1, _ := ret[1].(string) + return ret0, ret1 +} + +// ListGroups indicates an expected call of ListGroups. +func (mr *MockConfigGroupCacheMockRecorder) ListGroups(namespace interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListGroups", reflect.TypeOf((*MockConfigGroupCache)(nil).ListGroups), namespace) +} + // Name mocks base method. func (m *MockConfigGroupCache) Name() string { m.ctrl.T.Helper() diff --git a/cache/service/service_contract.go b/cache/service/service_contract.go index 5546f30ea..d6f73e2bb 100644 --- a/cache/service/service_contract.go +++ b/cache/service/service_contract.go @@ -46,6 +46,8 @@ type serviceContractCache struct { lastMtimeLogged int64 + // data namespace/service/name/protocol/version -> *model.EnrichServiceContract + data *utils.SyncMap[string, *model.EnrichServiceContract] // contracts 服务契约缓存,namespace -> service -> []*model.EnrichServiceContract contracts *utils.SyncMap[string, *utils.SyncMap[string, *utils.SyncMap[string, *model.EnrichServiceContract]]] singleGroup *singleflight.Group @@ -54,6 +56,7 @@ type serviceContractCache struct { // Initialize func (sc *serviceContractCache) Initialize(c map[string]interface{}) error { sc.singleGroup = &singleflight.Group{} + sc.data = utils.NewSyncMap[string, *model.EnrichServiceContract]() sc.contracts = utils.NewSyncMap[string, *utils.SyncMap[string, *utils.SyncMap[string, *model.EnrichServiceContract]]]() return nil } @@ -113,11 +116,13 @@ func (sc *serviceContractCache) setContracts(values []*model.EnrichServiceContra serviceVal, _ := namespaceVal.Load(service) if !item.Valid { del++ + sc.data.Delete(item.GetCacheKey()) serviceVal.Delete(item.ID) continue } upsert++ + sc.data.Store(item.GetCacheKey(), item) serviceVal.Store(item.ID, item) } return map[string]time.Time{ @@ -127,6 +132,7 @@ func (sc *serviceContractCache) setContracts(values []*model.EnrichServiceContra // Clear func (sc *serviceContractCache) Clear() error { + sc.data = utils.NewSyncMap[string, *model.EnrichServiceContract]() sc.contracts = utils.NewSyncMap[string, *utils.SyncMap[string, *utils.SyncMap[string, *model.EnrichServiceContract]]]() return nil } @@ -148,6 +154,11 @@ func (sc *serviceContractCache) forceQueryUpdate() error { return err } +func (sc *serviceContractCache) Get(req *model.ServiceContract) *model.EnrichServiceContract { + ret, _ := sc.data.Load(req.GetCacheKey()) + return ret +} + // Query . func (sc *serviceContractCache) Query(filter map[string]string, offset, limit uint32) ([]*model.EnrichServiceContract, uint32, error) { if err := sc.forceQueryUpdate(); err != nil { diff --git a/common/model/contract.go b/common/model/contract.go index 34483ee5f..a5e1f9b46 100644 --- a/common/model/contract.go +++ b/common/model/contract.go @@ -97,10 +97,14 @@ type ServiceContractView struct { ManualInterfaces map[string]*InterfaceDescriptor } -func (s *ServiceContract) GetKey() string { +func (s *ServiceContract) GetResourceName() string { return fmt.Sprintf("%s/%s/%s/%s", s.Service, s.Name, s.Protocol, s.Version) } +func (s *ServiceContract) GetCacheKey() string { + return fmt.Sprintf("%s/%s/%s/%s/%s", s.Namespace, s.Service, s.Name, s.Protocol, s.Version) +} + type InterfaceDescriptor struct { // ID ID string diff --git a/release/standalone/linux/install.sh b/release/standalone/linux/install.sh index 781f91fcf..877de26b1 100644 --- a/release/standalone/linux/install.sh +++ b/release/standalone/linux/install.sh @@ -60,6 +60,7 @@ xdsv3_port=$(getProperties polaris_xdsv3_port) service_grpc_port=$(getProperties polaris_service_grpc_port) config_grpc_port=$(getProperties polaris_config_grpc_port) api_http_port=$(getProperties polaris_open_api_port) +nacos_port=$(getProperties nacos_http_port) prometheus_port=$(getProperties prometheus_port) pushgateway_port=$(getProperties pushgateway_port) @@ -78,6 +79,7 @@ echo "xdsv3_port=${xdsv3_port}" echo "service_grpc_port=${service_grpc_port}" echo "config_grpc_port=${config_grpc_port}" echo "api_http_port=${api_http_port}" +echo "nacos_port=${nacos_port}" echo "" echo "polaris-limiter-server listen port info" echo "polaris_limiter_http_port=${limiter_http_port}" @@ -126,6 +128,8 @@ function installPolarisServer() { sed -i "s/listenPort: 8093/listenPort: ${config_grpc_port}/g" conf/polaris-server.yaml # 修改 polaris-server http-api 端口信息 sed -i "s/listenPort: 8090/listenPort: ${api_http_port}/g" conf/polaris-server.yaml + # 修改 polaris-server nacos 端口信息 + sed -i "s/listenPort: 8848/listenPort: ${nacos_port}/g" conf/polaris-server.yaml /bin/bash ./tool/start.sh echo -e "install polaris server success" diff --git a/release/standalone/port.properties b/release/standalone/port.properties index dfb288225..4b57b4712 100644 --- a/release/standalone/port.properties +++ b/release/standalone/port.properties @@ -9,3 +9,5 @@ polaris_limiter_http_port=8100 polaris_limiter_grpc_port=8101 prometheus_port=9090 pushgateway_port=9091 +nacos_http_port=8848 +nacos_grpc_port=9848 diff --git a/release/tool/include b/release/tool/include index 58174c42a..29832900b 100644 --- a/release/tool/include +++ b/release/tool/include @@ -49,6 +49,7 @@ function start() { set +e ulimit -n 409600 set -e + chmod +x $server_name nohup $cmdline >>/dev/null 2>&1 & } diff --git a/service/api_v1.go b/service/api_v1.go index ce43adaee..9c6029415 100644 --- a/service/api_v1.go +++ b/service/api_v1.go @@ -182,6 +182,8 @@ type ClientServer interface { GetFaultDetectWithCache(ctx context.Context, req *apiservice.Service) *apiservice.DiscoverResponse // UpdateInstance update one instance by client UpdateInstance(ctx context.Context, req *apiservice.Instance) *apiservice.Response + // ReportServiceContract client report service_contract + ReportServiceContract(ctx context.Context, req *apiservice.ServiceContract) *apiservice.Response } // L5OperateServer L5 related operations diff --git a/service/client_v1.go b/service/client_v1.go index 2ccedb8ab..3311abcf7 100644 --- a/service/client_v1.go +++ b/service/client_v1.go @@ -47,6 +47,28 @@ func (s *Server) DeregisterInstance(ctx context.Context, req *apiservice.Instanc return s.DeleteInstance(ctx, req) } +// ReportServiceContract report client service interface info +func (s *Server) ReportServiceContract(ctx context.Context, req *apiservice.ServiceContract) *apiservice.Response { + ctx = context.WithValue(ctx, utils.ContextIsFromClient, true) + cacheData := s.caches.ServiceContract().Get(&model.ServiceContract{ + Namespace: req.GetNamespace(), + Service: req.GetService(), + Name: req.GetName(), + Version: req.GetVersion(), + Protocol: req.GetProtocol(), + }) + // 通过 Cache 模块减少无意义的 CreateServiceContract 逻辑 + if cacheData == nil || cacheData.Content != req.GetContent() { + rsp := s.CreateServiceContract(ctx, req) + if rsp.GetCode().GetValue() != uint32(apimodel.Code_ExecuteSuccess) { + return rsp + } + } + + rsp := s.CreateServiceContractInterfaces(ctx, req, apiservice.InterfaceDescriptor_Client) + return rsp +} + // ReportClient 客户端上报信息 func (s *Server) ReportClient(ctx context.Context, req *apiservice.Client) *apiservice.Response { if s.caches == nil { diff --git a/service/interceptor/auth/client_v1_authability.go b/service/interceptor/auth/client_v1_authability.go index a4f0119a2..9d0ceeea2 100644 --- a/service/interceptor/auth/client_v1_authability.go +++ b/service/interceptor/auth/client_v1_authability.go @@ -21,6 +21,7 @@ import ( "context" apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" + "google.golang.org/protobuf/types/known/wrapperspb" api "github.com/polarismesh/polaris/common/api/v1" "github.com/polarismesh/polaris/common/model" @@ -66,6 +67,25 @@ func (svr *ServerAuthAbility) ReportClient(ctx context.Context, req *apiservice. return svr.targetServer.ReportClient(ctx, req) } +// ReportServiceContract . +func (svr *ServerAuthAbility) ReportServiceContract(ctx context.Context, req *apiservice.ServiceContract) *apiservice.Response { + authCtx := svr.collectServiceAuthContext( + ctx, []*apiservice.Service{{ + Name: wrapperspb.String(req.GetService()), + Namespace: wrapperspb.String(req.GetNamespace()), + }}, model.Create, "ReportServiceContract") + + _, err := svr.strategyMgn.GetAuthChecker().CheckClientPermission(authCtx) + if err != nil { + resp := api.NewResponseWithMsg(convertToErrCode(err), err.Error()) + return resp + } + + ctx = authCtx.GetRequestContext() + ctx = context.WithValue(ctx, utils.ContextAuthContextKey, authCtx) + return svr.targetServer.ReportServiceContract(ctx, req) +} + // GetPrometheusTargets Used for client acquisition service information func (svr *ServerAuthAbility) GetPrometheusTargets(ctx context.Context, query map[string]string) *model.PrometheusDiscoveryResponse { diff --git a/service/service_contract.go b/service/service_contract.go index 2e874e2a0..7f6cf937e 100644 --- a/service/service_contract.go +++ b/service/service_contract.go @@ -431,7 +431,7 @@ func serviceContractRecordEntry(ctx context.Context, req *apiservice.ServiceCont entry := &model.RecordEntry{ ResourceType: model.RServiceContract, - ResourceName: data.GetKey(), + ResourceName: data.GetResourceName(), Namespace: req.GetNamespace(), OperationType: operationType, Operator: utils.ParseOperator(ctx), diff --git a/service/service_contract_test.go b/service/service_contract_test.go index 4f14281bc..a0b4a68fe 100644 --- a/service/service_contract_test.go +++ b/service/service_contract_test.go @@ -22,11 +22,12 @@ import ( "testing" "github.com/golang/protobuf/ptypes" - "github.com/polarismesh/polaris/common/utils" apimodel "github.com/polarismesh/specification/source/go/api/v1/model" "github.com/polarismesh/specification/source/go/api/v1/service_manage" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/types/known/anypb" + + "github.com/polarismesh/polaris/common/utils" ) func TestServer_CreateServiceContracts(t *testing.T) {