Repository: go-kratos/kratos
Pull request #1808 (2022-02-07 14:55:44)

fix: add yaml / yml parser
<!--
🎉 Thanks for sending a pull request to Kratos! Here are some tips for you:

1. If this is your first time contributing to Kratos, please read our contribution guide: https://go-kratos.dev/en/docs/community/contribution/
2. Ensure you have added or ran the appropriate tests and lint for your PR, please use `make lint` and `make test` before filing your PR, use `make clean` to tidy your go mod.
3. If the PR is unfinished, you may need mark it as a WIP(Work In Progress) PR or draft PR
4. Please use a conventional commits format title: `<type>[optional scope]: <description>`
    
    Some suggestion on <type>:

    fix: A bug fix
    feat: A new feature
    test: Adding missing tests or correcting existing tests
    refactor: A code change that neither fixes a bug nor adds a feature
    break: Changes has break change

    docs: Documentation only changes
    deps: Changes external dependencies
    style: Changes that do not affect the meaning of the code (white-space, formatting, etc)
    chore Daily work, examples, etc.
    ci: Changes to our CI configuration files and scripts
-->

#### Description (what this PR does / why we need it):
apollo yaml yml 配置读取使用了viper，而viper会将读到的配置的key全部变成小写。这样在读取配置的时候（比如包含大些字母KEY）会读取不到。而且config模块再去做scan struct的时候也会读取不到对应的配置。所以需要重新实现 yaml/yml的parser。


#### Which issue(s) this PR fixes (resolves / be part of):
<!--
* Automatically closes linked issue when PR is merged.
* If you PR is not fully resolved issue, please use `part of #<issue number>` instead.

Usage: `fixes/resolves #<issue number>`, or `fixes/resolves (paste link of issue)`.
-->
fixes #

#### Other special notes for reviewer:
<!--
* Somethings that need extra attention for reviewer
* Some additional notes, TODO list, etc.
-->


