Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(retry): support configure retry policy from nacos #1

Merged
merged 6 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ output/*

# Vscode files
.vscode

vendor
72 changes: 71 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,71 @@
# .github
# config-nacos (*This is a community driven project*)

[中文](https://github.com/kitex-contrib/config-nacos/blob/main/README_CN.md)

Nacos as config centre.

## How to use?

### Basic

#### Server

TODO

#### Client

```go
import (
// ...
"github.com/cloudwego/kitex-examples/kitex_gen/api/echo"
"github.com/cloudwego/kitex/client"
retry "github.com/kitex-contrib/config-nacos/client"
"github.com/kitex-contrib/config-nacos/nacos"
// ...
)

func main() {
// ...
nacosClient, err := nacos.DefaultClient()
if err != nil {
panic(err)
}
fn := func(cp *vo.ConfigParam) {
cp.Type = vo.TEXT
}
opts := []client.Option{
client.WithHostPorts("0.0.0.0:8888"),
client.WithMiddleware(mymiddleware.CommonMiddleware),
client.WithMiddleware(mymiddleware.ClientMiddleware),
//client.WithResolver(r),
}

opts = append(opts, retry.NewSuite("echo", "test", nacosClient, fn).Options()...)

client, err := echo.NewClient(
"echo",
opts...,
)
// ...
}
```

### Environment Variable

| Environment Variable Name | Environment Variable Default Value | Environment Variable 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 |

### More Info

Refer to [example](example) for more usage.

## Compatibility
This Package use Nacos1.x client. The Nacos2.0 and Nacos1.0 Server are fully compatible with it. [see](https://nacos.io/en-us/docs/v2/upgrading/2.0.0-compatibility.html)

maintained by: [whalecold](https://github.com/whalecold)

64 changes: 64 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# config-nacos

[English](https://github.com/kitex-contrib/config-nacos/blob/main/README.md)

使用 **nacos** 作为 **Kitex** 的配置中心

## 这个项目应当如何使用?

### 基本使用

#### 客户端

```go
import (
// ...
"github.com/cloudwego/kitex-examples/kitex_gen/api/echo"
"github.com/cloudwego/kitex/client"
retry "github.com/kitex-contrib/config-nacos/client"
"github.com/kitex-contrib/config-nacos/nacos"
// ...
)

func main() {
// ...
nacosClient, err := nacos.DefaultClient()
if err != nil {
panic(err)
}
fn := func(cp *vo.ConfigParam) {
cp.Type = vo.TEXT
}
opts := []client.Option{
client.WithHostPorts("0.0.0.0:8888"),
client.WithMiddleware(mymiddleware.CommonMiddleware),
client.WithMiddleware(mymiddleware.ClientMiddleware),
//client.WithResolver(r),
}

opts = append(opts, retry.NewSuite("echo", "test", nacosClient, fn).Options()...)

client, err := echo.NewClient(
"echo",
opts...,
)
// ...
}
```

### 环境变量

| 变量名 | 变量默认值 | 作用 |
| ------------------------- | ---------------------------------- | --------------------------------- |
| 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 |

### 更多信息

更多示例请参考 [example](example)

## 兼容性
该包使用 Nacos1.x 客户端,Nacos2.0 和 Nacos1.0 服务端完全兼容该版本. [详情](https://nacos.io/zh-cn/docs/v2/upgrading/2.0.0-compatibility.html)
48 changes: 48 additions & 0 deletions client/client_suite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 client

import (
"github.com/cloudwego/kitex/client"

"github.com/kitex-contrib/config-nacos/nacos"
)

// NacosClientSuite nacos client config suite, configure retry timeout limit and circuitbreak dynamically from nacos.
type NacosClientSuite struct {
nacosClient nacos.Client
service string
client string
fns []nacos.CustomFunction
}

// NewSuite service is the destination service name and client is the local identity.
func NewSuite(service, client string, cli nacos.Client,
cfs ...nacos.CustomFunction,
) *NacosClientSuite {
return &NacosClientSuite{
service: service,
client: client,
nacosClient: cli,
fns: cfs,
}
}

// Options return a list client.Option
func (s *NacosClientSuite) Options() []client.Option {
opts := make([]client.Option, 0, 8)
opts = append(opts, WithRetryPolicy(s.service, s.client, s.nacosClient, s.fns...)...)
return opts
}
87 changes: 87 additions & 0 deletions client/retry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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 client
whalecold marked this conversation as resolved.
Show resolved Hide resolved

import (
"github.com/kitex-contrib/config-nacos/nacos"
"github.com/nacos-group/nacos-sdk-go/vo"

"github.com/cloudwego/kitex/client"
"github.com/cloudwego/kitex/pkg/klog"
"github.com/cloudwego/kitex/pkg/retry"
)

const (
retryConfigName = "retry_config"
)

// WithRetryPolicy sets the retry policy from nacos configuration center.
func WithRetryPolicy(dest, src string, nacosClient nacos.Client,
cfs ...nacos.CustomFunction,
) []client.Option {
param := nacos.NaocsConfigParam(&nacos.ConfigParamConfig{
Category: retryConfigName,
ServerServiceName: dest,
ClientServiceName: src,
}, cfs...)

return []client.Option{
client.WithRetryContainer(initRetryContainer(param, dest, nacosClient)),
client.WithCloseCallbacks(func() error {
// cancel the configuration listener when client is closed.
return nacosClient.DeregisterConfig(param)
}),
}
}

// the key is method name, wildcard "*" can match anything.
type retryConfigs map[string]*retry.Policy
felix021 marked this conversation as resolved.
Show resolved Hide resolved

func initRetryContainer(param vo.ConfigParam, dest string,
nacosClient nacos.Client,
) *retry.Container {
retryContainer := retry.NewRetryContainer()

onChangeCallback := func(data string, parser nacos.ConfigParser) {
rcs := retryConfigs{}
err := parser.Decode(param.Type, data, rcs)
if err != nil {
klog.Warnf("[nacos] %s client nacos retry: unmarshal data %s failed: %s, skip...", dest, data, err)
return
}

for method, policy := range rcs {
if policy.BackupPolicy != nil && policy.FailurePolicy != nil {
klog.Warnf("[nacos] %s client policy for method %s BackupPolicy and FailurePolicy must not be set at same time",
dest, method)
continue
}
if policy.BackupPolicy == nil && policy.FailurePolicy == nil {
klog.Warnf("[nacos] %s client policy for method %s BackupPolicy and FailurePolicy must not be empty at same time",
dest, method)
continue
}
retryContainer.NotifyPolicyChange(method, *policy)
}
}

nacosClient.RegisterConfigCallback(dest,
retryConfigName,
param,
onChangeCallback,
)

return retryContainer
}
57 changes: 57 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module github.com/kitex-contrib/config-nacos

go 1.19

require (
github.com/cloudwego/kitex v0.6.1
github.com/nacos-group/nacos-sdk-go v1.1.4
github.com/stretchr/testify v1.8.2
sigs.k8s.io/yaml v1.3.0
)

require (
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
github.com/apache/thrift v0.13.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bytedance/gopkg v0.0.0-20230531144706-a12972768317 // indirect
github.com/bytedance/sonic v1.8.8 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/chenzhuoyu/iasm v0.0.0-20230222070914-0b1b64b0e762 // indirect
github.com/choleraehyq/pid v0.0.16 // indirect
github.com/cloudwego/configmanager v0.2.0 // indirect
github.com/cloudwego/fastpb v0.0.4 // indirect
github.com/cloudwego/frugal v0.1.6 // indirect
github.com/cloudwego/netpoll v0.4.0 // indirect
github.com/cloudwego/thriftgo v0.2.11 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/pprof v0.0.0-20220608213341-c488b8fa1db3 // indirect
github.com/jhump/protoreflect v1.8.2 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/oleiade/lane v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/tidwall/gjson v1.9.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
go.uber.org/atomic v1.6.0 // indirect
go.uber.org/multierr v1.5.0 // indirect
go.uber.org/zap v1.15.0 // indirect
golang.org/x/arch v0.2.0 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.42.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading