diff --git a/README.md b/README.md index 795da8f..466691d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Nacos as config centre. #### Server ```go +package main + import ( "context" "log" @@ -36,21 +38,16 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon } func main() { - nacosClient, err := nacos.DefaultClient() + klog.SetLevel(klog.LevelDebug) + nacosClient, err := nacos.New(nacos.Options{}) if err != nil { panic(err) } - serviceName := "echo" - - opts := []server.Option{ - server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - } - - opts = append(opts, nacosserver.NewSuite(serviceName, nacosClient).Options()...) - + serviceName := "ServiceName" svr := echo.NewServer( new(EchoImpl), - opts..., + server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), + server.WithSuite(nacosserver.NewSuite(serviceName, nacosClient)), ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) @@ -63,6 +60,8 @@ func main() { #### Client ```go +package main + import ( "context" "log" @@ -79,7 +78,7 @@ import ( func main() { klog.SetLevel(klog.LevelDebug) - nacosClient, err := nacos.DefaultClient() + nacosClient, err := nacos.New(nacos.Options{}) if err != nil { panic(err) } @@ -88,18 +87,12 @@ func main() { klog.Infof("nacos config %v", cp) } - opts := []client.Option{ - client.WithHostPorts("0.0.0.0:8888"), - } - - serviceName := "echo" - clientName := "test" - - opts = append(opts, nacosclient.NewSuite(serviceName, clientName, nacosClient, fn).Options()...) - + serviceName := "ServiceName" + clientName := "ClientName" client, err := echo.NewClient( serviceName, - opts..., + client.WithHostPorts("0.0.0.0:8888"), + client.WithSuite(nacosclient.NewSuite(serviceName, clientName, nacosClient, fn)), ) if err != nil { log.Fatal(err) @@ -116,16 +109,146 @@ func main() { } ``` -### Environment Variable +### Nacos Configuration + +The client is initialized according to the parameters of `Options` and connects to the nacos server. After the connection is established, the suite subscribes the appropriate configuration based on `Group`, `ServerDataIDFormat` and `ClientDataIDFormat` to updates its own policy dynamically. See the environment variables below for specific parameters. + +The configuration format supports `json` and `yaml`. You can use the [SetParser](https://github.com/kitex-contrib/config-nacos/blob/eb006978517678dd75a81513142d3faed6a66f8d/nacos/nacos.go#L68) function to customise the format parsing method, and the `CustomFunction` function to customise the format of the subscription function during `NewSuite`. +#### -| Environment Variable Name | Environment Variable Default Value | Environment Variable Introduction | +#### CustomFunction + +Provide the mechanism to custom the nacos parameter `vo.ConfigParam`. + +#### Options Variable + +| Variable Name | Default Value | Introduction | | ------------------------- | ---------------------------------- | --------------------------------- | -| serverAddr | 127.0.0.1 | nacos server address | -| serverPort | 8848 | nacos server port | -| namespace | | the namespaceId of nacos | -| configDataId | {{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}} | the format of config data id | -| configGroup | DEFAULT_GROUP | the group of config data | +| Address | 127.0.0.1 | Nacos server address | +| Port | 8848 | Nacos server port | +| NamespaceID | | The namespaceID of Nacos 中的 namespace Id | +| ClientDataIDFormat | {{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}} | Use go [template](https://pkg.go.dev/text/template) syntax rendering to generate the appropriate ID, and use `ClientServiceName` `ServiceName` `Category` three metadata that can be customised | +| ServerDataIDFormat | {{.ServerServiceName}}.{{.Category}} | Use go [template](https://pkg.go.dev/text/template) syntax rendering to generate the appropriate ID, and use `ServiceName` `Category` two metadatas that can be customised | +| Group | DEFAULT_GROUP | Use fixed values or dynamic rendering. Usage is the same as configDataId. | + +#### Governance Policy +> The configDataId and configGroup in the following example use default values, the service name is `ServiceName` and the client name is `ClientName`. + +##### Rate Limit Category=limit +> Currently, current limiting only supports the server side, so ClientServiceName is empty. + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/limiter/item_limiter.go#L33) + +|Variable|Introduction| +|----|----| +|connection_limit| Maximum concurrent connections | +|qps_limit| Maximum request number every 100ms | +Example: +``` +configDataID: ServiceName.limit +{ + "connection_limit": 100, + "qps_limit": 2000 +} +``` + +Note: + +- The granularity of the current limit configuration is server global, regardless of client or method. +- Not configured or value is 0 means not enabled. +- connection_limit and qps_limit can be configured independently, e.g. connection_limit = 100, qps_limit = 0 + +##### Retry Policy Category=retry +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/retry/policy.go#L63) + +|Variable|Introduction| +|----|----| +|type| 0: failure_policy 1: backup_policy| +|failure_policy.backoff_policy| Can only be set one of `fixed` `none` `random` | + +Example: +``` +configDataId: ClientName.ServiceName.retry +{ + "*": { + "enable": true, + "type": 0, + "failure_policy": { + "stop_policy": { + "max_retry_times": 3, + "max_duration_ms": 2000, + "cb_policy": { + "error_rate": 0.5 + } + }, + "backoff_policy": { + "backoff_type": "fixed", + "cfg_items": { + "fix_ms": 50 + } + }, + "retry_same_node": false + } + }, + "echo": { + "enable": true, + "type": 1, + "backup_policy": { + "retry_delay_ms": 100, + "retry_same_node": false, + "stop_policy": { + "max_retry_times": 2, + "max_duration_ms": 300, + "cb_policy": { + "error_rate": 0.2 + } + } + } + } +} +``` +Note: retry.Container has built-in support for specifying the default configuration using the `*` wildcard (see the [getRetryer](https://github.com/cloudwego/kitex/blob/v0.5.1/pkg/retry/retryer.go#L240) method for details). + +##### RPC Timeout Category=rpc_timeout + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/rpctimeout/item_rpc_timeout.go#L42) + +Example: +``` +configDataId: ClientName.ServiceName.rpc_timeout +{ + "*": { + "conn_timeout_ms": 100, + "rpc_timeout_ms": 3000 + }, + "echo": { + "conn_timeout_ms": 50, + "rpc_timeout_ms": 1000 + } +} +``` +Note: The circuit breaker implementation of kitex does not currently support changing the global default configuration (see [initServiceCB](https://github.com/cloudwego/kitex/blob/v0.5.1/pkg/circuitbreak/cbsuite.go#L195) for details). + +##### Circuit Break: Category=circuit_break + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/circuitbreak/item_circuit_breaker.go#L30) + +|Variable|Introduction| +|----|----| +|min_sample| Minimum statistical sample number| +Example: +``` +The echo method uses the following configuration (0.3, 100) and other methods use the global default configuration (0.5, 200) +configDataId: `ClientName.ServiecName.circuit_break` +{ + "echo": { + "enable": true, + "err_rate": 0.3, + "min_sample": 100 + } +} +``` ### More Info Refer to [example](https://github.com/kitex-contrib/config-nacos/tree/main/example) for more usage. diff --git a/README_CN.md b/README_CN.md index 5713340..9265870 100644 --- a/README_CN.md +++ b/README_CN.md @@ -11,6 +11,8 @@ #### 服务端 ```go +package main + import ( "context" "log" @@ -36,21 +38,16 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon } func main() { - nacosClient, err := nacos.DefaultClient() + klog.SetLevel(klog.LevelDebug) + nacosClient, err := nacos.New(nacos.Options{}) if err != nil { panic(err) } - serviceName := "echo" - - opts := []server.Option{ - server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - } - - opts = append(opts, nacosserver.NewSuite(serviceName, nacosClient).Options()...) - + serviceName := "ServiceName" svr := echo.NewServer( new(EchoImpl), - opts..., + server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), + server.WithSuite(nacosserver.NewSuite(serviceName, nacosClient)), ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) @@ -63,6 +60,8 @@ func main() { #### 客户端 ```go +package main + import ( "context" "log" @@ -79,7 +78,7 @@ import ( func main() { klog.SetLevel(klog.LevelDebug) - nacosClient, err := nacos.DefaultClient() + nacosClient, err := nacos.New(nacos.Options{}) if err != nil { panic(err) } @@ -88,18 +87,12 @@ func main() { klog.Infof("nacos config %v", cp) } - opts := []client.Option{ - client.WithHostPorts("0.0.0.0:8888"), - } - - serviceName := "echo" - clientName := "test" - - opts = append(opts, nacosclient.NewSuite(serviceName, clientName, nacosClient, fn).Options()...) - + serviceName := "ServiceName" + clientName := "ClientName" client, err := echo.NewClient( serviceName, - opts..., + client.WithHostPorts("0.0.0.0:8888"), + client.WithSuite(nacosclient.NewSuite(serviceName, clientName, nacosClient, fn)), ) if err != nil { log.Fatal(err) @@ -115,16 +108,146 @@ func main() { } } ``` +### Nacos 配置 + +根据 Options 的参数初始化 client,建立链接之后 suite 会根据 `Group` 以及 `ServerDataIDFormat` 或者 `ClientDataIDFormat` 订阅对应的配置并动态更新自身策略,具体参数参考下面环境变量。 + +配置的格式默认支持 `json` 和 `yaml`,可以使用函数 [SetParser](https://github.com/kitex-contrib/config-nacos/blob/eb006978517678dd75a81513142d3faed6a66f8d/nacos/nacos.go#L68) 进行自定义格式解析方式,并在 `NewSuite` 的时候使用 `CustomFunction` 函数修改订阅函数的格式。 + +#### CustomFunction -### 环境变量 +允许用户自定义 nacos 的参数. -| 变量名 | 变量默认值 | 作用 | +#### Options 默认值 + +| 参数 | 变量默认值 | 作用 | | ------------------------- | ---------------------------------- | --------------------------------- | -| serverAddr | 127.0.0.1 | nacos 服务器地址 | -| serverPort | 8848 | nacos 服务器端口 | -| namespace | | nacos 中的 namespace Id | -| configDataId | {{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}} | the format of config data id | -| configGroup | DEFAULT_GROUP | the group of config data | +| Address | 127.0.0.1 | nacos 服务器地址 | +| Port | 8848 | nacos 服务器端口 | +| NamespaceID | | nacos 中的 namespace Id | +| ClientDataIDFormat | {{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}} | 使用 go [template](https://pkg.go.dev/text/template) 语法渲染生成对应的 ID, 使用 `ClientServiceName` `ServiceName` `Category` 三个元数据 | +| ServerDataIDFormat | {{.ServerServiceName}}.{{.Category}} | 使用 go [template](https://pkg.go.dev/text/template) 语法渲染生成对应的 ID, 使用 `ServiceName` `Category` 两个元数据 | +| Group | DEFAULT_GROUP | 使用固定值,也可以动态渲染,用法同 DataIDFormat | + +#### 治理策略 + +下面例子中的 configDataId 以及 configGroup 均使用默认值,服务名称为 ServiceName,客户端名称为 ClientName + +##### 限流 Category=limit +> 限流目前只支持服务端,所以 ClientServiceName 为空。 + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/limiter/item_limiter.go#L33) + +|字段|说明| +|----|----| +|connection_limit|最大并发数量| +|qps_limit|每 100ms 内的最大请求数量| + +例子: +``` +configDataID: ServiceName.limit +{ + "connection_limit": 100, + "qps_limit": 2000 +} +``` +注: + +- 限流配置的粒度是 Server 全局,不分 client、method +- 「未配置」或「取值为 0」表示不开启 +- connection_limit 和 qps_limit 可以独立配置,例如 connection_limit = 100, qps_limit = 0 + +##### 重试 Category=retry + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/retry/policy.go#L63) + +|参数|说明| +|----|----| +|type| 0: failure_policy 1: backup_policy| +|failure_policy.backoff_policy| 可以设置的策略: `fixed` `none` `random` | + +例子: +``` +configDataId: ClientName.ServiceName.retry +{ + "*": { + "enable": true, + "type": 0, + "failure_policy": { + "stop_policy": { + "max_retry_times": 3, + "max_duration_ms": 2000, + "cb_policy": { + "error_rate": 0.5 + } + }, + "backoff_policy": { + "backoff_type": "fixed", + "cfg_items": { + "fix_ms": 50 + } + }, + "retry_same_node": false + } + }, + "echo": { + "enable": true, + "type": 1, + "backup_policy": { + "retry_delay_ms": 100, + "retry_same_node": false, + "stop_policy": { + "max_retry_times": 2, + "max_duration_ms": 300, + "cb_policy": { + "error_rate": 0.2 + } + } + } + } +} +``` +注:retry.Container 内置支持用 * 通配符指定默认配置(详见 [getRetryer](https://github.com/cloudwego/kitex/blob/v0.5.1/pkg/retry/retryer.go#L240) 方法) + +##### 超时 Category=rpc_timeout + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/rpctimeout/item_rpc_timeout.go#L42) + +例子: +``` +configDataId: ClientName.ServiceName.rpc_timeout +{ + "*": { + "conn_timeout_ms": 100, + "rpc_timeout_ms": 3000 + }, + "echo": { + "conn_timeout_ms": 50, + "rpc_timeout_ms": 1000 + } +} +``` +注:kitex 的熔断实现目前不支持修改全局默认配置(详见 [initServiceCB](https://github.com/cloudwego/kitex/blob/v0.5.1/pkg/circuitbreak/cbsuite.go#L195)) + +##### 熔断: Category=circuit_break + +[JSON Schema](https://github.com/cloudwego/kitex/blob/develop/pkg/circuitbreak/item_circuit_breaker.go#L30) + +|参数|说明| +|----|----| +|min_sample| 最小的统计样本数| +例子: +``` +echo 方法使用下面的配置(0.3、100),其他方法使用全局默认配置(0.5、200) +configDataId: `ClientName.ServiceName.circuit_break` +{ + "echo": { + "enable": true, + "err_rate": 0.3, + "min_sample": 100 + } +} +``` ### 更多信息 diff --git a/client/circuit_breaker.go b/client/circuit_breaker.go index 0f0ae59..95f576c 100644 --- a/client/circuit_breaker.go +++ b/client/circuit_breaker.go @@ -31,11 +31,14 @@ import ( func WithCircuitBreaker(dest, src string, nacosClient nacos.Client, cfs ...nacos.CustomFunction, ) []client.Option { - param := nacos.NacosConfigParam(&nacos.ConfigParamConfig{ + param, err := nacosClient.ClientConfigParam(&nacos.ConfigParamConfig{ Category: circuitBreakerConfigName, ServerServiceName: dest, ClientServiceName: src, }, cfs...) + if err != nil { + panic(err) + } cbSuite := initCircuitBreaker(param, dest, src, nacosClient) diff --git a/client/retry.go b/client/retry.go index 31fc0f7..05820e0 100644 --- a/client/retry.go +++ b/client/retry.go @@ -28,11 +28,14 @@ import ( func WithRetryPolicy(dest, src string, nacosClient nacos.Client, cfs ...nacos.CustomFunction, ) []client.Option { - param := nacos.NacosConfigParam(&nacos.ConfigParamConfig{ + param, err := nacosClient.ClientConfigParam(&nacos.ConfigParamConfig{ Category: retryConfigName, ServerServiceName: dest, ClientServiceName: src, }, cfs...) + if err != nil { + panic(err) + } return []client.Option{ client.WithRetryContainer(initRetryContainer(param, dest, nacosClient)), diff --git a/client/rpc_timeout.go b/client/rpc_timeout.go index 063b5be..dc094be 100644 --- a/client/rpc_timeout.go +++ b/client/rpc_timeout.go @@ -27,11 +27,14 @@ import ( func WithRPCTimeout(dest, src string, nacosClient nacos.Client, cfs ...nacos.CustomFunction, ) []client.Option { - param := nacos.NacosConfigParam(&nacos.ConfigParamConfig{ + param, err := nacosClient.ClientConfigParam(&nacos.ConfigParamConfig{ Category: rpcTimeoutConfigName, ServerServiceName: dest, ClientServiceName: src, }, cfs...) + if err != nil { + panic(err) + } return []client.Option{ client.WithTimeoutProvider(initRPCTimeoutContainer(param, dest, nacosClient)), diff --git a/example/client/main.go b/example/client/main.go index f06a875..52f0b67 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -18,6 +18,7 @@ package main import ( "context" "log" + "time" "github.com/cloudwego/kitex-examples/kitex_gen/api" "github.com/cloudwego/kitex-examples/kitex_gen/api/echo" @@ -31,7 +32,7 @@ import ( func main() { klog.SetLevel(klog.LevelDebug) - nacosClient, err := nacos.DefaultClient() + nacosClient, err := nacos.New(nacos.Options{}) if err != nil { panic(err) } @@ -40,18 +41,12 @@ func main() { klog.Infof("nacos config %v", cp) } - opts := []client.Option{ - client.WithHostPorts("0.0.0.0:8888"), - } - - serviceName := "echo" - clientName := "test" - - opts = append(opts, nacosclient.NewSuite(serviceName, clientName, nacosClient, fn).Options()...) - + serviceName := "ServiceName" + clientName := "ClientName" client, err := echo.NewClient( serviceName, - opts..., + client.WithHostPorts("0.0.0.0:8888"), + client.WithSuite(nacosclient.NewSuite(serviceName, clientName, nacosClient, fn)), ) if err != nil { log.Fatal(err) @@ -64,5 +59,6 @@ func main() { } else { klog.Infof("receive response %v", resp) } + time.Sleep(time.Second * 10) } } diff --git a/example/server/main.go b/example/server/main.go index 4ae4201..b36bf88 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -41,21 +41,15 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon func main() { klog.SetLevel(klog.LevelDebug) - nacosClient, err := nacos.DefaultClient() + nacosClient, err := nacos.New(nacos.Options{}) if err != nil { panic(err) } - serviceName := "echo" - - opts := []server.Option{ - server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - } - - opts = append(opts, nacosserver.NewSuite(serviceName, nacosClient).Options()...) - + serviceName := "ServiceName" svr := echo.NewServer( new(EchoImpl), - opts..., + server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), + server.WithSuite(nacosserver.NewSuite(serviceName, nacosClient)), ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) diff --git a/go.mod b/go.mod index e2cc5e9..7eff699 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/kitex-contrib/config-nacos go 1.19 require ( - github.com/cloudwego/kitex v0.6.2-0.20230825063748-0068e34282a5 + github.com/cloudwego/kitex v0.7.1 github.com/cloudwego/kitex-examples v0.2.0 github.com/nacos-group/nacos-sdk-go v1.1.4 github.com/stretchr/testify v1.8.2 @@ -20,7 +20,7 @@ require ( github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/choleraehyq/pid v0.0.17 // indirect github.com/cloudwego/configmanager v0.2.0 // indirect - github.com/cloudwego/dynamicgo v0.1.2 // indirect + github.com/cloudwego/dynamicgo v0.1.3 // indirect github.com/cloudwego/fastpb v0.0.4 // indirect github.com/cloudwego/frugal v0.1.7 // indirect github.com/cloudwego/localsession v0.0.2 // indirect diff --git a/go.sum b/go.sum index 605f891..c2d11a7 100644 --- a/go.sum +++ b/go.sum @@ -467,8 +467,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudwego/configmanager v0.2.0 h1:niVpVg+wQ+npNqnH3dup96SMbR02Pk+tNErubYCJqKo= github.com/cloudwego/configmanager v0.2.0/go.mod h1:FLIQTjxsZRGjnmDhTttWQTy6f6DghPTatfBVOs2gQLk= github.com/cloudwego/dynamicgo v0.1.0/go.mod h1:Mdsz0XGsIImi15vxhZaHZpspNChEmBMIiWkUfD6JDKg= -github.com/cloudwego/dynamicgo v0.1.2 h1:t5KMzo/UkT002n3EvGI0Y6+Me73NGDzFI/AQlT1LQME= -github.com/cloudwego/dynamicgo v0.1.2/go.mod h1:AdPqyFN+0+fc3iVSSWojDCnOGPkzH+T0rI65017GCUA= +github.com/cloudwego/dynamicgo v0.1.3 h1:xK2rFS3E7cGbo4CWhqP1HIWeQcVH4Po5YgdNFDC+CfI= +github.com/cloudwego/dynamicgo v0.1.3/go.mod h1:AdPqyFN+0+fc3iVSSWojDCnOGPkzH+T0rI65017GCUA= github.com/cloudwego/fastpb v0.0.3/go.mod h1:/V13XFTq2TUkxj2qWReV8MwfPC4NnPcy6FsrojnsSG0= github.com/cloudwego/fastpb v0.0.4-0.20230131074846-6fc453d58b96/go.mod h1:/V13XFTq2TUkxj2qWReV8MwfPC4NnPcy6FsrojnsSG0= github.com/cloudwego/fastpb v0.0.4 h1:/ROVVfoFtpfc+1pkQLzGs+azjxUbSOsAqSY4tAAx4mg= @@ -483,8 +483,8 @@ github.com/cloudwego/kitex v0.3.2/go.mod h1:/XD07VpUD9VQWmmoepASgZ6iw//vgWikVA9M github.com/cloudwego/kitex v0.4.4/go.mod h1:3FcH5h9Qw+dhRljSzuGSpWuThttA8DvK0BsL7HUYydo= github.com/cloudwego/kitex v0.5.0/go.mod h1:yhw7XikNVG4RstmlQAidBuxMlZYpIiCLsDU8eHPGEMo= github.com/cloudwego/kitex v0.6.1/go.mod h1:zI1GBrjT0qloTikcCfQTgxg3Ws+yQMyaChEEOcGNUvA= -github.com/cloudwego/kitex v0.6.2-0.20230825063748-0068e34282a5 h1:AIEVSRU5aC6Gk+CXpkNMVxyiPZRpKVSfo/pnYyw2Mvo= -github.com/cloudwego/kitex v0.6.2-0.20230825063748-0068e34282a5/go.mod h1:RVWi+MbiPzI0Gi7fz8KZp+zsxB1/pLJZkr4kEwAuX6k= +github.com/cloudwego/kitex v0.7.1 h1:GbCsJ+zDOCsjHaqXVLLD6QIHqDnKPqefqU3+QAOhclg= +github.com/cloudwego/kitex v0.7.1/go.mod h1:TU0FRxTH26XpbR7zm063O/OfqSszVlQvM1eGJES2A4E= github.com/cloudwego/kitex-examples v0.2.0 h1:77PXV+5q5OCKE38q2DVvHO7ePemtNapwnX+n6zaVSjo= github.com/cloudwego/kitex-examples v0.2.0/go.mod h1:jmqlyPgALXoYXiZwWJSpzb8wEycu9PIIyRRs2cN9OJs= github.com/cloudwego/localsession v0.0.2 h1:N9/IDtCPj1fCL9bCTP+DbXx3f40YjVYWcwkJG0YhQkY= diff --git a/nacos/env.go b/nacos/env.go deleted file mode 100644 index 5410b50..0000000 --- a/nacos/env.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2023 CloudWeGo 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 nacos - -import ( - "bytes" - "os" - "strconv" - "text/template" - - "github.com/nacos-group/nacos-sdk-go/vo" - - "github.com/cloudwego/kitex/pkg/klog" -) - -const ( - NACOS_ENV_SERVER_ADDR = "serverAddr" - NACOS_ENV_PORT = "serverPort" - NACOS_ENV_NAMESPACE_ID = "namespace" - NACOS_ENV_CONFIG_GROUP = "configGroup" - NACOS_ENV_CONFIG_DATA_ID = "configDataId" - NACOS_DEFAULT_SERVER_ADDR = "127.0.0.1" - NACOS_DEFAULT_PORT = 8848 - NACOS_DEFAULT_REGIONID = "cn-hangzhou" - NACOS_DEFAULT_CONFIG_GROUP = "DEFAULT_GROUP" - NACOS_DEFAULT_DATA_ID = "{{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}}" -) - -const ( - defaultContent = "" -) - -// CustomFunction use for customize the config parameters. -type CustomFunction func(*vo.ConfigParam) - -// ConfigParamConfig use for render the dataId or group info by go template, ref: https://pkg.go.dev/text/template -// The fixed key shows as below. -type ConfigParamConfig struct { - Category string - ClientServiceName string - ServerServiceName string -} - -func render(name, format string, cpc *ConfigParamConfig) string { - t, err := template.New(name).Parse(format) - if err != nil { - panic(err) - } - var tpl bytes.Buffer - err = t.Execute(&tpl, cpc) - if err != nil { - panic(err) - } - return tpl.String() -} - -// NacosConfigParam Get nacos config from environment variables. All the parameters can be customized with CustomFunction. -// ConfigParam explain: -// 1. Type: data format, support JSON and YAML, JSON by default. Could extend it by implementing the ConfigParser interface. -// 2. Content: empty by default. Customize with CustomFunction. -// 3. Group: DEFAULT_GROUP by default. -// 4. DataId: {{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}} by default. Customize it by CustomFunction or -// use specified format. ref: nacos/env.go:46 -func NacosConfigParam(cpc *ConfigParamConfig, cfs ...CustomFunction) vo.ConfigParam { - param := vo.ConfigParam{ - DataId: render("dataId", NacosConfigDataId(), cpc), - Group: render("group", NacosConfigGroup(), cpc), - Type: vo.JSON, - Content: defaultContent, - } - for _, cf := range cfs { - cf(¶m) - } - return param -} - -// NacosConfigDataId Get nacos DataId from environment variables -func NacosConfigDataId() string { - dataId := os.Getenv(NACOS_ENV_CONFIG_DATA_ID) - if len(dataId) == 0 { - return NACOS_DEFAULT_DATA_ID - } - return dataId -} - -// NacosConfigGroup Get nacos config group from environment variables -func NacosConfigGroup() string { - configGroup := os.Getenv(NACOS_ENV_CONFIG_GROUP) - if len(configGroup) == 0 { - return NACOS_DEFAULT_CONFIG_GROUP - } - return configGroup -} - -// NacosPort Get Nacos port from environment variables -func NacosPort() int64 { - portText := os.Getenv(NACOS_ENV_PORT) - if len(portText) == 0 { - return NACOS_DEFAULT_PORT - } - port, err := strconv.ParseInt(portText, 10, 64) - if err != nil { - klog.Errorf("ParseInt failed,err:%s", err.Error()) - return NACOS_DEFAULT_PORT - } - return port -} - -// NacosAddr Get Nacos addr from environment variables -func NacosAddr() string { - addr := os.Getenv(NACOS_ENV_SERVER_ADDR) - if len(addr) == 0 { - return NACOS_DEFAULT_SERVER_ADDR - } - return addr -} - -// NacosNameSpaceId Get Nacos namespace id from environment variables -func NacosNameSpaceId() string { - return os.Getenv(NACOS_ENV_NAMESPACE_ID) -} diff --git a/nacos/env_test.go b/nacos/env_test.go deleted file mode 100644 index ee1a260..0000000 --- a/nacos/env_test.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2023 CloudWeGo 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 nacos - -import ( - "testing" - - "github.com/nacos-group/nacos-sdk-go/vo" - "github.com/stretchr/testify/assert" -) - -// TestEnvFunc test env func -func TestEnvFunc(t *testing.T) { - cpc := &ConfigParamConfig{ - Category: "retry", - ServerServiceName: "svc", - ClientServiceName: "cli", - } - - assert.Equal(t, int64(8848), NacosPort()) - assert.Equal(t, "127.0.0.1", NacosAddr()) - assert.Equal(t, "", NacosNameSpaceId()) - assert.Equal(t, vo.ConfigParam{ - Type: vo.JSON, - Group: NACOS_DEFAULT_CONFIG_GROUP, - Content: defaultContent, - DataId: "cli.svc.retry", - }, NacosConfigParam(cpc)) - - t.Setenv(NACOS_ENV_NAMESPACE_ID, "ns") - t.Setenv(NACOS_ENV_SERVER_ADDR, "1.1.1.1") - t.Setenv(NACOS_ENV_PORT, "80") - t.Setenv(NACOS_ENV_CONFIG_DATA_ID, "{{.ClientServiceName}}") - t.Setenv(NACOS_ENV_CONFIG_GROUP, "{{.Category}}") - - assert.Equal(t, int64(80), NacosPort()) - assert.Equal(t, "1.1.1.1", NacosAddr()) - assert.Equal(t, "ns", NacosNameSpaceId()) - assert.Equal(t, vo.ConfigParam{ - Type: vo.JSON, - Group: "retry", - Content: defaultContent, - DataId: "cli", - }, NacosConfigParam(cpc)) -} diff --git a/nacos/nacos.go b/nacos/nacos.go index 43b9fd4..a7f82d9 100644 --- a/nacos/nacos.go +++ b/nacos/nacos.go @@ -15,16 +15,22 @@ package nacos import ( + "bytes" + "text/template" + "github.com/cloudwego/kitex/pkg/klog" "github.com/nacos-group/nacos-sdk-go/clients" "github.com/nacos-group/nacos-sdk-go/clients/config_client" "github.com/nacos-group/nacos-sdk-go/common/constant" + "github.com/nacos-group/nacos-sdk-go/common/logger" "github.com/nacos-group/nacos-sdk-go/vo" ) // Client the wrapper of nacos client. type Client interface { SetParser(ConfigParser) + ClientConfigParam(cpc *ConfigParamConfig, cfs ...CustomFunction) (vo.ConfigParam, error) + ServerConfigParam(cpc *ConfigParamConfig, cfs ...CustomFunction) (vo.ConfigParam, error) RegisterConfigCallback(vo.ConfigParam, func(string, ConfigParser)) DeregisterConfig(vo.ConfigParam) error } @@ -32,21 +38,59 @@ type Client interface { type client struct { ncli config_client.IConfigClient // support customise parser - parser ConfigParser + parser ConfigParser + groupTemplate *template.Template + serverDataIDTemplate *template.Template + clientDataIDTemplate *template.Template +} + +// Options nacos config options. All the fields have default value. +type Options struct { + Address string + Port uint64 + NamespaceID string + RegionID string + Group string + ServerDataIDFormat string + ClientDataIDFormat string + CustomLogger logger.Logger + ConfigParser ConfigParser } -// DefaultClient Create a default Nacos client +// New Create a default Nacos client // It can create a client with default config by env variable. // See: env.go -func DefaultClient() (Client, error) { +func New(opts Options) (Client, error) { + if opts.Address == "" { + opts.Address = NacosDefaultServerAddr + } + if opts.Port == 0 { + opts.Port = NacosDefaultPort + } + if opts.CustomLogger == nil { + opts.CustomLogger = NewCustomNacosLogger() + } + if opts.ConfigParser == nil { + opts.ConfigParser = defaultConfigParse() + } + if opts.Group == "" { + opts.Group = NacosDefaultConfigGroup + } + if opts.ServerDataIDFormat == "" { + opts.ServerDataIDFormat = NacosDefaultServerDataID + } + if opts.ClientDataIDFormat == "" { + opts.ClientDataIDFormat = NacosDefaultClientDataID + } + sc := []constant.ServerConfig{ - *constant.NewServerConfig(NacosAddr(), uint64(NacosPort())), + *constant.NewServerConfig(opts.Address, opts.Port), } cc := constant.ClientConfig{ - NamespaceId: NacosNameSpaceId(), - RegionId: NACOS_DEFAULT_REGIONID, + NamespaceId: opts.NamespaceID, + RegionId: opts.RegionID, NotLoadCacheAtStart: true, - CustomLogger: NewCustomNacosLogger(), + CustomLogger: opts.CustomLogger, } nacosClient, err := clients.NewConfigClient( vo.NacosClientParam{ @@ -57,9 +101,24 @@ func DefaultClient() (Client, error) { if err != nil { return nil, err } + groupTemplate, err := template.New("group").Parse(opts.Group) + if err != nil { + return nil, err + } + serverDataIDTemplate, err := template.New("serverDataID").Parse(opts.ServerDataIDFormat) + if err != nil { + return nil, err + } + clientDataIDTemplate, err := template.New("clientDataID").Parse(opts.ClientDataIDFormat) + if err != nil { + return nil, err + } c := &client{ - ncli: nacosClient, - parser: defaultConfigParse(), + ncli: nacosClient, + parser: opts.ConfigParser, + groupTemplate: groupTemplate, + serverDataIDTemplate: serverDataIDTemplate, + clientDataIDTemplate: clientDataIDTemplate, } return c, nil } @@ -69,6 +128,53 @@ func (c *client) SetParser(parser ConfigParser) { c.parser = parser } +func (c *client) render(cpc *ConfigParamConfig, t *template.Template) (string, error) { + var tpl bytes.Buffer + err := t.Execute(&tpl, cpc) + if err != nil { + return "", err + } + return tpl.String(), nil +} + +// ServerConfigParam render server config parameters +func (c *client) ServerConfigParam(cpc *ConfigParamConfig, cfs ...CustomFunction) (vo.ConfigParam, error) { + return c.configParam(cpc, c.serverDataIDTemplate, cfs...) +} + +// ClientConfigParam render client config parameters +func (c *client) ClientConfigParam(cpc *ConfigParamConfig, cfs ...CustomFunction) (vo.ConfigParam, error) { + return c.configParam(cpc, c.clientDataIDTemplate, cfs...) +} + +// configParam render config parameters. All the parameters can be customized with CustomFunction. +// ConfigParam explain: +// 1. Type: data id format, support JSON and YAML, JSON by default. Could extend it by implementing the ConfigParser interface. +// 2. Content: empty by default. Customize with CustomFunction. +// 3. Group: DEFAULT_GROUP by default. +// 4. ServerDataId: {{.ServerServiceName}}.{{.Category}} by default. +// ClientDataId: {{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}} by default. +func (c *client) configParam(cpc *ConfigParamConfig, t *template.Template, cfs ...CustomFunction) (vo.ConfigParam, error) { + param := vo.ConfigParam{ + Type: vo.JSON, + Content: defaultContent, + } + var err error + param.DataId, err = c.render(cpc, t) + if err != nil { + return param, err + } + param.Group, err = c.render(cpc, c.groupTemplate) + if err != nil { + return param, err + } + + for _, cf := range cfs { + cf(¶m) + } + return param, nil +} + // DeregisterConfig deregister the config. func (c *client) DeregisterConfig(cfg vo.ConfigParam) error { return c.ncli.CancelListenConfig(cfg) diff --git a/nacos/parser.go b/nacos/parser.go index c3a56c5..36ba045 100644 --- a/nacos/parser.go +++ b/nacos/parser.go @@ -21,6 +21,29 @@ import ( "sigs.k8s.io/yaml" ) +const ( + NacosDefaultServerAddr = "127.0.0.1" + NacosDefaultPort = 8848 + NacosDefaultConfigGroup = "DEFAULT_GROUP" + NacosDefaultClientDataID = "{{.ClientServiceName}}.{{.ServerServiceName}}.{{.Category}}" + NacosDefaultServerDataID = "{{.ServerServiceName}}.{{.Category}}" +) + +const ( + defaultContent = "" +) + +// CustomFunction use for customize the config parameters. +type CustomFunction func(*vo.ConfigParam) + +// ConfigParamConfig use for render the dataId or group info by go template, ref: https://pkg.go.dev/text/template +// The fixed key shows as below. +type ConfigParamConfig struct { + Category string + ClientServiceName string + ServerServiceName string +} + var _ ConfigParser = &parser{} // ConfigParser the parser for nacos config. diff --git a/server/limiter.go b/server/limiter.go index 63a806c..7aee6fb 100644 --- a/server/limiter.go +++ b/server/limiter.go @@ -30,10 +30,13 @@ import ( func WithLimiter(dest string, nacosClient nacos.Client, cfs ...nacos.CustomFunction, ) server.Option { - param := nacos.NacosConfigParam(&nacos.ConfigParamConfig{ + param, err := nacosClient.ServerConfigParam(&nacos.ConfigParamConfig{ Category: limiterConfigName, ServerServiceName: dest, }, cfs...) + if err != nil { + panic(err) + } return server.WithLimit(initLimitOptions(param, dest, nacosClient)) }