codecov-commenter: # [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) Report
> Merging [#1808](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (ff4ca36) into [main](https://codecov.io/gh/go-kratos/kratos/commit/86b8b6c366b9632d759e3a0b7db36c51c9043117?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (86b8b6c) will **decrease** coverage by `0.05%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/go-kratos/kratos/pull/1808/graphs/tree.svg?width=650&height=150&src=pr&token=XwnmBTz78x&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)

```diff
@@            Coverage Diff             @@
##             main    #1808      +/-   ##
==========================================
- Coverage   80.80%   80.74%   -0.06%     
==========================================
  Files          80       80              
  Lines        3558     3558              
==========================================
- Hits         2875     2873       -2     
- Misses        477      479       +2     
  Partials      206      206              
```


| [Impacted Files](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) | Coverage Δ | |
|---|---|---|
| [internal/context/context.go](https://codecov.io/gh/go-kratos/kratos/pull/1808/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-aW50ZXJuYWwvY29udGV4dC9jb250ZXh0Lmdv) | `97.01% <0.00%> (-2.99%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Last update [86b8b6c...ff4ca36](https://codecov.io/gh/go-kratos/kratos/pull/1808?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index d3b84788..5eac3b5d 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -32,6 +32,11 @@ jobs:
         ports:
           - "8848:8848"
           - "9848:9848"
+      polaris:
+        image: huyuanxin/polaris-server-with-config:latest
+        ports:
+          - 8090:8090
+          - 8091:8091
     steps:
       - uses: actions/checkout@v2
       - name: Set up Go
diff --git a/cmd/kratos/internal/proto/client/client.go b/cmd/kratos/internal/proto/client/client.go
index 5dc9b2f6..8bc00633 100644
--- a/cmd/kratos/internal/proto/client/client.go
+++ b/cmd/kratos/internal/proto/client/client.go
@@ -39,7 +39,7 @@ func run(cmd *cobra.Command, args []string) {
 		err   error
 		proto = strings.TrimSpace(args[0])
 	)
-	if err = look("protoc-gen-go", "protoc-gen-go-grpc", "protoc-gen-go-http", "protoc-gen-go-errors", "protoc-gen-validate", "protoc-gen-openapi"); err != nil {
+	if err = look("protoc-gen-go", "protoc-gen-go-grpc", "protoc-gen-go-http", "protoc-gen-go-errors", "protoc-gen-openapi"); err != nil {
 		// update the kratos plugins
 		cmd := exec.Command("kratos", "upgrade")
 		cmd.Stdout = os.Stdout
diff --git a/cmd/kratos/internal/upgrade/upgrade.go b/cmd/kratos/internal/upgrade/upgrade.go
index e93aae4a..a8825dcc 100644
--- a/cmd/kratos/internal/upgrade/upgrade.go
+++ b/cmd/kratos/internal/upgrade/upgrade.go
@@ -24,7 +24,6 @@ func Run(cmd *cobra.Command, args []string) {
 		"github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2@latest",
 		"google.golang.org/protobuf/cmd/protoc-gen-go@latest",
 		"google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest",
-		"github.com/envoyproxy/protoc-gen-validate@latest",
 		"github.com/google/gnostic/cmd/protoc-gen-openapi@latest",
 	)
 	if err != nil {
diff --git a/cmd/protoc-gen-go-http/http.go b/cmd/protoc-gen-go-http/http.go
index 3ecd4190..0d9458d8 100644
--- a/cmd/protoc-gen-go-http/http.go
+++ b/cmd/protoc-gen-go-http/http.go
@@ -110,6 +110,7 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 		body         string
 		responseBody string
 	)
+
 	switch pattern := rule.Pattern.(type) {
 	case *annotations.HttpRule_Get:
 		path = pattern.Get
@@ -137,8 +138,12 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 		if body != "" {
 			_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s body should not be declared.\n", method, path)
 		}
-		md.HasBody = false
-	} else if body == "*" {
+	} else {
+		if body == "" {
+			_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s does not declare a body.\n", method, path)
+		}
+	}
+	if body == "*" {
 		md.HasBody = true
 		md.Body = ""
 	} else if body != "" {
@@ -146,7 +151,6 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 		md.Body = "." + camelCaseVars(body)
 	} else {
 		md.HasBody = false
-		_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s does not declare a body.\n", method, path)
 	}
 	if responseBody == "*" {
 		md.ResponseBody = ""
@@ -199,6 +203,10 @@ func buildMethodDesc(g *protogen.GeneratedFile, m *protogen.Method, method, path
 }
 
 func buildPathVars(path string) (res map[string]*string) {
+	if strings.HasSuffix(path, "/") {
+		fmt.Fprintf(os.Stderr, "\u001B[31mERROR\u001B[m: Path %s should not end with \"/\" \n", path)
+		os.Exit(2)
+	}
 	res = make(map[string]*string)
 	pattern := regexp.MustCompile(`(?i){([a-z\.0-9_\s]*)=?([^{}]*)}`)
 	matches := pattern.FindAllStringSubmatch(path, -1)
diff --git a/contrib/config/apollo/go.mod b/contrib/config/apollo/go.mod
index e96d8f57..3631b634 100644
--- a/contrib/config/apollo/go.mod
+++ b/contrib/config/apollo/go.mod
@@ -12,6 +12,7 @@ require (
 	github.com/spf13/viper v1.10.1 // indirect
 	golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
 	gopkg.in/ini.v1 v1.66.3 // indirect
+	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/config/apollo/go.sum b/contrib/config/apollo/go.sum
index 185a878a..df612a3d 100644
--- a/contrib/config/apollo/go.sum
+++ b/contrib/config/apollo/go.sum
@@ -59,8 +59,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/apolloconfig/agollo/v4 v4.0.8 h1:SY23bGjLJX58OMVnussD9MKwg/XE9zZgzrTg3WrjFdU=
-github.com/apolloconfig/agollo/v4 v4.0.8/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs=
 github.com/apolloconfig/agollo/v4 v4.1.0 h1:aZmrnSr/l0/CD5+txdgF1bIiKP1I5m0EH0WkHqAVhHk=
 github.com/apolloconfig/agollo/v4 v4.1.0/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
diff --git a/contrib/config/apollo/json_parser.go b/contrib/config/apollo/json_parser.go
deleted file mode 100644
index 827c7b29..00000000
--- a/contrib/config/apollo/json_parser.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package apollo
-
-import (
-	"encoding/json"
-
-	"github.com/apolloconfig/agollo/v4/constant"
-	"github.com/apolloconfig/agollo/v4/extension"
-)
-
-type jsonExtParser struct{}
-
-func (j jsonExtParser) Parse(configContent interface{}) (map[string]interface{}, error) {
-	v, ok := configContent.(string)
-	if !ok {
-		return nil, nil
-	}
-	out := make(map[string]interface{}, 4)
-	err := json.Unmarshal([]byte(v), &out)
-	return out, err
-}
-
-func init() {
-	// add json format
-	extension.AddFormatParser(constant.JSON, &jsonExtParser{})
-}
diff --git a/contrib/config/apollo/parser.go b/contrib/config/apollo/parser.go
new file mode 100644
index 00000000..ab4cb434
--- /dev/null
+++ b/contrib/config/apollo/parser.go
@@ -0,0 +1,40 @@
+package apollo
+
+import (
+	"encoding/json"
+	"gopkg.in/yaml.v3"
+
+	"github.com/apolloconfig/agollo/v4/constant"
+	"github.com/apolloconfig/agollo/v4/extension"
+)
+
+type jsonExtParser struct{}
+
+func (parser jsonExtParser) Parse(configContent interface{}) (map[string]interface{}, error) {
+	v, ok := configContent.(string)
+	if !ok {
+		return nil, nil
+	}
+	out := make(map[string]interface{}, 4)
+	err := json.Unmarshal([]byte(v), &out)
+	return out, err
+}
+
+type yamlExtParser struct{}
+
+func (parser yamlExtParser) Parse(configContent interface{}) (out map[string]interface{}, err error) {
+	v, ok := configContent.(string)
+	if !ok {
+		return nil, nil
+	}
+	out = make(map[string]interface{}, 4)
+	err = yaml.Unmarshal([]byte(v), &out)
+	return
+}
+
+func init() {
+	// add json/yaml/yml format
+	extension.AddFormatParser(constant.JSON, &jsonExtParser{})
+	extension.AddFormatParser(constant.YAML, &yamlExtParser{})
+	extension.AddFormatParser(constant.YML, &yamlExtParser{})
+}
diff --git a/contrib/config/consul/config.go b/contrib/config/consul/config.go
index 8025ec96..afdf9132 100644
--- a/contrib/config/consul/config.go
+++ b/contrib/config/consul/config.go
@@ -18,7 +18,7 @@ type options struct {
 	path string
 }
 
-//  WithContext with registry context.
+// WithContext with registry context.
 func WithContext(ctx context.Context) Option {
 	return Option(func(o *options) {
 		o.ctx = ctx
@@ -71,6 +71,9 @@ func (s *source) Load() ([]*config.KeyValue, error) {
 	kvs := make([]*config.KeyValue, 0)
 	for _, item := range kv {
 		k := strings.TrimPrefix(item.Key, pathPrefix)
+		if k == "" {
+			continue
+		}
 		kvs = append(kvs, &config.KeyValue{
 			Key:    k,
 			Value:  item.Value,
diff --git a/contrib/registry/kubernetes/registry.go b/contrib/registry/kubernetes/registry.go
index 14b21f9a..e8aaa169 100644
--- a/contrib/registry/kubernetes/registry.go
+++ b/contrib/registry/kubernetes/registry.go
@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/go-kratos/kratos/v2/registry"
 	jsoniter "github.com/json-iterator/go"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -20,8 +21,6 @@ import (
 	"k8s.io/client-go/kubernetes"
 	listerv1 "k8s.io/client-go/listers/core/v1"
 	"k8s.io/client-go/tools/cache"
-
-	"github.com/go-kratos/kratos/v2/registry"
 )
 
 // Defines the key name of specific fields
@@ -64,7 +63,6 @@ import (
 //          ports:
 //            - containerPort: 80
 //
-//
 const (
 	// LabelsKeyServiceID is used to define the ID of the service
 	LabelsKeyServiceID = "kratos-service-id"
@@ -159,7 +157,7 @@ func (s *Registry) Deregister(ctx context.Context, service *registry.ServiceInst
 }
 
 // Service return the service instances in memory according to the service name.
-func (s *Registry) Service(name string) ([]*registry.ServiceInstance, error) {
+func (s *Registry) GetService(ctx context.Context, name string) ([]*registry.ServiceInstance, error) {
 	pods, err := s.podLister.List(labels.SelectorFromSet(map[string]string{
 		LabelsKeyServiceName: name,
 	}))
@@ -180,8 +178,8 @@ func (s *Registry) Service(name string) ([]*registry.ServiceInstance, error) {
 	return ret, nil
 }
 
-func (s *Registry) sendLatestInstances(name string, announcement chan []*registry.ServiceInstance) {
-	instances, err := s.Service(name)
+func (s *Registry) sendLatestInstances(ctx context.Context, name string, announcement chan []*registry.ServiceInstance) {
+	instances, err := s.GetService(ctx, name)
 	if err != nil {
 		panic(err)
 	}
@@ -189,7 +187,7 @@ func (s *Registry) sendLatestInstances(name string, announcement chan []*registr
 }
 
 // Watch creates a watcher according to the service name.
-func (s *Registry) Watch(name string) (registry.Watcher, error) {
+func (s *Registry) Watch(ctx context.Context, name string) (registry.Watcher, error) {
 	stopCh := make(chan struct{}, 1)
 	announcement := make(chan []*registry.ServiceInstance, 1)
 	s.podInformer.AddEventHandler(cache.FilteringResourceEventHandler{
@@ -207,13 +205,13 @@ func (s *Registry) Watch(name string) (registry.Watcher, error) {
 		},
 		Handler: cache.ResourceEventHandlerFuncs{
 			AddFunc: func(obj interface{}) {
-				s.sendLatestInstances(name, announcement)
+				s.sendLatestInstances(ctx, name, announcement)
 			},
 			UpdateFunc: func(oldObj, newObj interface{}) {
-				s.sendLatestInstances(name, announcement)
+				s.sendLatestInstances(ctx, name, announcement)
 			},
 			DeleteFunc: func(obj interface{}) {
-				s.sendLatestInstances(name, announcement)
+				s.sendLatestInstances(ctx, name, announcement)
 			},
 		},
 	})
diff --git a/contrib/registry/nacos/registry.go b/contrib/registry/nacos/registry.go
index baf9b473..088cb8c2 100644
--- a/contrib/registry/nacos/registry.go
+++ b/contrib/registry/nacos/registry.go
@@ -8,6 +8,7 @@ import (
 	"strconv"
 
 	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
+	"github.com/nacos-group/nacos-sdk-go/common/constant"
 	"github.com/nacos-group/nacos-sdk-go/vo"
 
 	"github.com/go-kratos/kratos/v2/registry"
@@ -65,7 +66,7 @@ func New(cli naming_client.INamingClient, opts ...Option) (r *Registry) {
 	op := options{
 		prefix:  "/microservices",
 		cluster: "DEFAULT",
-		group:   "DEFAULT_GROUP",
+		group:   constant.DEFAULT_GROUP,
 		weight:  100,
 		kind:    "grpc",
 	}
@@ -167,6 +168,7 @@ func (r *Registry) Watch(ctx context.Context, serviceName string) (registry.Watc
 func (r *Registry) GetService(_ context.Context, serviceName string) ([]*registry.ServiceInstance, error) {
 	res, err := r.cli.SelectInstances(vo.SelectInstancesParam{
 		ServiceName: serviceName,
+		GroupName:   r.opts.group,
 		HealthyOnly: true,
 	})
 	if err != nil {
diff --git a/contrib/registry/polaris/go.mod b/contrib/registry/polaris/go.mod
new file mode 100644
index 00000000..096caed0
--- /dev/null
+++ b/contrib/registry/polaris/go.mod
@@ -0,0 +1,32 @@
+module github.com/go-kratos/kratos/contrib/registry/polaris/v2
+
+go 1.17
+
+require (
+	github.com/go-kratos/kratos/v2 v2.1.5
+	github.com/polarismesh/polaris-go v1.0.1
+)
+
+require (
+	github.com/ghodss/yaml v1.0.0 // indirect
+	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/google/uuid v1.3.0 // indirect
+	github.com/hashicorp/errwrap v1.0.0 // indirect
+	github.com/hashicorp/go-multierror v1.1.1 // indirect
+	github.com/mitchellh/go-homedir v1.1.0 // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
+	github.com/spaolacci/murmur3 v1.1.0 // indirect
+	go.uber.org/atomic v1.7.0 // indirect
+	go.uber.org/multierr v1.6.0 // indirect
+	go.uber.org/zap v1.19.1 // indirect
+	golang.org/x/net v0.0.0-20210917221730-978cfadd31cf // indirect
+	golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 // indirect
+	golang.org/x/text v0.3.6 // indirect
+	google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect
+	google.golang.org/grpc v1.44.0 // indirect
+	google.golang.org/protobuf v1.27.1 // indirect
+	gopkg.in/yaml.v2 v2.3.0 // indirect
+)
+
+replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/registry/polaris/go.sum b/contrib/registry/polaris/go.sum
new file mode 100644
index 00000000..ebe4ce8f
--- /dev/null
+++ b/contrib/registry/polaris/go.sum
@@ -0,0 +1,239 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
+github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw=
+github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-kratos/aegis v0.1.1/go.mod h1:jYeSQ3Gesba478zEnujOiG5QdsyF3Xk/8owFUeKcHxw=
+github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/form/v4 v4.2.0/go.mod h1:q1a2BY+AQUUzhl6xA/6hBetay6dEIhMHjgvJiGo6K7U=
+github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
+github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg=
+github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2/go.mod h1:pDgmNM6seYpwvPos3q+zxlXMsbve6mOIPucUnUOrI7Y=
+github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks=
+github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A=
+github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw=
+github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
+github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/polarismesh/polaris-go v1.0.1 h1:Zqr8ZtxsJQsxt0MGyC/fFsF861ogoJCz16yWFJ/t54Q=
+github.com/polarismesh/polaris-go v1.0.1/go.mod h1:3NOqn3QquPdEdY6YhPrsWGvBVCpKhPBGt0Hspq3yEqY=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
+github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
+go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
+go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
+go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
+go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
+golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 h1:ikCpsnYR+Ew0vu99XlDp55lGgDJdIMx3f4a18jfse/s=
+golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
+google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
+google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
+gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/contrib/registry/polaris/registry.go b/contrib/registry/polaris/registry.go
new file mode 100644
index 00000000..f1bb7a79
--- /dev/null
+++ b/contrib/registry/polaris/registry.go
@@ -0,0 +1,271 @@
+package polaris
+
+import (
+	"context"
+	"net"
+	"net/url"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/go-kratos/kratos/v2/log"
+
+	"github.com/go-kratos/kratos/v2/registry"
+	"github.com/polarismesh/polaris-go/api"
+	"github.com/polarismesh/polaris-go/pkg/model"
+)
+
+var _ registry.Registrar = (*Registry)(nil)
+
+// _instanceIDSeparator . Instance id Separator.
+const _instanceIDSeparator = "-"
+
+type options struct {
+
+	// required, namespace in polaris
+	Namespace string
+
+	// required, service access token
+	ServiceToken string
+
+	// optional, protocol in polaris. Default value is nil, it means use protocol config in service
+	Protocol *string
+
+	// service weight in polaris. Default value is 100, 0 <= weight <= 10000
+	Weight int
+
+	// service priority. Default value is 0. The smaller the value, the lower the priority
+	Priority int
+
+	// To show service is healthy or not. Default value is True .
+	Healthy bool
+
+	// To show service is isolate or not. Default value is False .
+	Isolate bool
+
+	// TTL timeout. if node needs to use heartbeat to report,required. If not set,server will throw ErrorCode-400141
+	TTL int
+
+	// optional, Timeout for single query. Default value is global config
+	// Total is (1+RetryCount) * Timeout
+	Timeout time.Duration
+
+	// optional, retry count. Default value is global config
+	RetryCount int
+}
+
+// Option is polaris option.
+type Option func(o *options)
+
+// Registry is polaris registry.
+type Registry struct {
+	opt      options
+	provider api.ProviderAPI
+}
+
+// WithNamespace with Namespace option.
+func WithNamespace(namespace string) Option {
+	return func(o *options) { o.Namespace = namespace }
+}
+
+// WithServiceToken with ServiceToken option.
+func WithServiceToken(serviceToken string) Option {
+	return func(o *options) { o.ServiceToken = serviceToken }
+}
+
+// WithProtocol with Protocol option.
+func WithProtocol(protocol string) Option {
+	return func(o *options) { o.Protocol = &protocol }
+}
+
+// WithWeight with Weight option.
+func WithWeight(weight int) Option {
+	return func(o *options) { o.Weight = weight }
+}
+
+// WithHealthy with Healthy option.
+func WithHealthy(healthy bool) Option {
+	return func(o *options) { o.Healthy = healthy }
+}
+
+// WithIsolate with Isolate option.
+func WithIsolate(isolate bool) Option {
+	return func(o *options) { o.Isolate = isolate }
+}
+
+// WithTTL with TTL option.
+func WithTTL(TTL int) Option {
+	return func(o *options) { o.TTL = TTL }
+}
+
+// WithTimeout with Timeout option.
+func WithTimeout(timeout time.Duration) Option {
+	return func(o *options) { o.Timeout = timeout }
+}
+
+// WithRetryCount with RetryCount option.
+func WithRetryCount(retryCount int) Option {
+	return func(o *options) { o.RetryCount = retryCount }
+}
+
+func NewRegistry(provider api.ProviderAPI, opts ...Option) (r *Registry) {
+	op := options{
+		Namespace:    "default",
+		ServiceToken: "",
+		Protocol:     nil,
+		Weight:       0,
+		Priority:     0,
+		Healthy:      true,
+		Isolate:      false,
+		TTL:          0,
+		Timeout:      0,
+		RetryCount:   0,
+	}
+	for _, option := range opts {
+		option(&op)
+	}
+	return &Registry{
+		opt:      op,
+		provider: provider,
+	}
+}
+
+// Register the registration.
+func (r *Registry) Register(_ context.Context, serviceInstance *registry.ServiceInstance) error {
+	ids := make([]string, 0, len(serviceInstance.Endpoints))
+	for _, endpoint := range serviceInstance.Endpoints {
+		// get url
+		u, err := url.Parse(endpoint)
+		if err != nil {
+			return err
+		}
+
+		// get host and port
+		host, port, err := net.SplitHostPort(u.Host)
+		if err != nil {
+			return err
+		}
+
+		// port to int
+		portNum, err := strconv.Atoi(port)
+		if err != nil {
+			return err
+		}
+
+		// medata
+		var rmd map[string]string
+		if serviceInstance.Metadata == nil {
+			rmd = map[string]string{
+				"kind":    u.Scheme,
+				"version": serviceInstance.Version,
+			}
+		} else {
+			rmd = make(map[string]string, len(serviceInstance.Metadata)+2)
+			for k, v := range serviceInstance.Metadata {
+				rmd[k] = v
+			}
+			rmd["kind"] = u.Scheme
+			rmd["version"] = serviceInstance.Version
+		}
+		// Register
+		service, err := r.provider.Register(
+			&api.InstanceRegisterRequest{
+				InstanceRegisterRequest: model.InstanceRegisterRequest{
+					Service:      serviceInstance.Name + u.Scheme,
+					ServiceToken: r.opt.ServiceToken,
+					Namespace:    r.opt.Namespace,
+					Host:         host,
+					Port:         portNum,
+					Protocol:     r.opt.Protocol,
+					Weight:       &r.opt.Weight,
+					Priority:     &r.opt.Priority,
+					Version:      &serviceInstance.Version,
+					Metadata:     rmd,
+					Healthy:      &r.opt.Healthy,
+					Isolate:      &r.opt.Isolate,
+					TTL:          &r.opt.TTL,
+					Timeout:      &r.opt.Timeout,
+					RetryCount:   &r.opt.RetryCount,
+				},
+			})
+		if err != nil {
+			return err
+		}
+		instanceID := service.InstanceID
+
+		// start heartbeat report
+		go func() {
+			ticker := time.NewTicker(time.Second * time.Duration(r.opt.TTL))
+			defer ticker.Stop()
+
+			for {
+				<-ticker.C
+
+				err = r.provider.Heartbeat(&api.InstanceHeartbeatRequest{
+					InstanceHeartbeatRequest: model.InstanceHeartbeatRequest{
+						Service:      serviceInstance.Name + u.Scheme,
+						Namespace:    r.opt.Namespace,
+						Host:         host,
+						Port:         portNum,
+						ServiceToken: r.opt.ServiceToken,
+						InstanceID:   instanceID,
+						Timeout:      &r.opt.Timeout,
+						RetryCount:   &r.opt.RetryCount,
+					},
+				})
+				if err != nil {
+					log.Error(err.Error())
+					continue
+				}
+			}
+		}()
+
+		ids = append(ids, instanceID)
+	}
+	// need to set InstanceID for Deregister
+	serviceInstance.ID = strings.Join(ids, _instanceIDSeparator)
+	return nil
+}
+
+// Deregister the registration.
+func (r *Registry) Deregister(ctx context.Context, serviceInstance *registry.ServiceInstance) error {
+	split := strings.Split(serviceInstance.ID, _instanceIDSeparator)
+	for i, endpoint := range serviceInstance.Endpoints {
+		// get url
+		u, err := url.Parse(endpoint)
+		if err != nil {
+			return err
+		}
+
+		// get host and port
+		host, port, err := net.SplitHostPort(u.Host)
+		if err != nil {
+			return err
+		}
+
+		// port to int
+		portNum, err := strconv.Atoi(port)
+		if err != nil {
+			return err
+		}
+		// Deregister
+		err = r.provider.Deregister(
+			&api.InstanceDeRegisterRequest{
+				InstanceDeRegisterRequest: model.InstanceDeRegisterRequest{
+					Service:      serviceInstance.Name + u.Scheme,
+					ServiceToken: r.opt.ServiceToken,
+					Namespace:    r.opt.Namespace,
+					InstanceID:   split[i],
+					Host:         host,
+					Port:         portNum,
+					Timeout:      &r.opt.Timeout,
+					RetryCount:   &r.opt.RetryCount,
+				},
+			},
+		)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/encoding/README.md b/encoding/README.md
new file mode 100644
index 00000000..c147b3be
--- /dev/null
+++ b/encoding/README.md
@@ -0,0 +1,7 @@
+# encoding
+
+## msgpack
+
+```shell
+go get -u github.com/go-kratos/kratos/contrib/encoding/msgpack/v2
+```
diff --git a/examples/http/redirect/main.go b/examples/http/redirect/main.go
new file mode 100644
index 00000000..42b37b4c
--- /dev/null
+++ b/examples/http/redirect/main.go
@@ -0,0 +1,60 @@
+package main
+
+import (
+	"context"
+	"fmt"
+	"log"
+	"net/http"
+
+	"github.com/go-kratos/kratos/examples/helloworld/helloworld"
+	"github.com/go-kratos/kratos/v2"
+	"github.com/go-kratos/kratos/v2/errors"
+	khttp "github.com/go-kratos/kratos/v2/transport/http"
+)
+
+type server struct {
+	helloworld.UnimplementedGreeterServer
+}
+
+// SayHello implements helloworld.GreeterServer
+func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
+	if in.Name == "error" {
+		return nil, errors.BadRequest("custom_error", fmt.Sprintf("invalid argument %s", in.Name))
+	}
+	if in.Name == "panic" {
+		panic("server panic")
+	}
+	return &helloworld.HelloReply{Message: fmt.Sprintf("Hello %+v", in.Name)}, nil
+}
+
+func redirectFilter(next http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.Path == "/helloworld/kratos" {
+			http.Redirect(w, r, "https://go-kratos.dev/", http.StatusMovedPermanently)
+			return
+		}
+		next.ServeHTTP(w, r)
+	})
+}
+
+func main() {
+	httpSrv := khttp.NewServer(
+		khttp.Address(":8000"),
+		khttp.Filter(redirectFilter),
+	)
+	s := &server{}
+	helloworld.RegisterGreeterHTTPServer(httpSrv, s)
+
+	app := kratos.New(
+		kratos.Name("cors"),
+		kratos.Server(
+			httpSrv,
+		),
+	)
+	if err := app.Run(); err != nil {
+		log.Fatal(err)
+	}
+}
+
+// get http://127.0.0.1:8000/helloworld/kratos
+// get http://127.0.0.1:8000/helloworld/go-kratos.dev
diff --git a/container/group/example_test.go b/internal/group/example_test.go
similarity index 100%
rename from container/group/example_test.go
rename to internal/group/example_test.go
diff --git a/container/group/group.go b/internal/group/group.go
similarity index 100%
rename from container/group/group.go
rename to internal/group/group.go
diff --git a/container/group/group_test.go b/internal/group/group_test.go
similarity index 100%
rename from container/group/group_test.go
rename to internal/group/group_test.go
diff --git a/log/README.md b/log/README.md
index d640e733..0fb786f1 100644
--- a/log/README.md
+++ b/log/README.md
@@ -47,4 +47,10 @@ go get -u github.com/go-kratos/kratos/contrib/log/zap/v2
 
 ```shell
 go get -u github.com/go-kratos/kratos/contrib/log/fluent/v2
+```
+
+### aliyun
+
+```shell
+go get -u github.com/go-kratos/kratos/contrib/log/aliyun/v2
 ```
\ No newline at end of file
diff --git a/middleware/auth/jwt/jwt.go b/middleware/auth/jwt/jwt.go
index c7a7f78f..60dad2db 100644
--- a/middleware/auth/jwt/jwt.go
+++ b/middleware/auth/jwt/jwt.go
@@ -48,7 +48,7 @@ type Option func(*options)
 // Parser is a jwt parser
 type options struct {
 	signingMethod jwt.SigningMethod
-	claims        jwt.Claims
+	claims        func() jwt.Claims
 	tokenHeader   map[string]interface{}
 }
 
@@ -60,9 +60,11 @@ func WithSigningMethod(method jwt.SigningMethod) Option {
 }
 
 // WithClaims with customer claim
-func WithClaims(claims jwt.Claims) Option {
+// If you use it in Server, f needs to return a new jwt.Claims object each time to avoid concurrent write problems
+// If you use it in Client, f only needs to return a single object to provide performance
+func WithClaims(f func() jwt.Claims) Option {
 	return func(o *options) {
-		o.claims = claims
+		o.claims = f
 	}
 }
 
@@ -77,7 +79,6 @@ func WithTokenHeader(header map[string]interface{}) Option {
 func Server(keyFunc jwt.Keyfunc, opts ...Option) middleware.Middleware {
 	o := &options{
 		signingMethod: jwt.SigningMethodHS256,
-		claims:        jwt.RegisteredClaims{},
 	}
 	for _, opt := range opts {
 		opt(o)
@@ -93,7 +94,15 @@ func Server(keyFunc jwt.Keyfunc, opts ...Option) middleware.Middleware {
 					return nil, ErrMissingJwtToken
 				}
 				jwtToken := auths[1]
-				tokenInfo, err := jwt.Parse(jwtToken, keyFunc)
+				var (
+					tokenInfo *jwt.Token
+					err       error
+				)
+				if o.claims != nil {
+					tokenInfo, err = jwt.ParseWithClaims(jwtToken, o.claims(), keyFunc)
+				} else {
+					tokenInfo, err = jwt.Parse(jwtToken, keyFunc)
+				}
 				if err != nil {
 					if ve, ok := err.(*jwt.ValidationError); ok {
 						if ve.Errors&jwt.ValidationErrorMalformed != 0 {
@@ -120,9 +129,10 @@ func Server(keyFunc jwt.Keyfunc, opts ...Option) middleware.Middleware {
 
 // Client is a client jwt middleware.
 func Client(keyProvider jwt.Keyfunc, opts ...Option) middleware.Middleware {
+	claims := jwt.RegisteredClaims{}
 	o := &options{
 		signingMethod: jwt.SigningMethodHS256,
-		claims:        jwt.RegisteredClaims{},
+		claims:        func() jwt.Claims { return claims },
 	}
 	for _, opt := range opts {
 		opt(o)
@@ -132,7 +142,7 @@ func Client(keyProvider jwt.Keyfunc, opts ...Option) middleware.Middleware {
 			if keyProvider == nil {
 				return nil, ErrNeedTokenProvider
 			}
-			token := jwt.NewWithClaims(o.signingMethod, o.claims)
+			token := jwt.NewWithClaims(o.signingMethod, o.claims())
 			if o.tokenHeader != nil {
 				for k, v := range o.tokenHeader {
 					token.Header[k] = v
diff --git a/middleware/circuitbreaker/circuitbreaker.go b/middleware/circuitbreaker/circuitbreaker.go
index f6eb5f41..1b4fa08f 100644
--- a/middleware/circuitbreaker/circuitbreaker.go
+++ b/middleware/circuitbreaker/circuitbreaker.go
@@ -5,8 +5,8 @@ import (
 
 	"github.com/go-kratos/aegis/circuitbreaker"
 	"github.com/go-kratos/aegis/circuitbreaker/sre"
-	"github.com/go-kratos/kratos/v2/container/group"
 	"github.com/go-kratos/kratos/v2/errors"
+	"github.com/go-kratos/kratos/v2/internal/group"
 	"github.com/go-kratos/kratos/v2/middleware"
 	"github.com/go-kratos/kratos/v2/transport"
 )
diff --git a/registry/README.md b/registry/README.md
index f5fcb08c..ebbc6a57 100644
--- a/registry/README.md
+++ b/registry/README.md
@@ -1,26 +1,37 @@
 # Registry
 
 ## Consul
+
 ```shell
 go get -u github.com/go-kratos/kratos/contrib/registry/consul/v2
 ```
 
 ## Etcd
+
 ```shell
 go get -u github.com/go-kratos/kratos/contrib/registry/etcd/v2
 ```
 
 ## zookeeper
+
 ```shell
 go get -u github.com/go-kratos/kratos/contrib/registry/zookeeper/v2
 ```
 
 ## Nacos
+
 ```shell
 go get -u github.com/go-kratos/kratos/contrib/registry/nacos/v2
 ```
 
 ## kubernetes
+
 ```shell
 go get -u github.com/go-kratos/kratos/contrib/registry/kubernetes/v2
+```
+
+## polaris
+
+```shell
+go get -u github.com/go-kratos/kratos/contrib/registry/polaris/v2
 ```
\ No newline at end of file
diff --git a/third_party/protoc-gen-openapiv2/options/annotations.proto b/third_party/protoc-gen-openapiv2/options/annotations.proto
deleted file mode 100644
index 1c189e20..00000000
--- a/third_party/protoc-gen-openapiv2/options/annotations.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-syntax = "proto3";
-
-package grpc.gateway.protoc_gen_openapiv2.options;
-
-option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options";
-
-import "google/protobuf/descriptor.proto";
-import "protoc-gen-openapiv2/options/openapiv2.proto";
-
-extend google.protobuf.FileOptions {
-  // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
-  //
-  // All IDs are the same, as assigned. It is okay that they are the same, as they extend
-  // different descriptor messages.
-  Swagger openapiv2_swagger = 1042;
-}
-extend google.protobuf.MethodOptions {
-  // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
-  //
-  // All IDs are the same, as assigned. It is okay that they are the same, as they extend
-  // different descriptor messages.
-  Operation openapiv2_operation = 1042;
-}
-extend google.protobuf.MessageOptions {
-  // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
-  //
-  // All IDs are the same, as assigned. It is okay that they are the same, as they extend
-  // different descriptor messages.
-  Schema openapiv2_schema = 1042;
-}
-extend google.protobuf.ServiceOptions {
-  // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
-  //
-  // All IDs are the same, as assigned. It is okay that they are the same, as they extend
-  // different descriptor messages.
-  Tag openapiv2_tag = 1042;
-}
-extend google.protobuf.FieldOptions {
-  // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
-  //
-  // All IDs are the same, as assigned. It is okay that they are the same, as they extend
-  // different descriptor messages.
-  JSONSchema openapiv2_field = 1042;
-}
diff --git a/third_party/protoc-gen-openapiv2/options/openapiv2.proto b/third_party/protoc-gen-openapiv2/options/openapiv2.proto
deleted file mode 100644
index 85ab6a53..00000000
--- a/third_party/protoc-gen-openapiv2/options/openapiv2.proto
+++ /dev/null
@@ -1,645 +0,0 @@
-syntax = "proto3";
-
-package grpc.gateway.protoc_gen_openapiv2.options;
-
-option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options";
-
-import "google/protobuf/struct.proto";
-
-// Scheme describes the schemes supported by the OpenAPI Swagger
-// and Operation objects.
-enum Scheme {
-  UNKNOWN = 0;
-  HTTP = 1;
-  HTTPS = 2;
-  WS = 3;
-  WSS = 4;
-}
-
-// `Swagger` is a representation of OpenAPI v2 specification's Swagger object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject
-//
-// Example:
-//
-//  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
-//    info: {
-//      title: "Echo API";
-//      version: "1.0";
-//      description: ";
-//      contact: {
-//        name: "gRPC-Gateway project";
-//        url: "https://github.com/grpc-ecosystem/grpc-gateway";
-//        email: "none@example.com";
-//      };
-//      license: {
-//        name: "BSD 3-Clause License";
-//        url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt";
-//      };
-//    };
-//    schemes: HTTPS;
-//    consumes: "application/json";
-//    produces: "application/json";
-//  };
-//
-message Swagger {
-  // Specifies the OpenAPI Specification version being used. It can be
-  // used by the OpenAPI UI and other clients to interpret the API listing. The 
-  // value MUST be "2.0".
-  string swagger = 1;
-  // Provides metadata about the API. The metadata can be used by the 
-  // clients if needed.
-  Info info = 2;
-  // The host (name or ip) serving the API. This MUST be the host only and does 
-  // not include the scheme nor sub-paths. It MAY include a port. If the host is
-  // not included, the host serving the documentation is to be used (including
-  // the port). The host does not support path templating.
-  string host = 3;
-  // The base path on which the API is served, which is relative to the host. If
-  // it is not included, the API is served directly under the host. The value 
-  // MUST start with a leading slash (/). The basePath does not support path
-  // templating.
-  // Note that using `base_path` does not change the endpoint paths that are 
-  // generated in the resulting OpenAPI file. If you wish to use `base_path`
-  // with relatively generated OpenAPI paths, the `base_path` prefix must be 
-  // manually removed from your `google.api.http` paths and your code changed to 
-  // serve the API from the `base_path`.
-  string base_path = 4;
-  // The transfer protocol of the API. Values MUST be from the list: "http",
-  // "https", "ws", "wss". If the schemes is not included, the default scheme to
-  // be used is the one used to access the OpenAPI definition itself.
-  repeated Scheme schemes = 5;
-  // A list of MIME types the APIs can consume. This is global to all APIs but 
-  // can be overridden on specific API calls. Value MUST be as described under
-  // Mime Types.
-  repeated string consumes = 6;
-  // A list of MIME types the APIs can produce. This is global to all APIs but
-  // can be overridden on specific API calls. Value MUST be as described under
-  // Mime Types.
-  repeated string produces = 7;
-  // field 8 is reserved for 'paths'.
-  reserved 8;
-  // field 9 is reserved for 'definitions', which at this time are already
-  // exposed as and customizable as proto messages.
-  reserved 9;
-  // An object to hold responses that can be used across operations. This
-  // property does not define global responses for all operations.
-  map<string, Response> responses = 10;
-  // Security scheme definitions that can be used across the specification.
-  SecurityDefinitions security_definitions = 11;
-  // A declaration of which security schemes are applied for the API as a whole.
-  // The list of values describes alternative security schemes that can be used 
-  // (that is, there is a logical OR between the security requirements). 
-  // Individual operations can override this definition.
-  repeated SecurityRequirement security = 12;
-  // field 13 is reserved for 'tags', which are supposed to be exposed as and
-  // customizable as proto services. TODO(ivucica): add processing of proto
-  // service objects into OpenAPI v2 Tag objects.
-  reserved 13;
-  // Additional external documentation.
-  ExternalDocumentation external_docs = 14;
-  map<string, google.protobuf.Value> extensions = 15;
-}
-
-// `Operation` is a representation of OpenAPI v2 specification's Operation object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject
-//
-// Example:
-//
-//  service EchoService {
-//    rpc Echo(SimpleMessage) returns (SimpleMessage) {
-//      option (google.api.http) = {
-//        get: "/v1/example/echo/{id}"
-//      };
-//
-//      option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
-//        summary: "Get a message.";
-//        operation_id: "getMessage";
-//        tags: "echo";
-//        responses: {
-//          key: "200"
-//            value: {
-//            description: "OK";
-//          }
-//        }
-//      };
-//    }
-//  }
-message Operation {
-  // A list of tags for API documentation control. Tags can be used for logical
-  // grouping of operations by resources or any other qualifier.
-  repeated string tags = 1;
-  // A short summary of what the operation does. For maximum readability in the
-  // swagger-ui, this field SHOULD be less than 120 characters.
-  string summary = 2;
-  // A verbose explanation of the operation behavior. GFM syntax can be used for
-  // rich text representation.
-  string description = 3;
-  // Additional external documentation for this operation.
-  ExternalDocumentation external_docs = 4;
-  // Unique string used to identify the operation. The id MUST be unique among
-  // all operations described in the API. Tools and libraries MAY use the
-  // operationId to uniquely identify an operation, therefore, it is recommended
-  // to follow common programming naming conventions.
-  string operation_id = 5;
-  // A list of MIME types the operation can consume. This overrides the consumes
-  // definition at the OpenAPI Object. An empty value MAY be used to clear the
-  // global definition. Value MUST be as described under Mime Types.
-  repeated string consumes = 6;
-  // A list of MIME types the operation can produce. This overrides the produces
-  // definition at the OpenAPI Object. An empty value MAY be used to clear the
-  // global definition. Value MUST be as described under Mime Types.
-  repeated string produces = 7;
-  // field 8 is reserved for 'parameters'.
-  reserved 8;
-  // The list of possible responses as they are returned from executing this
-  // operation.
-  map<string, Response> responses = 9;
-  // The transfer protocol for the operation. Values MUST be from the list:
-  // "http", "https", "ws", "wss". The value overrides the OpenAPI Object
-  // schemes definition.
-  repeated Scheme schemes = 10;
-  // Declares this operation to be deprecated. Usage of the declared operation
-  // should be refrained. Default value is false.
-  bool deprecated = 11;
-  // A declaration of which security schemes are applied for this operation. The
-  // list of values describes alternative security schemes that can be used
-  // (that is, there is a logical OR between the security requirements). This
-  // definition overrides any declared top-level security. To remove a top-level
-  // security declaration, an empty array can be used.
-  repeated SecurityRequirement security = 12;
-  map<string, google.protobuf.Value> extensions = 13;
-}
-
-// `Header` is a representation of OpenAPI v2 specification's Header object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject
-//
-message Header {
-  // `Description` is a short description of the header.
-  string description = 1;
-  // The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported.
-  string type = 2;
-  // `Format` The extending format for the previously mentioned type.
-  string format = 3;
-  // field 4 is reserved for 'items', but in OpenAPI-specific way.
-  reserved 4;
-  // field 5 is reserved `Collection Format` Determines the format of the array if type array is used.
-  reserved 5;
-  // `Default` Declares the value of the header that the server will use if none is provided.
-  // See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2.
-  // Unlike JSON Schema this value MUST conform to the defined type for the header.
-  string default = 6;
-  // field 7 is reserved for 'maximum'.
-  reserved 7;
-  // field 8 is reserved for 'exclusiveMaximum'.
-  reserved 8;
-  // field 9 is reserved for 'minimum'.
-  reserved 9;
-  // field 10 is reserved for 'exclusiveMinimum'.
-  reserved 10;
-  // field 11 is reserved for 'maxLength'.
-  reserved 11;
-  // field 12 is reserved for 'minLength'.
-  reserved 12;
-  // 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3.
-  string pattern = 13;
-  // field 14 is reserved for 'maxItems'.
-  reserved 14;
-  // field 15 is reserved for 'minItems'.
-  reserved 15;
-  // field 16 is reserved for 'uniqueItems'.
-  reserved 16;
-  // field 17 is reserved for 'enum'.
-  reserved 17;
-  // field 18 is reserved for 'multipleOf'.
-  reserved 18;
-}
-
-// `Response` is a representation of OpenAPI v2 specification's Response object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject
-//
-message Response {
-  // `Description` is a short description of the response.
-  // GFM syntax can be used for rich text representation.
-  string description = 1;
-  // `Schema` optionally defines the structure of the response.
-  // If `Schema` is not provided, it means there is no content to the response.
-  Schema schema = 2;
-  // `Headers` A list of headers that are sent with the response.
-  // `Header` name is expected to be a string in the canonical format of the MIME header key
-  // See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey
-  map<string, Header> headers = 3;
-  // `Examples` gives per-mimetype response examples.
-  // See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object
-  map<string, string> examples = 4;
-  map<string, google.protobuf.Value> extensions = 5;
-}
-
-// `Info` is a representation of OpenAPI v2 specification's Info object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject
-//
-// Example:
-//
-//  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
-//    info: {
-//      title: "Echo API";
-//      version: "1.0";
-//      description: ";
-//      contact: {
-//        name: "gRPC-Gateway project";
-//        url: "https://github.com/grpc-ecosystem/grpc-gateway";
-//        email: "none@example.com";
-//      };
-//      license: {
-//        name: "BSD 3-Clause License";
-//        url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt";
-//      };
-//    };
-//    ...
-//  };
-//
-message Info {
-  // The title of the application.
-  string title = 1;
-  // A short description of the application. GFM syntax can be used for rich
-  // text representation.
-  string description = 2;
-  // The Terms of Service for the API.
-  string terms_of_service = 3;
-  // The contact information for the exposed API.
-  Contact contact = 4;
-  // The license information for the exposed API.
-  License license = 5;
-  // Provides the version of the application API (not to be confused
-  // with the specification version).
-  string version = 6;
-  map<string, google.protobuf.Value> extensions = 7;
-}
-
-// `Contact` is a representation of OpenAPI v2 specification's Contact object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject
-//
-// Example:
-//
-//  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
-//    info: {
-//      ...
-//      contact: {
-//        name: "gRPC-Gateway project";
-//        url: "https://github.com/grpc-ecosystem/grpc-gateway";
-//        email: "none@example.com";
-//      };
-//      ...
-//    };
-//    ...
-//  };
-//
-message Contact {
-  // The identifying name of the contact person/organization.
-  string name = 1;
-  // The URL pointing to the contact information. MUST be in the format of a
-  // URL.
-  string url = 2;
-  // The email address of the contact person/organization. MUST be in the format
-  // of an email address.
-  string email = 3;
-}
-
-// `License` is a representation of OpenAPI v2 specification's License object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject
-//
-// Example:
-//
-//  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
-//    info: {
-//      ...
-//      license: {
-//        name: "BSD 3-Clause License";
-//        url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt";
-//      };
-//      ...
-//    };
-//    ...
-//  };
-//
-message License {
-  // The license name used for the API.
-  string name = 1;
-  // A URL to the license used for the API. MUST be in the format of a URL.
-  string url = 2;
-}
-
-// `ExternalDocumentation` is a representation of OpenAPI v2 specification's
-// ExternalDocumentation object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject
-//
-// Example:
-//
-//  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
-//    ...
-//    external_docs: {
-//      description: "More about gRPC-Gateway";
-//      url: "https://github.com/grpc-ecosystem/grpc-gateway";
-//    }
-//    ...
-//  };
-//
-message ExternalDocumentation {
-  // A short description of the target documentation. GFM syntax can be used for
-  // rich text representation.
-  string description = 1;
-  // The URL for the target documentation. Value MUST be in the format
-  // of a URL.
-  string url = 2;
-}
-
-// `Schema` is a representation of OpenAPI v2 specification's Schema object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
-//
-message Schema {
-  JSONSchema json_schema = 1;
-  // Adds support for polymorphism. The discriminator is the schema property
-  // name that is used to differentiate between other schema that inherit this
-  // schema. The property name used MUST be defined at this schema and it MUST
-  // be in the required property list. When used, the value MUST be the name of
-  // this schema or any schema that inherits it.
-  string discriminator = 2;
-  // Relevant only for Schema "properties" definitions. Declares the property as
-  // "read only". This means that it MAY be sent as part of a response but MUST
-  // NOT be sent as part of the request. Properties marked as readOnly being
-  // true SHOULD NOT be in the required list of the defined schema. Default
-  // value is false.
-  bool read_only = 3;
-  // field 4 is reserved for 'xml'.
-  reserved 4;
-  // Additional external documentation for this schema.
-  ExternalDocumentation external_docs = 5;
-  // A free-form property to include an example of an instance for this schema in JSON.
-  // This is copied verbatim to the output.
-  string example = 6;
-}
-
-// `JSONSchema` represents properties from JSON Schema taken, and as used, in
-// the OpenAPI v2 spec.
-//
-// This includes changes made by OpenAPI v2.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
-//
-// See also: https://cswr.github.io/JsonSchema/spec/basic_types/,
-// https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json
-//
-// Example:
-//
-//  message SimpleMessage {
-//    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
-//      json_schema: {
-//        title: "SimpleMessage"
-//        description: "A simple message."
-//        required: ["id"]
-//      }
-//    };
-//
-//    // Id represents the message identifier.
-//    string id = 1; [
-//        (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
-//          {description: "The unique identifier of the simple message."
-//        }];
-//  }
-//
-message JSONSchema {
-  // field 1 is reserved for '$id', omitted from OpenAPI v2.
-  reserved 1;
-  // field 2 is reserved for '$schema', omitted from OpenAPI v2.
-  reserved 2;
-  // Ref is used to define an external reference to include in the message.
-  // This could be a fully qualified proto message reference, and that type must
-  // be imported into the protofile. If no message is identified, the Ref will
-  // be used verbatim in the output.
-  // For example:
-  //  `ref: ".google.protobuf.Timestamp"`.
-  string ref = 3;
-  // field 4 is reserved for '$comment', omitted from OpenAPI v2.
-  reserved 4;
-  // The title of the schema.
-  string title = 5;
-  // A short description of the schema.
-  string description = 6;
-  string default = 7;
-  bool read_only = 8;
-  // A free-form property to include a JSON example of this field. This is copied
-  // verbatim to the output swagger.json. Quotes must be escaped.
-  // This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject  https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
-  string example = 9;
-  double multiple_of = 10;
-  // Maximum represents an inclusive upper limit for a numeric instance. The 
-  // value of MUST be a number, 
-  double maximum = 11;
-  bool exclusive_maximum = 12;
-  // minimum represents an inclusive lower limit for a numeric instance. The 
-  // value of MUST be a number, 
-  double minimum = 13;
-  bool exclusive_minimum = 14;
-  uint64 max_length = 15;
-  uint64 min_length = 16;
-  string pattern = 17;
-  // field 18 is reserved for 'additionalItems', omitted from OpenAPI v2.
-  reserved 18;
-  // field 19 is reserved for 'items', but in OpenAPI-specific way.
-  // TODO(ivucica): add 'items'?
-  reserved 19;
-  uint64 max_items = 20;
-  uint64 min_items = 21;
-  bool unique_items = 22;
-  // field 23 is reserved for 'contains', omitted from OpenAPI v2.
-  reserved 23;
-  uint64 max_properties = 24;
-  uint64 min_properties = 25;
-  repeated string required = 26;
-  // field 27 is reserved for 'additionalProperties', but in OpenAPI-specific
-  // way. TODO(ivucica): add 'additionalProperties'?
-  reserved 27;
-  // field 28 is reserved for 'definitions', omitted from OpenAPI v2.
-  reserved 28;
-  // field 29 is reserved for 'properties', but in OpenAPI-specific way.
-  // TODO(ivucica): add 'additionalProperties'?
-  reserved 29;
-  // following fields are reserved, as the properties have been omitted from
-  // OpenAPI v2:
-  // patternProperties, dependencies, propertyNames, const
-  reserved 30 to 33;
-  // Items in 'array' must be unique.
-  repeated string array = 34;
-
-  enum JSONSchemaSimpleTypes {
-    UNKNOWN = 0;
-    ARRAY = 1;
-    BOOLEAN = 2;
-    INTEGER = 3;
-    NULL = 4;
-    NUMBER = 5;
-    OBJECT = 6;
-    STRING = 7;
-  }
-
-  repeated JSONSchemaSimpleTypes type = 35;
-  // `Format`
-  string format = 36;
-  // following fields are reserved, as the properties have been omitted from 
-  // OpenAPI v2: contentMediaType, contentEncoding, if, then, else
-  reserved 37 to 41;
-  // field 42 is reserved for 'allOf', but in OpenAPI-specific way.
-  // TODO(ivucica): add 'allOf'?
-  reserved 42;
-  // following fields are reserved, as the properties have been omitted from
-  // OpenAPI v2:
-  // anyOf, oneOf, not
-  reserved 43 to 45;
-  // Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1
-  repeated string enum = 46;
-}
-
-// `Tag` is a representation of OpenAPI v2 specification's Tag object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject
-//
-message Tag {
-  // field 1 is reserved for 'name'. In our generator, this is (to be) extracted
-  // from the name of proto service, and thus not exposed to the user, as
-  // changing tag object's name would break the link to the references to the
-  // tag in individual operation specifications.
-  //
-  // TODO(ivucica): Add 'name' property. Use it to allow override of the name of
-  // global Tag object, then use that name to reference the tag throughout the
-  // OpenAPI file.
-  reserved 1;
-  // A short description for the tag. GFM syntax can be used for rich text 
-  // representation.
-  string description = 2;
-  // Additional external documentation for this tag.
-  ExternalDocumentation external_docs = 3;
-}
-
-// `SecurityDefinitions` is a representation of OpenAPI v2 specification's
-// Security Definitions object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject
-//
-// A declaration of the security schemes available to be used in the
-// specification. This does not enforce the security schemes on the operations
-// and only serves to provide the relevant details for each scheme.
-message SecurityDefinitions {
-  // A single security scheme definition, mapping a "name" to the scheme it
-  // defines.
-  map<string, SecurityScheme> security = 1;
-}
-
-// `SecurityScheme` is a representation of OpenAPI v2 specification's
-// Security Scheme object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject
-//
-// Allows the definition of a security scheme that can be used by the
-// operations. Supported schemes are basic authentication, an API key (either as
-// a header or as a query parameter) and OAuth2's common flows (implicit,
-// password, application and access code).
-message SecurityScheme {
-  // The type of the security scheme. Valid values are "basic",
-  // "apiKey" or "oauth2".
-  enum Type {
-    TYPE_INVALID = 0;
-    TYPE_BASIC = 1;
-    TYPE_API_KEY = 2;
-    TYPE_OAUTH2 = 3;
-  }
-
-  // The location of the API key. Valid values are "query" or "header".
-  enum In {
-    IN_INVALID = 0;
-    IN_QUERY = 1;
-    IN_HEADER = 2;
-  }
-
-  // The flow used by the OAuth2 security scheme. Valid values are
-  // "implicit", "password", "application" or "accessCode".
-  enum Flow {
-    FLOW_INVALID = 0;
-    FLOW_IMPLICIT = 1;
-    FLOW_PASSWORD = 2;
-    FLOW_APPLICATION = 3;
-    FLOW_ACCESS_CODE = 4;
-  }
-
-  // The type of the security scheme. Valid values are "basic",
-  // "apiKey" or "oauth2".
-  Type type = 1;
-  // A short description for security scheme.
-  string description = 2;
-  // The name of the header or query parameter to be used.
-  // Valid for apiKey.
-  string name = 3;
-  // The location of the API key. Valid values are "query" or
-  // "header".
-  // Valid for apiKey.
-  In in = 4;
-  // The flow used by the OAuth2 security scheme. Valid values are
-  // "implicit", "password", "application" or "accessCode".
-  // Valid for oauth2.
-  Flow flow = 5;
-  // The authorization URL to be used for this flow. This SHOULD be in
-  // the form of a URL.
-  // Valid for oauth2/implicit and oauth2/accessCode.
-  string authorization_url = 6;
-  // The token URL to be used for this flow. This SHOULD be in the
-  // form of a URL.
-  // Valid for oauth2/password, oauth2/application and oauth2/accessCode.
-  string token_url = 7;
-  // The available scopes for the OAuth2 security scheme.
-  // Valid for oauth2.
-  Scopes scopes = 8;
-  map<string, google.protobuf.Value> extensions = 9;
-}
-
-// `SecurityRequirement` is a representation of OpenAPI v2 specification's
-// Security Requirement object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject
-//
-// Lists the required security schemes to execute this operation. The object can
-// have multiple security schemes declared in it which are all required (that
-// is, there is a logical AND between the schemes).
-//
-// The name used for each property MUST correspond to a security scheme
-// declared in the Security Definitions.
-message SecurityRequirement {
-  // If the security scheme is of type "oauth2", then the value is a list of
-  // scope names required for the execution. For other security scheme types,
-  // the array MUST be empty.
-  message SecurityRequirementValue {
-    repeated string scope = 1;
-  }
-  // Each name must correspond to a security scheme which is declared in
-  // the Security Definitions. If the security scheme is of type "oauth2",
-  // then the value is a list of scope names required for the execution.
-  // For other security scheme types, the array MUST be empty.
-  map<string, SecurityRequirementValue> security_requirement = 1;
-}
-
-// `Scopes` is a representation of OpenAPI v2 specification's Scopes object.
-//
-// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject
-//
-// Lists the available scopes for an OAuth2 security scheme.
-message Scopes {
-  // Maps between a name of a scope to a short description of it (as the value
-  // of the property).
-  map<string, string> scope = 1;
-}
\ No newline at end of file


Test patch:
diff --git a/contrib/registry/polaris/registry_test.go b/contrib/registry/polaris/registry_test.go
new file mode 100644
index 00000000..af64230c
--- /dev/null
+++ b/contrib/registry/polaris/registry_test.go
@@ -0,0 +1,112 @@
+package polaris
+
+import (
+	"context"
+	"testing"
+	"time"
+
+	"github.com/polarismesh/polaris-go/pkg/config"
+
+	"github.com/go-kratos/kratos/v2/registry"
+	"github.com/polarismesh/polaris-go/api"
+)
+
+// TestRegistry . TestRegistryManyService
+func TestRegistry(t *testing.T) {
+	conf := config.NewDefaultConfiguration([]string{"127.0.0.1:8091"})
+	provider, err := api.NewProviderAPIByConfig(conf)
+	defer provider.Destroy()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	r := NewRegistry(
+		provider,
+		WithTimeout(1*time.Second),
+		WithTTL(5),
+	)
+
+	ctx := context.Background()
+
+	svc := &registry.ServiceInstance{
+		Name:      "kratos-provider-0-",
+		Version:   "test",
+		Metadata:  map[string]string{"app": "kratos"},
+		Endpoints: []string{"tcp://127.0.0.1:9000?isSecure=false"},
+	}
+
+	err = r.Register(ctx, svc)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = r.Deregister(ctx, svc)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// TestRegistryMany . TestRegistryManyService
+func TestRegistryMany(t *testing.T) {
+	conf := config.NewDefaultConfiguration([]string{"127.0.0.1:8091"})
+	provider, err := api.NewProviderAPIByConfig(conf)
+	defer provider.Destroy()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	r := NewRegistry(
+		provider,
+		WithTimeout(1*time.Second),
+		WithTTL(10),
+	)
+
+	svc := &registry.ServiceInstance{
+		Name:      "kratos-provider-0-",
+		Version:   "test",
+		Metadata:  map[string]string{"app": "kratos"},
+		Endpoints: []string{"tcp://127.0.0.1:9000?isSecure=false"},
+	}
+	svc1 := &registry.ServiceInstance{
+		Name:      "kratos-provider-1-",
+		Version:   "test",
+		Metadata:  map[string]string{"app": "kratos"},
+		Endpoints: []string{"tcp://127.0.0.1:9001?isSecure=false"},
+	}
+	svc2 := &registry.ServiceInstance{
+		Name:      "kratos-provider-2-",
+		Version:   "test",
+		Metadata:  map[string]string{"app": "kratos"},
+		Endpoints: []string{"tcp://127.0.0.1:9002?isSecure=false"},
+	}
+
+	err = r.Register(context.Background(), svc)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = r.Register(context.Background(), svc1)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = r.Register(context.Background(), svc2)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = r.Deregister(context.Background(), svc)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = r.Deregister(context.Background(), svc1)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = r.Deregister(context.Background(), svc2)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/middleware/auth/jwt/jwt_test.go b/middleware/auth/jwt/jwt_test.go
index 7944d503..188744b0 100644
--- a/middleware/auth/jwt/jwt_test.go
+++ b/middleware/auth/jwt/jwt_test.go
@@ -4,8 +4,11 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"math/rand"
 	"net/http"
 	"reflect"
+	"strconv"
+	"sync"
 	"testing"
 	"time"
 
@@ -63,6 +66,107 @@ func (tr *Transport) ReplyHeader() transport.Header {
 	return nil
 }
 
+type CustomerClaims struct {
+	Name string `json:"name"`
+	jwt.RegisteredClaims
+}
+
+func TestJWTServerParse(t *testing.T) {
+	var (
+		errConcurrentWrite = errors.New("concurrent write claims")
+		errParseClaims     = errors.New("bad result, token claims is not CustomerClaims")
+	)
+
+	testKey := "testKey"
+	tests := []struct {
+		name         string
+		token        func() string
+		claims       func() jwt.Claims
+		exceptErr    error
+		key          string
+		goroutineNum int
+	}{
+		{
+			name: "normal",
+			token: func() string {
+				token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, &CustomerClaims{}).SignedString([]byte(testKey))
+				if err != nil {
+					panic(err)
+				}
+				return fmt.Sprintf(bearerFormat, token)
+			},
+			claims: func() jwt.Claims {
+				return &CustomerClaims{}
+			},
+			exceptErr:    nil,
+			key:          testKey,
+			goroutineNum: 1,
+		},
+		{
+			name: "concurrent request",
+			token: func() string {
+				token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, &CustomerClaims{
+					Name: strconv.Itoa(rand.Int()),
+				}).SignedString([]byte(testKey))
+				if err != nil {
+					panic(err)
+				}
+				return fmt.Sprintf(bearerFormat, token)
+			},
+			claims: func() jwt.Claims {
+				return &CustomerClaims{}
+			},
+			exceptErr:    nil,
+			key:          testKey,
+			goroutineNum: 10000,
+		},
+	}
+
+	next := func(ctx context.Context, req interface{}) (interface{}, error) {
+		testToken, _ := FromContext(ctx)
+		var name string
+		if customerClaims, ok := testToken.(*CustomerClaims); ok {
+			name = customerClaims.Name
+		} else {
+			return nil, errParseClaims
+		}
+
+		// mock biz
+		time.Sleep(100 * time.Millisecond)
+
+		if customerClaims, ok := testToken.(*CustomerClaims); ok {
+			if name != customerClaims.Name {
+				return nil, errConcurrentWrite
+			}
+		} else {
+			return nil, errParseClaims
+		}
+		return "reply", nil
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			server := Server(
+				func(token *jwt.Token) (interface{}, error) { return []byte(testKey), nil },
+				WithClaims(test.claims),
+			)(next)
+			wg := sync.WaitGroup{}
+			for i := 0; i < test.goroutineNum; i++ {
+				wg.Add(1)
+				go func() {
+					defer wg.Done()
+					ctx := transport.NewServerContext(context.Background(), &Transport{reqHeader: newTokenHeader(authorizationKey, test.token())})
+					_, err2 := server(ctx, test.name)
+					if !errors.Is(test.exceptErr, err2) {
+						t.Errorf("except error %v, but got %v", test.exceptErr, err2)
+					}
+				}()
+			}
+			wg.Wait()
+		})
+	}
+}
+
 func TestServer(t *testing.T) {
 	testKey := "testKey"
 	mapClaims := jwt.MapClaims{}
@@ -279,6 +383,7 @@ func TestClientWithClaims(t *testing.T) {
 	testKey := "testKey"
 	mapClaims := jwt.MapClaims{}
 	mapClaims["name"] = "xiaoli"
+	mapClaimsFunc := func() jwt.Claims { return mapClaims }
 	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, mapClaims)
 	token, err := claims.SignedString([]byte(testKey))
 	if err != nil {
@@ -301,7 +406,7 @@ func TestClientWithClaims(t *testing.T) {
 		next := func(ctx context.Context, req interface{}) (interface{}, error) {
 			return "reply", nil
 		}
-		handler := Client(test.tokenProvider, WithClaims(mapClaims))(next)
+		handler := Client(test.tokenProvider, WithClaims(mapClaimsFunc))(next)
 		header := &headerCarrier{}
 		_, err2 := handler(transport.NewClientContext(context.Background(), &Transport{reqHeader: header}), "ok")
 		if !errors.Is(test.expectError, err2) {
@@ -319,6 +424,7 @@ func TestClientWithHeader(t *testing.T) {
 	testKey := "testKey"
 	mapClaims := jwt.MapClaims{}
 	mapClaims["name"] = "xiaoli"
+	mapClaimsFunc := func() jwt.Claims { return mapClaims }
 	tokenHeader := map[string]interface{}{
 		"test": "test",
 	}
@@ -336,7 +442,7 @@ func TestClientWithHeader(t *testing.T) {
 	next := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return "reply", nil
 	}
-	handler := Client(tProvider, WithClaims(mapClaims), WithTokenHeader(tokenHeader))(next)
+	handler := Client(tProvider, WithClaims(mapClaimsFunc), WithTokenHeader(tokenHeader))(next)
 	header := &headerCarrier{}
 	_, err2 := handler(transport.NewClientContext(context.Background(), &Transport{reqHeader: header}), "ok")
 	if err2 != nil {
@@ -351,6 +457,7 @@ func TestClientMissKey(t *testing.T) {
 	testKey := "testKey"
 	mapClaims := jwt.MapClaims{}
 	mapClaims["name"] = "xiaoli"
+	mapClaimsFunc := func() jwt.Claims { return mapClaims }
 	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, mapClaims)
 	token, err := claims.SignedString([]byte(testKey))
 	if err != nil {
@@ -373,7 +480,7 @@ func TestClientMissKey(t *testing.T) {
 		next := func(ctx context.Context, req interface{}) (interface{}, error) {
 			return "reply", nil
 		}
-		handler := Client(test.tokenProvider, WithClaims(mapClaims))(next)
+		handler := Client(test.tokenProvider, WithClaims(mapClaimsFunc))(next)
 		header := &headerCarrier{}
 		_, err2 := handler(transport.NewClientContext(context.Background(), &Transport{reqHeader: header}), "ok")
 		if !errors.Is(test.expectError, err2) {
diff --git a/transport/grpc/client_test.go b/transport/grpc/client_test.go
index 034f01e4..1443b9b8 100644
--- a/transport/grpc/client_test.go
+++ b/transport/grpc/client_test.go
@@ -104,12 +104,10 @@ func TestUnaryClientInterceptor(t *testing.T) {
 func TestWithUnaryInterceptor(t *testing.T) {
 	o := &clientOptions{}
 	v := []grpc.UnaryClientInterceptor{
-		func(ctx context.Context, method string, req, reply interface{},
-			cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+		func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
 			return nil
 		},
-		func(ctx context.Context, method string, req, reply interface{},
-			cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+		func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
 			return nil
 		},
 	}
diff --git a/transport/grpc/server_test.go b/transport/grpc/server_test.go
index aaa6aca1..b4893186 100644
--- a/transport/grpc/server_test.go
+++ b/transport/grpc/server_test.go
@@ -53,8 +53,7 @@ func TestServer(t *testing.T) {
 					return handler(ctx, req)
 				}
 			}),
-		UnaryInterceptor(func(ctx context.Context, req interface{},
-			info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+		UnaryInterceptor(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 			return handler(ctx, req)
 		}),
 		Options(grpc.InitialConnWindowSize(0)),
@@ -85,10 +84,10 @@ func testClient(t *testing.T, srv *Server) {
 	conn, err := DialInsecure(context.Background(),
 		WithEndpoint(u.Host),
 		WithOptions(grpc.WithBlock()),
-		WithUnaryInterceptor(func(ctx context.Context, method string, req, reply interface{},
-			cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
-			return invoker(ctx, method, req, reply, cc, opts...)
-		}),
+		WithUnaryInterceptor(
+			func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+				return invoker(ctx, method, req, reply, cc, opts...)
+			}),
 		WithMiddleware(func(handler middleware.Handler) middleware.Handler {
 			return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
 				if tr, ok := transport.FromClientContext(ctx); ok {