diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8d84e695a59e8064cf06a2f8879564efd5588d44
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,5 @@
+notifications:
+    commits:      commits@dubbo.apache.org
+    issues:       notifications@dubbo.apache.org
+    pullrequests: notifications@dubbo.apache.org
+    jira_options: link label link label
diff --git a/.travis.yml b/.travis.yml
index 1b46f5d872932b7ed307ceaf802c95997b2800e6..566c88ece05bd80175eea2d1de8fd061a279e273 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,23 +1,32 @@
-language: go
+dist: trusty
+sudo: required
 
+# define the dependence env
+language: go
 os:
   - linux
-
 go:
   - "1.13"
-
+services:
+  - docker
 env:
   - GO111MODULE=on
-
 install: true
 
+# define ci-stage
 script:
+  # license-check
+  - echo 'start license check'
   - go fmt ./... && [[ -z `git status -s` ]]
   - sh before_validate_license.sh
   - chmod u+x /tmp/tools/license/license-header-checker
   - /tmp/tools/license/license-header-checker -v -a -r -i vendor  /tmp/tools/license/license.txt . go  && [[ -z `git status -s` ]]
+  # unit-test
+  - echo 'start unit-test'
   - chmod u+x before_ut.sh && ./before_ut.sh
   - go mod vendor && go test ./... -coverprofile=coverage.txt -covermode=atomic
+  # integrate-test
+  - chmod +x integrate_test.sh && ./integrate_test.sh
 
 after_success:
   - bash <(curl -s https://codecov.io/bash)
diff --git a/cluster/cluster_impl/available_cluster_invoker_test.go b/cluster/cluster_impl/available_cluster_invoker_test.go
index c2cebd3843d453a2d46d031e711e0efebd240fda..61d1c934522008e4d9bc46bbd57eb6fed6bf00f9 100644
--- a/cluster/cluster_impl/available_cluster_invoker_test.go
+++ b/cluster/cluster_impl/available_cluster_invoker_test.go
@@ -42,7 +42,7 @@ var (
 	availableUrl, _ = common.NewURL("dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider")
 )
 
-func registerAvailable(t *testing.T, invoker *mock.MockInvoker) protocol.Invoker {
+func registerAvailable(invoker *mock.MockInvoker) protocol.Invoker {
 	extension.SetLoadbalance("random", loadbalance.NewRandomLoadBalance)
 	availableCluster := NewAvailableCluster()
 
@@ -60,7 +60,7 @@ func TestAvailableClusterInvokerSuccess(t *testing.T) {
 	defer ctrl.Finish()
 
 	invoker := mock.NewMockInvoker(ctrl)
-	clusterInvoker := registerAvailable(t, invoker)
+	clusterInvoker := registerAvailable(invoker)
 
 	mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}}
 	invoker.EXPECT().IsAvailable().Return(true)
@@ -76,7 +76,7 @@ func TestAvailableClusterInvokerNoAvail(t *testing.T) {
 	defer ctrl.Finish()
 
 	invoker := mock.NewMockInvoker(ctrl)
-	clusterInvoker := registerAvailable(t, invoker)
+	clusterInvoker := registerAvailable(invoker)
 
 	invoker.EXPECT().IsAvailable().Return(false)
 
diff --git a/cluster/cluster_impl/base_cluster_invoker.go b/cluster/cluster_impl/base_cluster_invoker.go
index 12799994125c4bf5d968dfc811cda374effbf85c..cabd6c5f17cd3a3310054c0ff7b9a9877d581345 100644
--- a/cluster/cluster_impl/base_cluster_invoker.go
+++ b/cluster/cluster_impl/base_cluster_invoker.go
@@ -87,7 +87,6 @@ func (invoker *baseClusterInvoker) checkWhetherDestroyed() error {
 }
 
 func (invoker *baseClusterInvoker) doSelect(lb cluster.LoadBalance, invocation protocol.Invocation, invokers []protocol.Invoker, invoked []protocol.Invoker) protocol.Invoker {
-
 	var selectedInvoker protocol.Invoker
 	url := invokers[0].GetUrl()
 	sticky := url.GetParamBool(constant.STICKY_KEY, false)
diff --git a/cluster/cluster_impl/failover_cluster_test.go b/cluster/cluster_impl/failover_cluster_test.go
index 1be21067a6a9045cb6ae6f84655d516fea1f844b..ee7d48f3497772db3143b1ae62a30f66f99faa58 100644
--- a/cluster/cluster_impl/failover_cluster_test.go
+++ b/cluster/cluster_impl/failover_cluster_test.go
@@ -107,8 +107,8 @@ func normalInvoke(t *testing.T, successCount int, urlParam url.Values, invocatio
 
 	invokers := []protocol.Invoker{}
 	for i := 0; i < 10; i++ {
-		url, _ := common.NewURL(fmt.Sprintf("dubbo://192.168.1.%v:20000/com.ikurento.user.UserProvider", i), common.WithParams(urlParam))
-		invokers = append(invokers, NewMockInvoker(url, successCount))
+		newUrl, _ := common.NewURL(fmt.Sprintf("dubbo://192.168.1.%v:20000/com.ikurento.user.UserProvider", i), common.WithParams(urlParam))
+		invokers = append(invokers, NewMockInvoker(newUrl, successCount))
 	}
 
 	staticDir := directory.NewStaticDirectory(invokers)
diff --git a/cluster/directory/base_directory.go b/cluster/directory/base_directory.go
index a3e207f3022a4d882d1b90f2756b51ab4e0b2775..3ede3d8c0ab3691603ac69c10202155e0a331d26 100644
--- a/cluster/directory/base_directory.go
+++ b/cluster/directory/base_directory.go
@@ -89,7 +89,7 @@ func (dir *BaseDirectory) SetRouters(urls []*common.URL) {
 			factory := extension.GetRouterFactory(url.Protocol)
 			r, err := factory.NewRouter(url)
 			if err != nil {
-				logger.Errorf("Create router fail. router key: %s, error: %v", routerKey, url.Service(), err)
+				logger.Errorf("Create router fail. router key: %s, url:%s, error: %+v", routerKey, url.Service(), err)
 				return
 			}
 			routers = append(routers, r)
diff --git a/cluster/directory/base_directory_test.go b/cluster/directory/base_directory_test.go
index d5993959f1d37f343a612e2bee305461d49535d0..6dc55b39407c9e88d18a65b5ec02fa866571624b 100644
--- a/cluster/directory/base_directory_test.go
+++ b/cluster/directory/base_directory_test.go
@@ -19,7 +19,6 @@ package directory
 
 import (
 	"encoding/base64"
-	"fmt"
 	"testing"
 )
 
@@ -35,7 +34,7 @@ import (
 )
 
 func TestNewBaseDirectory(t *testing.T) {
-	url, _ := common.NewURL(fmt.Sprintf("dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider"))
+	url, _ := common.NewURL("dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider")
 	directory := NewBaseDirectory(&url)
 
 	assert.NotNil(t, directory)
@@ -46,7 +45,7 @@ func TestNewBaseDirectory(t *testing.T) {
 }
 
 func TestBuildRouterChain(t *testing.T) {
-	url, _ := common.NewURL(fmt.Sprintf("dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider"))
+	url, _ := common.NewURL("dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider")
 	directory := NewBaseDirectory(&url)
 
 	assert.NotNil(t, directory)
diff --git a/cluster/directory/static_directory.go b/cluster/directory/static_directory.go
index 9f600fedc40cf29a40abca6c11652935f20473b4..87f51356495dbd0a956c42bf4f34022b4d21ad4d 100644
--- a/cluster/directory/static_directory.go
+++ b/cluster/directory/static_directory.go
@@ -61,7 +61,7 @@ func (dir *staticDirectory) IsAvailable() bool {
 // List List invokers
 func (dir *staticDirectory) List(invocation protocol.Invocation) []protocol.Invoker {
 	l := len(dir.invokers)
-	invokers := make([]protocol.Invoker, l, l)
+	invokers := make([]protocol.Invoker, l)
 	copy(invokers, dir.invokers)
 	routerChain := dir.RouterChain()
 
diff --git a/cluster/loadbalance/consistent_hash.go b/cluster/loadbalance/consistent_hash.go
index 957c110663d6c56ada15543d372e210fa83bf74b..492434431f7382545cb747fa3611c6b18279fa4d 100644
--- a/cluster/loadbalance/consistent_hash.go
+++ b/cluster/loadbalance/consistent_hash.go
@@ -27,7 +27,9 @@ import (
 	"strconv"
 	"strings"
 )
-
+import (
+	gxsort "github.com/dubbogo/gost/sort"
+)
 import (
 	"github.com/apache/dubbo-go/cluster"
 	"github.com/apache/dubbo-go/common/constant"
@@ -40,7 +42,7 @@ const (
 	ConsistentHash = "consistenthash"
 	// HashNodes ...
 	HashNodes = "hash.nodes"
-	// HashArguments ...
+	// HashArguments  key of hash arguments  in url
 	HashArguments = "hash.arguments"
 )
 
@@ -53,16 +55,16 @@ func init() {
 	extension.SetLoadbalance(ConsistentHash, NewConsistentHashLoadBalance)
 }
 
-// ConsistentHashLoadBalance ...
+// ConsistentHashLoadBalance implementation of load balancing: using consistent hashing
 type ConsistentHashLoadBalance struct {
 }
 
-// NewConsistentHashLoadBalance ...
+// NewConsistentHashLoadBalance creates NewConsistentHashLoadBalance
 func NewConsistentHashLoadBalance() cluster.LoadBalance {
 	return &ConsistentHashLoadBalance{}
 }
 
-// Select ...
+// Select gets invoker based on load balancing strategy
 func (lb *ConsistentHashLoadBalance) Select(invokers []protocol.Invoker, invocation protocol.Invocation) protocol.Invoker {
 	methodName := invocation.MethodName()
 	key := invokers[0].GetUrl().ServiceKey() + "." + methodName
@@ -85,27 +87,12 @@ func (lb *ConsistentHashLoadBalance) Select(invokers []protocol.Invoker, invocat
 	return selector.Select(invocation)
 }
 
-// Uint32Slice ...
-type Uint32Slice []uint32
-
-func (s Uint32Slice) Len() int {
-	return len(s)
-}
-
-func (s Uint32Slice) Less(i, j int) bool {
-	return s[i] < s[j]
-}
-
-func (s Uint32Slice) Swap(i, j int) {
-	s[i], s[j] = s[j], s[i]
-}
-
-// ConsistentHashSelector ...
+// ConsistentHashSelector implementation of Selector:get invoker based on load balancing strategy
 type ConsistentHashSelector struct {
 	hashCode        uint32
 	replicaNum      int
 	virtualInvokers map[uint32]protocol.Invoker
-	keys            Uint32Slice
+	keys            gxsort.Uint32Slice
 	argumentIndex   []int
 }
 
@@ -141,7 +128,7 @@ func newConsistentHashSelector(invokers []protocol.Invoker, methodName string,
 	return selector
 }
 
-// Select ...
+// Select gets invoker based on load balancing strategy
 func (c *ConsistentHashSelector) Select(invocation protocol.Invocation) protocol.Invoker {
 	key := c.toKey(invocation.Arguments())
 	digest := md5.Sum([]byte(key))
diff --git a/common/config/environment.go b/common/config/environment.go
index 071af31152ba4ce3c579f70aa23df59d718ce506..446c46aa1ef71a68aa024bf83dd9088cf03677f2 100644
--- a/common/config/environment.go
+++ b/common/config/environment.go
@@ -46,7 +46,7 @@ var (
 	once     sync.Once
 )
 
-// GetEnvInstance ...
+// GetEnvInstance gets env instance by singleton
 func GetEnvInstance() *Environment {
 	once.Do(func() {
 		instance = &Environment{configCenterFirst: true}
@@ -54,7 +54,7 @@ func GetEnvInstance() *Environment {
 	return instance
 }
 
-// NewEnvInstance ...
+// NewEnvInstance creates Environment instance
 func NewEnvInstance() {
 	instance = &Environment{configCenterFirst: true}
 }
@@ -67,21 +67,22 @@ func NewEnvInstance() {
 //	return env.configCenterFirst
 //}
 
-// UpdateExternalConfigMap ...
+// UpdateExternalConfigMap updates env externalConfigMap field
 func (env *Environment) UpdateExternalConfigMap(externalMap map[string]string) {
 	for k, v := range externalMap {
 		env.externalConfigMap.Store(k, v)
 	}
 }
 
-// UpdateAppExternalConfigMap ...
+// UpdateAppExternalConfigMap updates env appExternalConfigMap field
 func (env *Environment) UpdateAppExternalConfigMap(externalMap map[string]string) {
 	for k, v := range externalMap {
 		env.appExternalConfigMap.Store(k, v)
 	}
 }
 
-// Configuration ...
+// Configuration puts externalConfigMap and appExternalConfigMap into list
+// List represents a doubly linked list.
 func (env *Environment) Configuration() *list.List {
 	cfgList := list.New()
 	// The sequence would be: SystemConfiguration -> ExternalConfiguration -> AppExternalConfiguration -> AbstractConfig -> PropertiesConfiguration
@@ -90,17 +91,17 @@ func (env *Environment) Configuration() *list.List {
 	return cfgList
 }
 
-// SetDynamicConfiguration ...
+// SetDynamicConfiguration sets value for dynamicConfiguration
 func (env *Environment) SetDynamicConfiguration(dc config_center.DynamicConfiguration) {
 	env.dynamicConfiguration = dc
 }
 
-// GetDynamicConfiguration ...
+// GetDynamicConfiguration gets dynamicConfiguration
 func (env *Environment) GetDynamicConfiguration() config_center.DynamicConfiguration {
 	return env.dynamicConfiguration
 }
 
-// InmemoryConfiguration ...
+// InmemoryConfiguration stores config in memory
 type InmemoryConfiguration struct {
 	store *sync.Map
 }
@@ -109,7 +110,7 @@ func newInmemoryConfiguration(p *sync.Map) *InmemoryConfiguration {
 	return &InmemoryConfiguration{store: p}
 }
 
-// GetProperty ...
+// GetProperty gets value from InmemoryConfiguration instance by @key
 func (conf *InmemoryConfiguration) GetProperty(key string) (bool, string) {
 	if conf.store == nil {
 		return false, ""
@@ -123,7 +124,7 @@ func (conf *InmemoryConfiguration) GetProperty(key string) (bool, string) {
 	return false, ""
 }
 
-// GetSubProperty ...
+// GetSubProperty gets sub property from InmemoryConfiguration instance by @subkey
 func (conf *InmemoryConfiguration) GetSubProperty(subKey string) map[string]struct{} {
 	if conf.store == nil {
 		return nil
diff --git a/common/constant/key.go b/common/constant/key.go
index eafed2eeeb88e0606ac92766c8dd84ff6b42b58e..15496628ebef49517abc2e6811822a34b94caddf 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -187,6 +187,9 @@ const (
 	// ForceUseTag is the tag in attachment
 	ForceUseTag = "dubbo.force.tag"
 	Tagkey      = "dubbo.tag"
+
+	// Attachment key in context in invoker
+	AttachmentKey = "attachment"
 )
 
 const (
diff --git a/common/extension/auth.go b/common/extension/auth.go
index d7900045d3f7db9e2587e4e92e377325c74971b3..7caae00e84fd80666ff79b599e12f8516e23209c 100644
--- a/common/extension/auth.go
+++ b/common/extension/auth.go
@@ -26,12 +26,12 @@ var (
 	accesskeyStorages = make(map[string]func() filter.AccessKeyStorage)
 )
 
-// SetAuthenticator put the fcn into map with name
+// SetAuthenticator puts the @fcn into map with name
 func SetAuthenticator(name string, fcn func() filter.Authenticator) {
 	authenticators[name] = fcn
 }
 
-// GetAuthenticator find the Authenticator with name
+// GetAuthenticator finds the Authenticator with @name
 // if not found, it will panic
 func GetAuthenticator(name string) filter.Authenticator {
 	if authenticators[name] == nil {
@@ -40,12 +40,12 @@ func GetAuthenticator(name string) filter.Authenticator {
 	return authenticators[name]()
 }
 
-// SetAccesskeyStorages will set the fcn into map with this name
+// SetAccesskeyStorages will set the @fcn into map with this name
 func SetAccesskeyStorages(name string, fcn func() filter.AccessKeyStorage) {
 	accesskeyStorages[name] = fcn
 }
 
-// GetAccesskeyStorages find the storage with the name.
+// GetAccesskeyStorages finds the storage with the @name.
 // If not found, it will panic.
 func GetAccesskeyStorages(name string) filter.AccessKeyStorage {
 	if accesskeyStorages[name] == nil {
diff --git a/common/extension/cluster.go b/common/extension/cluster.go
index b2d81f6b1e56bb487b1d408b878308f6dfe042e4..8be27a1ca3aaf93dd54201c4ff7081478c746f0f 100644
--- a/common/extension/cluster.go
+++ b/common/extension/cluster.go
@@ -25,12 +25,13 @@ var (
 	clusters = make(map[string]func() cluster.Cluster)
 )
 
-// SetCluster ...
+// SetCluster sets the cluster fault-tolerant mode with @name
+// For example: available/failfast/broadcast/failfast/failsafe/...
 func SetCluster(name string, fcn func() cluster.Cluster) {
 	clusters[name] = fcn
 }
 
-// GetCluster ...
+// GetCluster finds the cluster fault-tolerant mode with @name
 func GetCluster(name string) cluster.Cluster {
 	if clusters[name] == nil {
 		panic("cluster for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/config_center.go b/common/extension/config_center.go
index 03d27db46c94b0ea0e212646077d97f948a8e328..3cbced8d3bbcdb3dc7f9af800fa36681d6dc063d 100644
--- a/common/extension/config_center.go
+++ b/common/extension/config_center.go
@@ -26,12 +26,12 @@ var (
 	configCenters = make(map[string]func(config *common.URL) (config_center.DynamicConfiguration, error))
 )
 
-// SetConfigCenter ...
+// SetConfigCenter sets the DynamicConfiguration with @name
 func SetConfigCenter(name string, v func(config *common.URL) (config_center.DynamicConfiguration, error)) {
 	configCenters[name] = v
 }
 
-// GetConfigCenter ...
+// GetConfigCenter finds the DynamicConfiguration with @name
 func GetConfigCenter(name string, config *common.URL) (config_center.DynamicConfiguration, error) {
 	if configCenters[name] == nil {
 		panic("config center for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/config_center_factory.go b/common/extension/config_center_factory.go
index 85913fdce1ed3472c2bd9eb4aadbb0f631481dbd..dff89752296c6d2441d043ec628aa13ad219e698 100644
--- a/common/extension/config_center_factory.go
+++ b/common/extension/config_center_factory.go
@@ -25,12 +25,12 @@ var (
 	configCenterFactories = make(map[string]func() config_center.DynamicConfigurationFactory)
 )
 
-// SetConfigCenterFactory ...
+// SetConfigCenterFactory sets the DynamicConfigurationFactory with @name
 func SetConfigCenterFactory(name string, v func() config_center.DynamicConfigurationFactory) {
 	configCenterFactories[name] = v
 }
 
-// GetConfigCenterFactory ...
+// GetConfigCenterFactory finds the DynamicConfigurationFactory with @name
 func GetConfigCenterFactory(name string) config_center.DynamicConfigurationFactory {
 	if configCenterFactories[name] == nil {
 		panic("config center for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/config_reader.go b/common/extension/config_reader.go
index aced5b0281ff9313461425e5ec6d70d562c6c947..5e13d8629fd145dac680619a427c68b29226b051 100644
--- a/common/extension/config_reader.go
+++ b/common/extension/config_reader.go
@@ -26,12 +26,12 @@ var (
 	defaults      = make(map[string]string)
 )
 
-// SetConfigReaders set a creator of config reader.
+// SetConfigReaders sets a creator of config reader with @name
 func SetConfigReaders(name string, v func() interfaces.ConfigReader) {
 	configReaders[name] = v
 }
 
-// GetConfigReaders get a config reader by name.
+// GetConfigReaders gets a config reader with @name
 func GetConfigReaders(name string) interfaces.ConfigReader {
 	if configReaders[name] == nil {
 		panic("config reader for " + name + " is not existing, make sure you have imported the package.")
@@ -39,12 +39,12 @@ func GetConfigReaders(name string) interfaces.ConfigReader {
 	return configReaders[name]()
 }
 
-// SetDefaultConfigReader set {name} to default config reader for {module}
+// SetDefaultConfigReader sets @name for @module in default config reader
 func SetDefaultConfigReader(module, name string) {
 	defaults[module] = name
 }
 
-// GetDefaultConfigReader
+// GetDefaultConfigReader gets default config reader
 func GetDefaultConfigReader() map[string]string {
 	return defaults
 }
diff --git a/common/extension/configurator.go b/common/extension/configurator.go
index de98f8a260ea1f3a2e2a1f32c82dc869585e2789..dc2bea73afb79aaab36e2ce7cc9675169a446eb7 100644
--- a/common/extension/configurator.go
+++ b/common/extension/configurator.go
@@ -23,7 +23,7 @@ import (
 )
 
 const (
-	// DefaultKey ...
+	// DefaultKey for default Configurator
 	DefaultKey = "default"
 )
 
@@ -33,12 +33,12 @@ var (
 	configurator = make(map[string]getConfiguratorFunc)
 )
 
-// SetConfigurator ...
+// SetConfigurator sets the getConfiguratorFunc with @name
 func SetConfigurator(name string, v getConfiguratorFunc) {
 	configurator[name] = v
 }
 
-// GetConfigurator ...
+// GetConfigurator finds the Configurator with @name
 func GetConfigurator(name string, url *common.URL) config_center.Configurator {
 	if configurator[name] == nil {
 		panic("configurator for " + name + " is not existing, make sure you have import the package.")
@@ -47,12 +47,12 @@ func GetConfigurator(name string, url *common.URL) config_center.Configurator {
 
 }
 
-// SetDefaultConfigurator ...
+// SetDefaultConfigurator sets the default Configurator
 func SetDefaultConfigurator(v getConfiguratorFunc) {
 	configurator[DefaultKey] = v
 }
 
-// GetDefaultConfigurator ...
+// GetDefaultConfigurator gets default configurator
 func GetDefaultConfigurator(url *common.URL) config_center.Configurator {
 	if configurator[DefaultKey] == nil {
 		panic("configurator for default is not existing, make sure you have import the package.")
@@ -61,7 +61,7 @@ func GetDefaultConfigurator(url *common.URL) config_center.Configurator {
 
 }
 
-// GetDefaultConfiguratorFunc ...
+// GetDefaultConfiguratorFunc gets default configurator function
 func GetDefaultConfiguratorFunc() getConfiguratorFunc {
 	if configurator[DefaultKey] == nil {
 		panic("configurator for default is not existing, make sure you have import the package.")
diff --git a/common/extension/filter.go b/common/extension/filter.go
index deea2d908bc2741e0f15ecc36e9d4fc5975e531e..96059c4363060c41f14ececb466ca62bdaefb1a9 100644
--- a/common/extension/filter.go
+++ b/common/extension/filter.go
@@ -26,12 +26,13 @@ var (
 	rejectedExecutionHandler = make(map[string]func() filter.RejectedExecutionHandler)
 )
 
-// SetFilter ...
+// SetFilter sets the filter extension with @name
+// For example: hystrix/metrics/token/tracing/limit/...
 func SetFilter(name string, v func() filter.Filter) {
 	filters[name] = v
 }
 
-// GetFilter ...
+// GetFilter finds the filter extension with @name
 func GetFilter(name string) filter.Filter {
 	if filters[name] == nil {
 		panic("filter for " + name + " is not existing, make sure you have imported the package.")
@@ -39,12 +40,12 @@ func GetFilter(name string) filter.Filter {
 	return filters[name]()
 }
 
-// SetRejectedExecutionHandler ...
+// SetRejectedExecutionHandler sets the RejectedExecutionHandler with @name
 func SetRejectedExecutionHandler(name string, creator func() filter.RejectedExecutionHandler) {
 	rejectedExecutionHandler[name] = creator
 }
 
-// GetRejectedExecutionHandler ...
+// GetRejectedExecutionHandler finds the RejectedExecutionHandler with @name
 func GetRejectedExecutionHandler(name string) filter.RejectedExecutionHandler {
 	creator, ok := rejectedExecutionHandler[name]
 	if !ok {
diff --git a/common/extension/graceful_shutdown.go b/common/extension/graceful_shutdown.go
index 3abd75c0aa328f3553c3d83340ae440b8dfe3356..cb55419aabbce26b41e5b10f49268f6b3ace516d 100644
--- a/common/extension/graceful_shutdown.go
+++ b/common/extension/graceful_shutdown.go
@@ -49,7 +49,7 @@ func AddCustomShutdownCallback(callback func()) {
 	customShutdownCallbacks.PushBack(callback)
 }
 
-// GetAllCustomShutdownCallbacks ...
+// GetAllCustomShutdownCallbacks gets all custom shutdown callbacks
 func GetAllCustomShutdownCallbacks() *list.List {
 	return customShutdownCallbacks
 }
diff --git a/common/extension/health_checker.go b/common/extension/health_checker.go
index 365c5d0910812efb00eb94408bb226115b037c02..548d4dc761b31773a2a39ccb0ae3de1d7ab39eb4 100644
--- a/common/extension/health_checker.go
+++ b/common/extension/health_checker.go
@@ -26,12 +26,12 @@ var (
 	healthCheckers = make(map[string]func(url *common.URL) router.HealthChecker)
 )
 
-// SethealthChecker set the HealthChecker with name
+// SethealthChecker sets the HealthChecker with @name
 func SethealthChecker(name string, fcn func(url *common.URL) router.HealthChecker) {
 	healthCheckers[name] = fcn
 }
 
-// GetHealthChecker get the HealthChecker with name
+// GetHealthChecker gets the HealthChecker with @name
 func GetHealthChecker(name string, url *common.URL) router.HealthChecker {
 	if healthCheckers[name] == nil {
 		panic("healthCheckers for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/loadbalance.go b/common/extension/loadbalance.go
index 0d557a4640ed892a18ad59a3247763ab5807a593..aa19141014a6c42df0c17dad05301997f67fbd79 100644
--- a/common/extension/loadbalance.go
+++ b/common/extension/loadbalance.go
@@ -25,12 +25,13 @@ var (
 	loadbalances = make(map[string]func() cluster.LoadBalance)
 )
 
-// SetLoadbalance ...
+// SetLoadbalance sets the loadbalance extension with @name
+// For example: random/round_robin/consistent_hash/least_active/...
 func SetLoadbalance(name string, fcn func() cluster.LoadBalance) {
 	loadbalances[name] = fcn
 }
 
-// GetLoadbalance ...
+// GetLoadbalance finds the loadbalance extension with @name
 func GetLoadbalance(name string) cluster.LoadBalance {
 	if loadbalances[name] == nil {
 		panic("loadbalance for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/metadata_report_factory.go b/common/extension/metadata_report_factory.go
index 89dab0409987d8959b5761771c8893abaf88673b..593318d01beec1f89d8194c6d4bd18a15c798a0e 100644
--- a/common/extension/metadata_report_factory.go
+++ b/common/extension/metadata_report_factory.go
@@ -25,12 +25,12 @@ var (
 	metaDataReportFactories = make(map[string]func() factory.MetadataReportFactory, 8)
 )
 
-// SetMetadataReportFactory ...
+// SetMetadataReportFactory sets the MetadataReportFactory with @name
 func SetMetadataReportFactory(name string, v func() factory.MetadataReportFactory) {
 	metaDataReportFactories[name] = v
 }
 
-// GetMetadataReportFactory ...
+// GetMetadataReportFactory finds the MetadataReportFactory with @name
 func GetMetadataReportFactory(name string) factory.MetadataReportFactory {
 	if metaDataReportFactories[name] == nil {
 		panic("metadata report for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/metrics.go b/common/extension/metrics.go
index 42fca7a2db36614fcef31dd5ba7324a156164d4f..60cf6bac2384c7367094adad83e01f7dcf64a33d 100644
--- a/common/extension/metrics.go
+++ b/common/extension/metrics.go
@@ -27,12 +27,12 @@ var (
 	metricReporterMap = make(map[string]func() metrics.Reporter, 4)
 )
 
-// SetMetricReporter set a reporter with the name
+// SetMetricReporter sets a reporter with the @name
 func SetMetricReporter(name string, reporterFunc func() metrics.Reporter) {
 	metricReporterMap[name] = reporterFunc
 }
 
-// GetMetricReporter find the reporter with name.
+// GetMetricReporter finds the reporter with @name.
 // if not found, it will panic.
 // we should know that this method usually is called when system starts, so we should panic
 func GetMetricReporter(name string) metrics.Reporter {
diff --git a/common/extension/protocol.go b/common/extension/protocol.go
index 009687a17ace8cea567248af655e04604d09d9b8..c89dd08fae5d12b384d6ca4e797343fe79897bbd 100644
--- a/common/extension/protocol.go
+++ b/common/extension/protocol.go
@@ -25,12 +25,12 @@ var (
 	protocols = make(map[string]func() protocol.Protocol)
 )
 
-// SetProtocol ...
+// SetProtocol sets the protocol extension with @name
 func SetProtocol(name string, v func() protocol.Protocol) {
 	protocols[name] = v
 }
 
-// GetProtocol ...
+// GetProtocol finds the protocol extension with @name
 func GetProtocol(name string) protocol.Protocol {
 	if protocols[name] == nil {
 		panic("protocol for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/proxy_factory.go b/common/extension/proxy_factory.go
index 19826bb0560ea0d3fa471c04873b20a6878f57d8..1e326d884b5dd37925c38ffdf0a87e69bf6a865c 100644
--- a/common/extension/proxy_factory.go
+++ b/common/extension/proxy_factory.go
@@ -25,12 +25,12 @@ var (
 	proxyFactories = make(map[string]func(...proxy.Option) proxy.ProxyFactory)
 )
 
-// SetProxyFactory ...
+// SetProxyFactory sets the ProxyFactory extension with @name
 func SetProxyFactory(name string, f func(...proxy.Option) proxy.ProxyFactory) {
 	proxyFactories[name] = f
 }
 
-// GetProxyFactory ...
+// GetProxyFactory finds the ProxyFactory extension with @name
 func GetProxyFactory(name string) proxy.ProxyFactory {
 	if name == "" {
 		name = "default"
diff --git a/common/extension/registry.go b/common/extension/registry.go
index 6ba746dc47382927d12ce39b7936212c5d75153d..291a7a7fc2cae07c9228043acae7cc0ed5459a1f 100644
--- a/common/extension/registry.go
+++ b/common/extension/registry.go
@@ -26,12 +26,12 @@ var (
 	registrys = make(map[string]func(config *common.URL) (registry.Registry, error))
 )
 
-// SetRegistry ...
+// SetRegistry sets the registry extension with @name
 func SetRegistry(name string, v func(config *common.URL) (registry.Registry, error)) {
 	registrys[name] = v
 }
 
-// GetRegistry ...
+// GetRegistry finds the registry extension with @name
 func GetRegistry(name string, config *common.URL) (registry.Registry, error) {
 	if registrys[name] == nil {
 		panic("registry for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/registry_directory.go b/common/extension/registry_directory.go
index 6b92189c4e98b391a90e6e71a68d51a252eede2a..330fc46400daf81047e5c24c1634249e355d74b7 100644
--- a/common/extension/registry_directory.go
+++ b/common/extension/registry_directory.go
@@ -27,12 +27,12 @@ type registryDirectory func(url *common.URL, registry registry.Registry) (cluste
 
 var defaultRegistry registryDirectory
 
-// SetDefaultRegistryDirectory ...
+// SetDefaultRegistryDirectory sets the default registryDirectory
 func SetDefaultRegistryDirectory(v registryDirectory) {
 	defaultRegistry = v
 }
 
-// GetDefaultRegistryDirectory ...
+// GetDefaultRegistryDirectory finds the registryDirectory with url and registry
 func GetDefaultRegistryDirectory(config *common.URL, registry registry.Registry) (cluster.Directory, error) {
 	if defaultRegistry == nil {
 		panic("registry directory is not existing, make sure you have import the package.")
diff --git a/common/extension/rest_client.go b/common/extension/rest_client.go
index 514d1fdfd2efb5c291fdb47df4dd69da26fa90b1..9caf8c67df76bb160d5e2c3100f83e2d198b6381 100644
--- a/common/extension/rest_client.go
+++ b/common/extension/rest_client.go
@@ -25,10 +25,12 @@ var (
 	restClients = make(map[string]func(restOptions *client.RestOptions) client.RestClient, 8)
 )
 
+// SetRestClient sets the RestClient with @name
 func SetRestClient(name string, fun func(restOptions *client.RestOptions) client.RestClient) {
 	restClients[name] = fun
 }
 
+// GetNewRestClient finds the RestClient with @name
 func GetNewRestClient(name string, restOptions *client.RestOptions) client.RestClient {
 	if restClients[name] == nil {
 		panic("restClient for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/rest_server.go b/common/extension/rest_server.go
index fa8d435a5c976a4c95b036810fa2916a327a73b9..37a231a57c861ae49aab244eb9fa8b611ae63f6d 100644
--- a/common/extension/rest_server.go
+++ b/common/extension/rest_server.go
@@ -25,10 +25,12 @@ var (
 	restServers = make(map[string]func() server.RestServer, 8)
 )
 
+// SetRestServer sets the RestServer with @name
 func SetRestServer(name string, fun func() server.RestServer) {
 	restServers[name] = fun
 }
 
+// GetNewRestServer finds the RestServer with @name
 func GetNewRestServer(name string) server.RestServer {
 	if restServers[name] == nil {
 		panic("restServer for " + name + " is not existing, make sure you have import the package.")
diff --git a/common/extension/router_factory.go b/common/extension/router_factory.go
index 1339228618def41ccebc8d54cdebb5a623e605fa..21a49d2681b500bf4e4942d1b92e5b23bc7cf6b7 100644
--- a/common/extension/router_factory.go
+++ b/common/extension/router_factory.go
@@ -31,12 +31,12 @@ var (
 	fileRouterFactories   = make(map[string]router.FileRouterFactory)
 )
 
-// SetRouterFactory Set create router factory function by name
+// SetRouterFactory sets create router factory function with @name
 func SetRouterFactory(name string, fun func() router.RouterFactory) {
 	routers[name] = fun
 }
 
-// GetRouterFactory Get create router factory function by name
+// GetRouterFactory gets create router factory function by @name
 func GetRouterFactory(name string) router.RouterFactory {
 	if routers[name] == nil {
 		panic("router_factory for " + name + " is not existing, make sure you have import the package.")
@@ -44,12 +44,12 @@ func GetRouterFactory(name string) router.RouterFactory {
 	return routers[name]()
 }
 
-// GetRouterFactories Get all create router factory function
+// GetRouterFactories gets all create router factory function
 func GetRouterFactories() map[string]func() router.RouterFactory {
 	return routers
 }
 
-// GetFileRouterFactories Get all create file router factory instance
+// GetFileRouterFactories gets all create file router factory instance
 func GetFileRouterFactories() map[string]router.FileRouterFactory {
 	l := len(routers)
 	if l == 0 {
diff --git a/common/extension/service_discovery.go b/common/extension/service_discovery.go
index f820721515d9091c454067cf059bc29664e04808..456b14c83dcab4189ea287f2e9f3329109e538c3 100644
--- a/common/extension/service_discovery.go
+++ b/common/extension/service_discovery.go
@@ -28,7 +28,7 @@ var (
 	discoveryCreatorMap = make(map[string]func(name string) (registry.ServiceDiscovery, error), 4)
 )
 
-// SetServiceDiscovery will store the creator and name
+// SetServiceDiscovery will store the @creator and @name
 // protocol indicate the implementation, like nacos
 // the name like nacos-1...
 func SetServiceDiscovery(protocol string, creator func(name string) (registry.ServiceDiscovery, error)) {
diff --git a/common/extension/tps_limit.go b/common/extension/tps_limit.go
index c72c2b030fc0f391362189bfe18a65582543693a..d25821deee626cb75c94af2257f877c9983023de 100644
--- a/common/extension/tps_limit.go
+++ b/common/extension/tps_limit.go
@@ -26,12 +26,12 @@ var (
 	tpsLimiter       = make(map[string]func() filter.TpsLimiter)
 )
 
-// SetTpsLimiter ...
+// SetTpsLimiter sets the TpsLimiter with @name
 func SetTpsLimiter(name string, creator func() filter.TpsLimiter) {
 	tpsLimiter[name] = creator
 }
 
-// GetTpsLimiter ...
+// GetTpsLimiter finds the TpsLimiter with @name
 func GetTpsLimiter(name string) filter.TpsLimiter {
 	creator, ok := tpsLimiter[name]
 	if !ok {
@@ -41,12 +41,12 @@ func GetTpsLimiter(name string) filter.TpsLimiter {
 	return creator()
 }
 
-// SetTpsLimitStrategy ...
+// SetTpsLimitStrategy sets the TpsLimitStrategyCreator with @name
 func SetTpsLimitStrategy(name string, creator filter.TpsLimitStrategyCreator) {
 	tpsLimitStrategy[name] = creator
 }
 
-// GetTpsLimitStrategyCreator ...
+// GetTpsLimitStrategyCreator finds the TpsLimitStrategyCreator with @name
 func GetTpsLimitStrategyCreator(name string) filter.TpsLimitStrategyCreator {
 	creator, ok := tpsLimitStrategy[name]
 	if !ok {
diff --git a/common/logger/logger.go b/common/logger/logger.go
index 016afe69808f2007541c617f406db64beb511f1c..9bc6a461003d086e8951ebac3d6997774ac69b90 100644
--- a/common/logger/logger.go
+++ b/common/logger/logger.go
@@ -40,13 +40,13 @@ var (
 	logger Logger
 )
 
-// DubboLogger ...
+// nolint
 type DubboLogger struct {
 	Logger
 	dynamicLevel zap.AtomicLevel
 }
 
-// Logger ...
+// Logger is the interface for Logger types
 type Logger interface {
 	Info(args ...interface{})
 	Warn(args ...interface{})
@@ -67,7 +67,7 @@ func init() {
 	}
 }
 
-// InitLog ...
+// InitLog use for init logger by call InitLogger
 func InitLog(logConfFile string) error {
 	if logConfFile == "" {
 		InitLogger(nil)
@@ -96,7 +96,7 @@ func InitLog(logConfFile string) error {
 	return nil
 }
 
-// InitLogger ...
+// InitLogger use for init logger by @conf
 func InitLogger(conf *zap.Config) {
 	var zapLoggerConfig zap.Config
 	if conf == nil {
@@ -125,18 +125,18 @@ func InitLogger(conf *zap.Config) {
 	getty.SetLogger(logger)
 }
 
-// SetLogger ...
+// SetLogger sets logger for dubbo and getty
 func SetLogger(log Logger) {
 	logger = log
 	getty.SetLogger(logger)
 }
 
-// GetLogger ...
+// GetLogger gets the logger
 func GetLogger() Logger {
 	return logger
 }
 
-// SetLoggerLevel ...
+// SetLoggerLevel use for set logger level
 func SetLoggerLevel(level string) bool {
 	if l, ok := logger.(OpsLogger); ok {
 		l.SetLoggerLevel(level)
@@ -145,13 +145,13 @@ func SetLoggerLevel(level string) bool {
 	return false
 }
 
-// OpsLogger ...
+// OpsLogger use for the SetLoggerLevel
 type OpsLogger interface {
 	Logger
 	SetLoggerLevel(level string)
 }
 
-// SetLoggerLevel ...
+// SetLoggerLevel use for set logger level
 func (dl *DubboLogger) SetLoggerLevel(level string) {
 	l := new(zapcore.Level)
 	l.Set(level)
diff --git a/common/logger/logging.go b/common/logger/logging.go
index 36d48ee61e8a4a986abfbaa79f3d361cd81494f4..7a31ece203815287384ade282b2a4f12e11abc2a 100644
--- a/common/logger/logging.go
+++ b/common/logger/logging.go
@@ -17,42 +17,42 @@
 
 package logger
 
-// Info ...
+// Info is info level
 func Info(args ...interface{}) {
 	logger.Info(args...)
 }
 
-// Warn ...
+// Warn is warning level
 func Warn(args ...interface{}) {
 	logger.Warn(args...)
 }
 
-// Error ...
+// Error is error level
 func Error(args ...interface{}) {
 	logger.Error(args...)
 }
 
-// Debug ...
+// Debug is debug level
 func Debug(args ...interface{}) {
 	logger.Debug(args...)
 }
 
-// Infof ...
+// Infof is format info level
 func Infof(fmt string, args ...interface{}) {
 	logger.Infof(fmt, args...)
 }
 
-// Warnf ...
+// Warnf is format warning level
 func Warnf(fmt string, args ...interface{}) {
 	logger.Warnf(fmt, args...)
 }
 
-// Errorf ...
+// Errorf is format error level
 func Errorf(fmt string, args ...interface{}) {
 	logger.Errorf(fmt, args...)
 }
 
-// Debugf ...
+// Debugf is format debug level
 func Debugf(fmt string, args ...interface{}) {
 	logger.Debugf(fmt, args...)
 }
diff --git a/common/node.go b/common/node.go
index 979eee31ef3a63eb21af6c9045aee7f6d784f2ba..4febd78536126c67bdc65fc09d4be47fb869ef5e 100644
--- a/common/node.go
+++ b/common/node.go
@@ -17,7 +17,7 @@
 
 package common
 
-// Node ...
+// Node use for process dubbo node
 type Node interface {
 	GetUrl() URL
 	IsAvailable() bool
diff --git a/common/proxy/proxy.go b/common/proxy/proxy.go
index f98a44873aa33589997c8c14b78b403a668bffe9..abcf87cd9d297769bf8aff6fa07d6a4659091eb6 100644
--- a/common/proxy/proxy.go
+++ b/common/proxy/proxy.go
@@ -25,12 +25,13 @@ import (
 
 import (
 	"github.com/apache/dubbo-go/common"
+	"github.com/apache/dubbo-go/common/constant"
 	"github.com/apache/dubbo-go/common/logger"
 	"github.com/apache/dubbo-go/protocol"
 	invocation_impl "github.com/apache/dubbo-go/protocol/invocation"
 )
 
-// Proxy struct
+// nolint
 type Proxy struct {
 	rpc         common.RPCService
 	invoke      protocol.Invoker
@@ -140,7 +141,7 @@ func (p *Proxy) Implement(v common.RPCService) {
 			}
 
 			// add user setAttachment
-			atm := invCtx.Value("attachment")
+			atm := invCtx.Value(constant.AttachmentKey)
 			if m, ok := atm.(map[string]string); ok {
 				for k, value := range m {
 					inv.SetAttachments(k, value)
@@ -148,6 +149,9 @@ func (p *Proxy) Implement(v common.RPCService) {
 			}
 
 			result := p.invoke.Invoke(invCtx, inv)
+			if len(result.Attachments()) > 0 {
+				invCtx = context.WithValue(invCtx, constant.AttachmentKey, result.Attachments())
+			}
 
 			err = result.Error()
 			logger.Debugf("[makeDubboCallProxy] result: %v, err: %v", result.Result(), err)
@@ -201,12 +205,12 @@ func (p *Proxy) Implement(v common.RPCService) {
 
 }
 
-// Get get rpc service instance.
+// Get gets rpc service instance.
 func (p *Proxy) Get() common.RPCService {
 	return p.rpc
 }
 
-// GetCallback get callback.
+// GetCallback gets callback.
 func (p *Proxy) GetCallback() interface{} {
 	return p.callBack
 }
diff --git a/common/proxy/proxy_factory.go b/common/proxy/proxy_factory.go
index 34fa3fd07eacae95351f302158d7da68165ea5cf..117428cb253e1ad4a4ceee59aa620d7097b41a75 100644
--- a/common/proxy/proxy_factory.go
+++ b/common/proxy/proxy_factory.go
@@ -29,5 +29,5 @@ type ProxyFactory interface {
 	GetInvoker(url common.URL) protocol.Invoker
 }
 
-// Option ...
+// Option will define a function of handling ProxyFactory
 type Option func(ProxyFactory)
diff --git a/common/proxy/proxy_factory/default.go b/common/proxy/proxy_factory/default.go
index 114cfee2363022da5f7957a825a16fc42b8c928f..1bb1e29c5ced78ad9e2e2483b73379c66328050a 100644
--- a/common/proxy/proxy_factory/default.go
+++ b/common/proxy/proxy_factory/default.go
@@ -40,7 +40,7 @@ func init() {
 	extension.SetProxyFactory("default", NewDefaultProxyFactory)
 }
 
-// DefaultProxyFactory ...
+// DefaultProxyFactory is the default proxy factory
 type DefaultProxyFactory struct {
 	//delegate ProxyFactory
 }
@@ -53,17 +53,17 @@ type DefaultProxyFactory struct {
 //	}
 //}
 
-// NewDefaultProxyFactory ...
+// NewDefaultProxyFactory returns a proxy factory instance
 func NewDefaultProxyFactory(options ...proxy.Option) proxy.ProxyFactory {
 	return &DefaultProxyFactory{}
 }
 
-// GetProxy ...
+// GetProxy gets a proxy
 func (factory *DefaultProxyFactory) GetProxy(invoker protocol.Invoker, url *common.URL) *proxy.Proxy {
 	return factory.GetAsyncProxy(invoker, nil, url)
 }
 
-// GetAsyncProxy ...
+// GetAsyncProxy gets a async proxy
 func (factory *DefaultProxyFactory) GetAsyncProxy(invoker protocol.Invoker, callBack interface{}, url *common.URL) *proxy.Proxy {
 	//create proxy
 	attachments := map[string]string{}
@@ -71,19 +71,19 @@ func (factory *DefaultProxyFactory) GetAsyncProxy(invoker protocol.Invoker, call
 	return proxy.NewProxy(invoker, callBack, attachments)
 }
 
-// GetInvoker ...
+// GetInvoker gets a invoker
 func (factory *DefaultProxyFactory) GetInvoker(url common.URL) protocol.Invoker {
 	return &ProxyInvoker{
 		BaseInvoker: *protocol.NewBaseInvoker(url),
 	}
 }
 
-// ProxyInvoker ...
+// ProxyInvoker is a invoker struct
 type ProxyInvoker struct {
 	protocol.BaseInvoker
 }
 
-// Invoke ...
+// Invoke is used to call service method by invocation
 func (pi *ProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result {
 	result := &protocol.RPCResult{}
 	result.SetAttachments(invocation.Attachments())
@@ -113,6 +113,7 @@ func (pi *ProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocati
 
 	in := []reflect.Value{svc.Rcvr()}
 	if method.CtxType() != nil {
+		ctx = context.WithValue(ctx, constant.AttachmentKey, invocation.Attachments())
 		in = append(in, method.SuiteContext(ctx))
 	}
 
diff --git a/common/rpc_service.go b/common/rpc_service.go
index 90ebdaa6dc9acb8c06a0155e77d6b38c481c0a9e..2eeb52bdfbea21825f7702a750cabe73a3a09bf6 100644
--- a/common/rpc_service.go
+++ b/common/rpc_service.go
@@ -35,23 +35,23 @@ import (
 )
 
 // RPCService
-//rpc service interface
+// rpc service interface
 type RPCService interface {
 	// Reference:
 	// rpc service id or reference id
 	Reference() string
 }
 
-//AsyncCallbackService callback interface for async
+// AsyncCallbackService callback interface for async
 type AsyncCallbackService interface {
 	// Callback: callback
 	CallBack(response CallbackResponse)
 }
 
-//CallbackResponse for different protocol
+// CallbackResponse for different protocol
 type CallbackResponse interface{}
 
-//AsyncCallback async callback method
+// AsyncCallback async callback method
 type AsyncCallback func(response CallbackResponse)
 
 // for lowercase func
@@ -87,27 +87,27 @@ type MethodType struct {
 	replyType reflect.Type   // return value, otherwise it is nil
 }
 
-// Method get @m.method.
+// Method gets @m.method.
 func (m *MethodType) Method() reflect.Method {
 	return m.method
 }
 
-// CtxType get @m.ctxType.
+// CtxType gets @m.ctxType.
 func (m *MethodType) CtxType() reflect.Type {
 	return m.ctxType
 }
 
-// ArgsType get @m.argsType.
+// ArgsType gets @m.argsType.
 func (m *MethodType) ArgsType() []reflect.Type {
 	return m.argsType
 }
 
-// ReplyType get @m.replyType.
+// ReplyType gets @m.replyType.
 func (m *MethodType) ReplyType() reflect.Type {
 	return m.replyType
 }
 
-// SuiteContext tranfer @ctx to reflect.Value type or get it from @m.ctxType.
+// SuiteContext tranfers @ctx to reflect.Value type or get it from @m.ctxType.
 func (m *MethodType) SuiteContext(ctx context.Context) reflect.Value {
 	if contextv := reflect.ValueOf(ctx); contextv.IsValid() {
 		return contextv
@@ -127,7 +127,7 @@ type Service struct {
 	methods  map[string]*MethodType
 }
 
-// Method get @s.methods.
+// Method gets @s.methods.
 func (s *Service) Method() map[string]*MethodType {
 	return s.methods
 }
@@ -137,12 +137,12 @@ func (s *Service) Name() string {
 	return s.name
 }
 
-// RcvrType get @s.rcvrType.
+// RcvrType gets @s.rcvrType.
 func (s *Service) RcvrType() reflect.Type {
 	return s.rcvrType
 }
 
-// Rcvr get @s.rcvr.
+// Rcvr gets @s.rcvr.
 func (s *Service) Rcvr() reflect.Value {
 	return s.rcvr
 }
@@ -157,7 +157,7 @@ type serviceMap struct {
 	interfaceMap map[string][]*Service          // interface -> service
 }
 
-// GetService get a service defination by protocol and name
+// GetService gets a service defination by protocol and name
 func (sm *serviceMap) GetService(protocol, name string) *Service {
 	sm.mutex.RLock()
 	defer sm.mutex.RUnlock()
@@ -170,7 +170,7 @@ func (sm *serviceMap) GetService(protocol, name string) *Service {
 	return nil
 }
 
-// GetInterface get an interface defination by interface name
+// GetInterface gets an interface defination by interface name
 func (sm *serviceMap) GetInterface(interfaceName string) []*Service {
 	sm.mutex.RLock()
 	defer sm.mutex.RUnlock()
@@ -180,7 +180,7 @@ func (sm *serviceMap) GetInterface(interfaceName string) []*Service {
 	return nil
 }
 
-// Register register a service by @interfaceName and @protocol
+// Register registers a service by @interfaceName and @protocol
 func (sm *serviceMap) Register(interfaceName, protocol string, rcvr RPCService) (string, error) {
 	if sm.serviceMap[protocol] == nil {
 		sm.serviceMap[protocol] = make(map[string]*Service)
@@ -228,7 +228,7 @@ func (sm *serviceMap) Register(interfaceName, protocol string, rcvr RPCService)
 	return strings.TrimSuffix(methods, ","), nil
 }
 
-// UnRegister cancel a service by @interfaceName, @protocol and @serviceId
+// UnRegister cancels a service by @interfaceName, @protocol and @serviceId
 func (sm *serviceMap) UnRegister(interfaceName, protocol, serviceId string) error {
 	if protocol == "" || serviceId == "" {
 		return perrors.New("protocol or serviceName is nil")
diff --git a/common/url.go b/common/url.go
index a70ac7dc9dd6f415aa458689864604a793c8e256..1cfa47ae28451a6ab6c00029247ba7179b43371a 100644
--- a/common/url.go
+++ b/common/url.go
@@ -18,7 +18,6 @@
 package common
 
 import (
-	"bytes"
 	"encoding/base64"
 	"fmt"
 	"math"
@@ -26,7 +25,6 @@ import (
 	"net/url"
 	"strconv"
 	"strings"
-	"sync"
 )
 
 import (
@@ -40,136 +38,140 @@ import (
 	"github.com/apache/dubbo-go/common/constant"
 )
 
-/////////////////////////////////
+// ///////////////////////////////
 // dubbo role type
-/////////////////////////////////
+// ///////////////////////////////
 
 // role constant
 const (
-	// CONSUMER ...
+	// CONSUMER is consumer role
 	CONSUMER = iota
-	// CONFIGURATOR ...
+	// CONFIGURATOR is configurator role
 	CONFIGURATOR
-	// ROUTER ...
+	// ROUTER is router role
 	ROUTER
-	// PROVIDER ...
+	// PROVIDER is provider role
 	PROVIDER
 )
 
 var (
-	// DubboNodes ...
+	// DubboNodes Dubbo service node
 	DubboNodes = [...]string{"consumers", "configurators", "routers", "providers"}
 	// DubboRole Dubbo service role
 	DubboRole = [...]string{"consumer", "", "routers", "provider"}
 )
 
-// RoleType ...
+// nolint
 type RoleType int
 
 func (t RoleType) String() string {
 	return DubboNodes[t]
 }
 
-// Role ...
+// Role returns role by @RoleType
 func (t RoleType) Role() string {
 	return DubboRole[t]
 }
 
 type baseUrl struct {
-	Protocol string
-	Location string // ip+port
-	Ip       string
-	Port     string
-	//url.Values is not safe map, add to avoid concurrent map read and map write error
-	paramsLock   sync.RWMutex
+	Protocol     string
+	Location     string // ip+port
+	Ip           string
+	Port         string
 	params       url.Values
 	PrimitiveURL string
 }
 
-// URL ...
+// URL is not thread-safe.
+// we fail to define this struct to be immutable object.
+// but, those method which will update the URL, including SetParam, SetParams
+// are only allowed to be invoked in creating URL instance
+// Please keep in mind that this struct is immutable after it has been created and initialized.
 type URL struct {
 	baseUrl
 	Path     string // like  /com.ikurento.dubbo.UserProvider3
 	Username string
 	Password string
 	Methods  []string
-	//special for registry
+	// special for registry
 	SubURL *URL
 }
 
+// Option accepts url
+// Option will define a function of handling URL
 type option func(*URL)
 
-// WithUsername ...
+// WithUsername sets username for url
 func WithUsername(username string) option {
 	return func(url *URL) {
 		url.Username = username
 	}
 }
 
-// WithPassword ...
+// WithPassword sets password for url
 func WithPassword(pwd string) option {
 	return func(url *URL) {
 		url.Password = pwd
 	}
 }
 
-// WithMethods ...
+// WithMethods sets methods for url
 func WithMethods(methods []string) option {
 	return func(url *URL) {
 		url.Methods = methods
 	}
 }
 
-// WithParams ...
+// WithParams sets params for url
 func WithParams(params url.Values) option {
 	return func(url *URL) {
 		url.params = params
 	}
 }
 
-// WithParamsValue ...
+// WithParamsValue sets params field for url
 func WithParamsValue(key, val string) option {
 	return func(url *URL) {
 		url.SetParam(key, val)
 	}
 }
 
-// WithProtocol ...
+// WithProtocol sets protocol for url
 func WithProtocol(proto string) option {
 	return func(url *URL) {
 		url.Protocol = proto
 	}
 }
 
-// WithIp ...
+// WithIp sets ip for url
 func WithIp(ip string) option {
 	return func(url *URL) {
 		url.Ip = ip
 	}
 }
 
-// WithPort ...
+// WithPort sets port for url
 func WithPort(port string) option {
 	return func(url *URL) {
 		url.Port = port
 	}
 }
 
-// WithPath ...
+// WithPath sets path for url
 func WithPath(path string) option {
 	return func(url *URL) {
 		url.Path = "/" + strings.TrimPrefix(path, "/")
 	}
 }
 
-// WithLocation ...
+// WithLocation sets location for url
 func WithLocation(location string) option {
 	return func(url *URL) {
 		url.Location = location
 	}
 }
 
-// WithToken ...
+// WithToken sets token for url
 func WithToken(token string) option {
 	return func(url *URL) {
 		if len(token) > 0 {
@@ -182,7 +184,7 @@ func WithToken(token string) option {
 	}
 }
 
-// NewURLWithOptions ...
+// NewURLWithOptions will create a new url with options
 func NewURLWithOptions(opts ...option) *URL {
 	url := &URL{}
 	for _, opt := range opts {
@@ -212,7 +214,7 @@ func NewURL(urlString string, opts ...option) (URL, error) {
 		return s, perrors.Errorf("url.QueryUnescape(%s),  error{%v}", urlString, err)
 	}
 
-	//rawUrlString = "//" + rawUrlString
+	// rawUrlString = "//" + rawUrlString
 	if strings.Index(rawUrlString, "//") < 0 {
 		t := URL{baseUrl: baseUrl{}}
 		for _, opt := range opts {
@@ -275,7 +277,7 @@ func (c URL) URLEqual(url URL) bool {
 		return false
 	}
 
-	//TODO :may need add interface key any value condition
+	// TODO :may need add interface key any value condition
 	return isMatchCategory(url.GetParam(constant.CATEGORY_KEY, constant.DEFAULT_CATEGORY), c.GetParam(constant.CATEGORY_KEY, constant.DEFAULT_CATEGORY))
 }
 
@@ -292,23 +294,21 @@ func isMatchCategory(category1 string, category2 string) bool {
 }
 
 func (c URL) String() string {
-	var buildString string
+	var buf strings.Builder
 	if len(c.Username) == 0 && len(c.Password) == 0 {
-		buildString = fmt.Sprintf(
+		buf.WriteString(fmt.Sprintf(
 			"%s://%s:%s%s?",
-			c.Protocol, c.Ip, c.Port, c.Path)
+			c.Protocol, c.Ip, c.Port, c.Path))
 	} else {
-		buildString = fmt.Sprintf(
+		buf.WriteString(fmt.Sprintf(
 			"%s://%s:%s@%s:%s%s?",
-			c.Protocol, c.Username, c.Password, c.Ip, c.Port, c.Path)
+			c.Protocol, c.Username, c.Password, c.Ip, c.Port, c.Path))
 	}
-	c.paramsLock.RLock()
-	buildString += c.params.Encode()
-	c.paramsLock.RUnlock()
-	return buildString
+	buf.WriteString(c.params.Encode())
+	return buf.String()
 }
 
-// Key ...
+// Key gets key
 func (c URL) Key() string {
 	buildString := fmt.Sprintf(
 		"%s://%s:%s@%s:%s/?interface=%s&group=%s&version=%s",
@@ -316,13 +316,13 @@ func (c URL) Key() string {
 	return buildString
 }
 
-// ServiceKey get a unique key of a service.
+// ServiceKey gets a unique key of a service.
 func (c URL) ServiceKey() string {
 	intf := c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/"))
 	if intf == "" {
 		return ""
 	}
-	buf := &bytes.Buffer{}
+	var buf strings.Builder
 	group := c.GetParam(constant.GROUP_KEY, "")
 	if group != "" {
 		buf.WriteString(group)
@@ -347,7 +347,7 @@ func (c *URL) ColonSeparatedKey() string {
 	if intf == "" {
 		return ""
 	}
-	buf := &bytes.Buffer{}
+	var buf strings.Builder
 	buf.WriteString(intf)
 	buf.WriteString(":")
 	version := c.GetParam(constant.VERSION_KEY, "")
@@ -362,44 +362,44 @@ func (c *URL) ColonSeparatedKey() string {
 	return buf.String()
 }
 
-// EncodedServiceKey ...
+// EncodedServiceKey encode the service key
 func (c *URL) EncodedServiceKey() string {
 	serviceKey := c.ServiceKey()
 	return strings.Replace(serviceKey, "/", "*", 1)
 }
 
-// Service ...
+// Service gets service
 func (c URL) Service() string {
 	service := c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/"))
 	if service != "" {
 		return service
 	} else if c.SubURL != nil {
 		service = c.GetParam(constant.INTERFACE_KEY, strings.TrimPrefix(c.Path, "/"))
-		if service != "" { //if url.path is "" then return suburl's path, special for registry url
+		if service != "" { // if url.path is "" then return suburl's path, special for registry url
 			return service
 		}
 	}
 	return ""
 }
 
-// AddParam ...
+// AddParam will add the key-value pair
+// Not thread-safe
+// think twice before using it.
 func (c *URL) AddParam(key string, value string) {
-	c.paramsLock.Lock()
 	c.params.Add(key, value)
-	c.paramsLock.Unlock()
 }
 
-// SetParam ...
+// SetParam will put the key-value pair into url
+// it's not thread safe.
+// think twice before you want to use this method
+// usually it should only be invoked when you want to initialized an url
 func (c *URL) SetParam(key string, value string) {
-	c.paramsLock.Lock()
 	c.params.Set(key, value)
-	c.paramsLock.Unlock()
 }
 
-// RangeParams ...
+// RangeParams will iterate the params
+// it's not thread-safe
 func (c *URL) RangeParams(f func(key, value string) bool) {
-	c.paramsLock.RLock()
-	defer c.paramsLock.RUnlock()
 	for k, v := range c.params {
 		if !f(k, v[0]) {
 			break
@@ -407,10 +407,8 @@ func (c *URL) RangeParams(f func(key, value string) bool) {
 	}
 }
 
-// GetParam ...
+// GetParam gets value by key
 func (c URL) GetParam(s string, d string) string {
-	c.paramsLock.RLock()
-	defer c.paramsLock.RUnlock()
 	r := c.params.Get(s)
 	if len(r) == 0 {
 		r = d
@@ -418,21 +416,19 @@ func (c URL) GetParam(s string, d string) string {
 	return r
 }
 
-// GetParams ...
+// GetParams gets values
 func (c URL) GetParams() url.Values {
 	return c.params
 }
 
-// GetParamAndDecoded ...
+// GetParamAndDecoded gets values and decode
 func (c URL) GetParamAndDecoded(key string) (string, error) {
-	c.paramsLock.RLock()
-	defer c.paramsLock.RUnlock()
 	ruleDec, err := base64.URLEncoding.DecodeString(c.GetParam(key, ""))
 	value := string(ruleDec)
 	return value, err
 }
 
-// GetRawParam ...
+// GetRawParam gets raw param
 func (c URL) GetRawParam(key string) string {
 	switch key {
 	case "protocol":
@@ -452,25 +448,25 @@ func (c URL) GetRawParam(key string) string {
 	}
 }
 
-// GetParamBool ...
-func (c URL) GetParamBool(s string, d bool) bool {
-	r, err := strconv.ParseBool(c.GetParam(s, ""))
+// GetParamBool judge whether @key exists or not
+func (c URL) GetParamBool(key string, d bool) bool {
+	r, err := strconv.ParseBool(c.GetParam(key, ""))
 	if err != nil {
 		return d
 	}
 	return r
 }
 
-// GetParamInt ...
-func (c URL) GetParamInt(s string, d int64) int64 {
-	r, err := strconv.Atoi(c.GetParam(s, ""))
+// GetParamInt gets int value by @key
+func (c URL) GetParamInt(key string, d int64) int64 {
+	r, err := strconv.Atoi(c.GetParam(key, ""))
 	if r == 0 || err != nil {
 		return d
 	}
 	return int64(r)
 }
 
-// GetMethodParamInt ...
+// GetMethodParamInt gets int method param
 func (c URL) GetMethodParamInt(method string, key string, d int64) int64 {
 	r, err := strconv.Atoi(c.GetParam("methods."+method+"."+key, ""))
 	if r == 0 || err != nil {
@@ -479,7 +475,7 @@ func (c URL) GetMethodParamInt(method string, key string, d int64) int64 {
 	return int64(r)
 }
 
-// GetMethodParamInt64 ...
+// GetMethodParamInt64 gets int64 method param
 func (c URL) GetMethodParamInt64(method string, key string, d int64) int64 {
 	r := c.GetMethodParamInt(method, key, math.MinInt64)
 	if r == math.MinInt64 {
@@ -488,7 +484,7 @@ func (c URL) GetMethodParamInt64(method string, key string, d int64) int64 {
 	return r
 }
 
-// GetMethodParam ...
+// GetMethodParam gets method param
 func (c URL) GetMethodParam(method string, key string, d string) string {
 	r := c.GetParam("methods."+method+"."+key, "")
 	if r == "" {
@@ -497,23 +493,16 @@ func (c URL) GetMethodParam(method string, key string, d string) string {
 	return r
 }
 
-// GetMethodParamBool ...
+// GetMethodParamBool judge whether @method param exists or not
 func (c URL) GetMethodParamBool(method string, key string, d bool) bool {
 	r := c.GetParamBool("methods."+method+"."+key, d)
 	return r
 }
 
-// RemoveParams ...
-func (c *URL) RemoveParams(set *gxset.HashSet) {
-	c.paramsLock.Lock()
-	defer c.paramsLock.Unlock()
-	for k := range set.Items {
-		s := k.(string)
-		delete(c.params, s)
-	}
-}
-
-// SetParams ...
+// SetParams will put all key-value pair into url.
+// 1. if there already has same key, the value will be override
+// 2. it's not thread safe
+// 3. think twice when you want to invoke this method
 func (c *URL) SetParams(m url.Values) {
 	for k := range m {
 		c.SetParam(k, m.Get(k))
@@ -562,29 +551,35 @@ func (c URL) ToMap() map[string]string {
 
 // configuration  > reference config >service config
 //  in this function we should merge the reference local url config into the service url from registry.
-//TODO configuration merge, in the future , the configuration center's config should merge too.
-
-// MergeUrl ...
+// TODO configuration merge, in the future , the configuration center's config should merge too.
+
+// MergeUrl will merge those two url
+// the result is based on serviceUrl, and the key which si only contained in referenceUrl
+// will be added into result.
+// for example, if serviceUrl contains params (a1->v1, b1->v2) and referenceUrl contains params(a2->v3, b1 -> v4)
+// the params of result will be (a1->v1, b1->v2, a2->v3).
+// You should notice that the value of b1 is v2, not v4.
+// due to URL is not thread-safe, so this method is not thread-safe
 func MergeUrl(serviceUrl *URL, referenceUrl *URL) *URL {
 	mergedUrl := serviceUrl.Clone()
 
-	//iterator the referenceUrl if serviceUrl not have the key ,merge in
+	// iterator the referenceUrl if serviceUrl not have the key ,merge in
 	referenceUrl.RangeParams(func(key, value string) bool {
 		if v := mergedUrl.GetParam(key, ""); len(v) == 0 {
 			mergedUrl.SetParam(key, value)
 		}
 		return true
 	})
-	//loadBalance,cluster,retries strategy config
+	// loadBalance,cluster,retries strategy config
 	methodConfigMergeFcn := mergeNormalParam(mergedUrl, referenceUrl, []string{constant.LOADBALANCE_KEY, constant.CLUSTER_KEY, constant.RETRIES_KEY, constant.TIMEOUT_KEY})
 
-	//remote timestamp
+	// remote timestamp
 	if v := serviceUrl.GetParam(constant.TIMESTAMP_KEY, ""); len(v) > 0 {
 		mergedUrl.SetParam(constant.REMOTE_TIMESTAMP_KEY, v)
 		mergedUrl.SetParam(constant.TIMESTAMP_KEY, referenceUrl.GetParam(constant.TIMESTAMP_KEY, ""))
 	}
 
-	//finally execute methodConfigMergeFcn
+	// finally execute methodConfigMergeFcn
 	for _, method := range referenceUrl.Methods {
 		for _, fcn := range methodConfigMergeFcn {
 			fcn("methods." + method)
@@ -594,7 +589,7 @@ func MergeUrl(serviceUrl *URL, referenceUrl *URL) *URL {
 	return mergedUrl
 }
 
-// Clone ...
+// Clone will copy the url
 func (c *URL) Clone() *URL {
 	newUrl := &URL{}
 	copier.Copy(newUrl, c)
@@ -606,7 +601,20 @@ func (c *URL) Clone() *URL {
 	return newUrl
 }
 
-// Copy url based on the reserved parameters' keys.
+func (c *URL) CloneExceptParams(excludeParams *gxset.HashSet) *URL {
+	newUrl := &URL{}
+	copier.Copy(newUrl, c)
+	newUrl.params = url.Values{}
+	c.RangeParams(func(key, value string) bool {
+		if !excludeParams.Contains(key) {
+			newUrl.SetParam(key, value)
+		}
+		return true
+	})
+	return newUrl
+}
+
+// Copy url based on the reserved parameter's keys.
 func (c *URL) CloneWithParams(reserveParams []string) *URL {
 	params := url.Values{}
 	for _, reserveParam := range reserveParams {
diff --git a/common/yaml/yaml.go b/common/yaml/yaml.go
index 93ebb166144510236aff27a67422a6377ccb5c9f..5edda1b3c7751e8171528d121148b6c3c60fe128 100644
--- a/common/yaml/yaml.go
+++ b/common/yaml/yaml.go
@@ -40,7 +40,7 @@ func LoadYMLConfig(confProFile string) ([]byte, error) {
 	return ioutil.ReadFile(confProFile)
 }
 
-// unmarshalYMLConfig Load yml config byte from file , then unmarshal to object
+// unmarshalYMLConfig Load yml config byte from file, then unmarshal to object
 func UnmarshalYMLConfig(confProFile string, out interface{}) ([]byte, error) {
 	confFileStream, err := LoadYMLConfig(confProFile)
 	if err != nil {
diff --git a/config/base_config_test.go b/config/base_config_test.go
index 4a4b2b06b985971b7a397daa52107fa812fc88e9..f36d7190c379d7d190af3fd2b2314b3b4b10c3f0 100644
--- a/config/base_config_test.go
+++ b/config/base_config_test.go
@@ -21,9 +21,11 @@ import (
 	"reflect"
 	"testing"
 )
+
 import (
 	"github.com/stretchr/testify/assert"
 )
+
 import (
 	"github.com/apache/dubbo-go/common/config"
 	"github.com/apache/dubbo-go/common/extension"
@@ -455,7 +457,6 @@ func Test_refreshProvider(t *testing.T) {
 }
 
 func Test_startConfigCenter(t *testing.T) {
-
 	extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory {
 		return &config_center.MockDynamicConfigurationFactory{}
 	})
@@ -473,21 +474,21 @@ func Test_startConfigCenter(t *testing.T) {
 }
 
 func Test_initializeStruct(t *testing.T) {
-	consumerConfig := &ConsumerConfig{}
+	testConsumerConfig := &ConsumerConfig{}
 	tp := reflect.TypeOf(ConsumerConfig{})
 	v := reflect.New(tp)
 	initializeStruct(tp, v.Elem())
-	fmt.Println(reflect.ValueOf(consumerConfig).Elem().Type().String())
+	fmt.Println(reflect.ValueOf(testConsumerConfig).Elem().Type().String())
 	fmt.Println(v.Elem().Type().String())
-	reflect.ValueOf(consumerConfig).Elem().Set(v.Elem())
+	reflect.ValueOf(testConsumerConfig).Elem().Set(v.Elem())
 
 	assert.Condition(t, func() (success bool) {
-		return consumerConfig.Registry != nil
+		return testConsumerConfig.Registry != nil
 	})
 	assert.Condition(t, func() (success bool) {
-		return consumerConfig.Registries != nil
+		return testConsumerConfig.Registries != nil
 	})
 	assert.Condition(t, func() (success bool) {
-		return consumerConfig.References != nil
+		return testConsumerConfig.References != nil
 	})
 }
diff --git a/config/config_loader.go b/config/config_loader.go
index b79c2e824988e2353b032d3ac1992740d0eca2b9..a4dc62ffbd0decbf83bc8b9f5ff9f0b17718277d 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -276,16 +276,10 @@ func GetApplicationConfig() *ApplicationConfig {
 
 // GetProviderConfig find the provider config
 // if not found, create new one
-// we use double-check to reduce race condition
-// In general, it will be locked 0 or 1 time.
-// So you don't need to worry about the race condition
 func GetProviderConfig() ProviderConfig {
 	if providerConfig == nil {
 		logger.Warnf("providerConfig is nil! we will try to create one")
-		configAccessMutex.Lock()
-		defer configAccessMutex.Unlock()
 		if providerConfig == nil {
-			logger.Warnf("creating empty provider config. You should see this log only once.")
 			return ProviderConfig{}
 		}
 	}
@@ -299,11 +293,7 @@ func GetProviderConfig() ProviderConfig {
 // So you don't need to worry about the race condition
 func GetConsumerConfig() ConsumerConfig {
 	if consumerConfig == nil {
-		logger.Warnf("consumerConfig is nil! we will try to create one")
-		configAccessMutex.Lock()
-		defer configAccessMutex.Unlock()
 		if consumerConfig == nil {
-			logger.Warnf("creating empty consumer config. You should see this log only once.")
 			return ConsumerConfig{}
 		}
 	}
diff --git a/config/consumer_config.go b/config/consumer_config.go
index 76476511fbf74a5e973d59e560f65cab978d4527..bee9b1e3fcf6e9d95a285c8613bb9c8f4c6c858b 100644
--- a/config/consumer_config.go
+++ b/config/consumer_config.go
@@ -126,7 +126,7 @@ func configCenterRefreshConsumer() error {
 	var err error
 	if consumerConfig.ConfigCenterConfig != nil {
 		consumerConfig.SetFatherConfig(consumerConfig)
-		if err := consumerConfig.startConfigCenter(); err != nil {
+		if err = consumerConfig.startConfigCenter(); err != nil {
 			return perrors.Errorf("start config center error , error message is {%v}", perrors.WithStack(err))
 		}
 		consumerConfig.fresh()
@@ -141,6 +141,5 @@ func configCenterRefreshConsumer() error {
 			return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
 		}
 	}
-
 	return nil
 }
diff --git a/config/metadata_report_config.go b/config/metadata_report_config.go
index caf7c55c28a02cdfe1afcefa7861770b81944c92..66b88d5e9acb7c7f737104c53fe3a04982b92d9b 100644
--- a/config/metadata_report_config.go
+++ b/config/metadata_report_config.go
@@ -104,7 +104,7 @@ func startMetadataReport(metadataType string, metadataReportConfig *MetadataRepo
 	if url, err := metadataReportConfig.ToUrl(); err == nil {
 		instance.GetMetadataReportInstance(url)
 	} else {
-		return perrors.New("MetadataConfig is invalid!")
+		return perrors.Wrap(err, "Start MetadataReport failed.")
 	}
 
 	return nil
diff --git a/config/service_config.go b/config/service_config.go
index d233e2b8a55facd2ca62f86a7af9f5d6e7e309d5..2b1e5a1a3f1e708831f8f969706088d2db0512a5 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -170,9 +170,9 @@ func (c *ServiceConfig) Export() error {
 		// registry the service reflect
 		methods, err := common.ServiceMap.Register(c.InterfaceName, proto.Name, c.rpcService)
 		if err != nil {
-			err := perrors.Errorf("The service %v  export the protocol %v error! Error message is %v .", c.InterfaceName, proto.Name, err.Error())
-			logger.Errorf(err.Error())
-			return err
+			formatErr := perrors.Errorf("The service %v  export the protocol %v error! Error message is %v .", c.InterfaceName, proto.Name, err.Error())
+			logger.Errorf(formatErr.Error())
+			return formatErr
 		}
 
 		port := proto.Port
diff --git a/config_center/apollo/listener.go b/config_center/apollo/listener.go
index fb257a4828aed077f61568685ee7823e9c215cf9..1cf65ed22ba0a1f765af66191ed19a04f81b0fe6 100644
--- a/config_center/apollo/listener.go
+++ b/config_center/apollo/listener.go
@@ -29,7 +29,7 @@ type apolloListener struct {
 	listeners map[config_center.ConfigurationListener]struct{}
 }
 
-// NewApolloListener ...
+// NewApolloListener creates a new apolloListener
 func NewApolloListener() *apolloListener {
 	return &apolloListener{
 		listeners: make(map[config_center.ConfigurationListener]struct{}, 0),
@@ -49,7 +49,7 @@ func (a *apolloListener) OnChange(changeEvent *agollo.ChangeEvent) {
 	}
 }
 
-// AddListener ...
+// AddListener adds a listener for apollo
 func (a *apolloListener) AddListener(l config_center.ConfigurationListener) {
 	if _, ok := a.listeners[l]; !ok {
 		a.listeners[l] = struct{}{}
@@ -57,7 +57,7 @@ func (a *apolloListener) AddListener(l config_center.ConfigurationListener) {
 	}
 }
 
-// RemoveListener ...
+// RemoveListener removes listeners of apollo
 func (a *apolloListener) RemoveListener(l config_center.ConfigurationListener) {
 	delete(a.listeners, l)
 }
diff --git a/config_center/configuration_listener.go b/config_center/configuration_listener.go
index e70e4f68075c51c33f1110ef44a7b703e36fb78d..541cc09286bb83fa5b66db3745e45ad0a9df5e2f 100644
--- a/config_center/configuration_listener.go
+++ b/config_center/configuration_listener.go
@@ -25,12 +25,12 @@ import (
 	"github.com/apache/dubbo-go/remoting"
 )
 
-// ConfigurationListener ...
+// ConfigurationListener for changing listener's event
 type ConfigurationListener interface {
 	Process(*ConfigChangeEvent)
 }
 
-// ConfigChangeEvent ...
+// ConfigChangeEvent for changing listener's event
 type ConfigChangeEvent struct {
 	Key        string
 	Value      interface{}
diff --git a/config_center/configurator.go b/config_center/configurator.go
index ffa9034e05c4c3d4cc254886e2ed19576f155dec..9db4804365689d8eb357965973a2916e86383cf8 100644
--- a/config_center/configurator.go
+++ b/config_center/configurator.go
@@ -21,7 +21,7 @@ import (
 	"github.com/apache/dubbo-go/common"
 )
 
-// Configurator ...
+// Configurator supports GetUrl and constructor
 type Configurator interface {
 	GetUrl() *common.URL
 	Configure(url *common.URL)
diff --git a/config_center/configurator/mock.go b/config_center/configurator/mock.go
index d294b9195db9cfe60056bc29ec26816f740ea396..7ec7179634cfd967cd27e85ed248e2075c387cb5 100644
--- a/config_center/configurator/mock.go
+++ b/config_center/configurator/mock.go
@@ -23,7 +23,7 @@ import (
 	"github.com/apache/dubbo-go/config_center"
 )
 
-// NewMockConfigurator ...
+// NewMockConfigurator creates a new mockConfigurator
 func NewMockConfigurator(url *common.URL) config_center.Configurator {
 	return &mockConfigurator{configuratorUrl: url}
 }
@@ -32,12 +32,12 @@ type mockConfigurator struct {
 	configuratorUrl *common.URL
 }
 
-// GetUrl ...
+// GetUrl gets a configuratorUrl
 func (c *mockConfigurator) GetUrl() *common.URL {
 	return c.configuratorUrl
 }
 
-// Configure ...
+// Configure sets up param CLUSTER_KEY and cluster for url
 func (c *mockConfigurator) Configure(url *common.URL) {
 	if cluster := c.GetUrl().GetParam(constant.CLUSTER_KEY, ""); cluster != "" {
 		url.SetParam(constant.CLUSTER_KEY, cluster)
diff --git a/config_center/configurator/override.go b/config_center/configurator/override.go
index 18415bee3a28b37ffc2f3f73cc7309b685de5408..ebd3dc601b2821f3f4e1e4405720e4ebc55b607e 100644
--- a/config_center/configurator/override.go
+++ b/config_center/configurator/override.go
@@ -50,12 +50,12 @@ func (c *overrideConfigurator) GetUrl() *common.URL {
 }
 
 func (c *overrideConfigurator) Configure(url *common.URL) {
-	//remove configuratorUrl some param that can not be configured
+	// remove configuratorUrl some param that can not be configured
 	if c.configuratorUrl.GetParam(constant.ENABLED_KEY, "true") == "false" || len(c.configuratorUrl.Location) == 0 {
 		return
 	}
 
-	//branch for version 2.7.x
+	// branch for version 2.7.x
 	apiVersion := c.configuratorUrl.GetParam(constant.CONFIG_VERSION_KEY, "")
 	if len(apiVersion) != 0 {
 		currentSide := url.GetParam(constant.SIDE_KEY, "")
@@ -67,12 +67,12 @@ func (c *overrideConfigurator) Configure(url *common.URL) {
 			c.configureIfMatch(url.Ip, url)
 		}
 	} else {
-		//branch for version 2.6.x and less
+		// branch for version 2.6.x and less
 		c.configureDeprecated(url)
 	}
 }
 
-//translate from java, compatible rules in java
+// configureIfMatch translate from java, compatible rules in java
 func (c *overrideConfigurator) configureIfMatch(host string, url *common.URL) {
 	if constant.ANYHOST_VALUE == c.configuratorUrl.Ip || host == c.configuratorUrl.Ip {
 		providers := c.configuratorUrl.GetParam(constant.OVERRIDE_PROVIDERS_KEY, "")
@@ -105,8 +105,7 @@ func (c *overrideConfigurator) configureIfMatch(host string, url *common.URL) {
 				if returnUrl {
 					return
 				}
-				configUrl := c.configuratorUrl.Clone()
-				configUrl.RemoveParams(conditionKeys)
+				configUrl := c.configuratorUrl.CloneExceptParams(conditionKeys)
 				url.SetParams(configUrl.GetParams())
 			}
 		}
diff --git a/config_center/dynamic_configuration.go b/config_center/dynamic_configuration.go
index 9013d7140e757520f2e8f048ce53a5ac2a13f982..540febc9d38e164afcc62538478df140b7d671c7 100644
--- a/config_center/dynamic_configuration.go
+++ b/config_center/dynamic_configuration.go
@@ -40,7 +40,7 @@ const (
 	DEFAULT_CONFIG_TIMEOUT = "10s"
 )
 
-// DynamicConfiguration ...
+// DynamicConfiguration for modify listener and get properties file
 type DynamicConfiguration interface {
 	Parser() parser.ConfigurationParser
 	SetParser(parser.ConfigurationParser)
@@ -71,14 +71,14 @@ type Options struct {
 // Option ...
 type Option func(*Options)
 
-// WithGroup ...
+// WithGroup assigns group to opt.Group
 func WithGroup(group string) Option {
 	return func(opt *Options) {
 		opt.Group = group
 	}
 }
 
-// WithTimeout ...
+// WithTimeout assigns time to opt.Timeout
 func WithTimeout(time time.Duration) Option {
 	return func(opt *Options) {
 		opt.Timeout = time
diff --git a/config_center/dynamic_configuration_factory.go b/config_center/dynamic_configuration_factory.go
index 9f9b13227f6623a02b0261c46d8d1e43624005f8..46faf864443b7f8780584213b758f26395224956 100644
--- a/config_center/dynamic_configuration_factory.go
+++ b/config_center/dynamic_configuration_factory.go
@@ -21,7 +21,7 @@ import (
 	"github.com/apache/dubbo-go/common"
 )
 
-// DynamicConfigurationFactory ...
+// DynamicConfigurationFactory gets the DynamicConfiguration
 type DynamicConfigurationFactory interface {
 	GetDynamicConfiguration(*common.URL) (DynamicConfiguration, error)
 }
diff --git a/config_center/mock_dynamic_config.go b/config_center/mock_dynamic_config.go
index 59c788b65bce2a4773975ea1a96a314649781832..9cfb9e6078be60fbe2072e8e293143e8b111df58 100644
--- a/config_center/mock_dynamic_config.go
+++ b/config_center/mock_dynamic_config.go
@@ -43,7 +43,7 @@ var (
 	dynamicConfiguration *MockDynamicConfiguration
 )
 
-// GetDynamicConfiguration ...
+// GetDynamicConfiguration returns a DynamicConfiguration
 func (f *MockDynamicConfigurationFactory) GetDynamicConfiguration(_ *common.URL) (DynamicConfiguration, error) {
 	var err error
 	once.Do(func() {
@@ -99,16 +99,16 @@ type MockDynamicConfiguration struct {
 	listener map[string]ConfigurationListener
 }
 
-// AddListener ...
+// AddListener adds a listener for MockDynamicConfiguration
 func (c *MockDynamicConfiguration) AddListener(key string, listener ConfigurationListener, _ ...Option) {
 	c.listener[key] = listener
 }
 
-// RemoveListener ...
+// RemoveListener removes the listener for MockDynamicConfiguration
 func (c *MockDynamicConfiguration) RemoveListener(_ string, _ ConfigurationListener, _ ...Option) {
 }
 
-// GetConfig ...
+// GetConfig returns content of MockDynamicConfiguration
 func (c *MockDynamicConfiguration) GetConfig(_ string, _ ...Option) (string, error) {
 
 	return c.content, nil
@@ -119,17 +119,17 @@ func (c *MockDynamicConfiguration) GetConfigs(key string, opts ...Option) (strin
 	return c.GetConfig(key, opts...)
 }
 
-// Parser ...
+// Parser returns a parser of MockDynamicConfiguration
 func (c *MockDynamicConfiguration) Parser() parser.ConfigurationParser {
 	return c.parser
 }
 
-// SetParser ...
+// SetParser sets parser of MockDynamicConfiguration
 func (c *MockDynamicConfiguration) SetParser(p parser.ConfigurationParser) {
 	c.parser = p
 }
 
-// GetProperties ...
+// GetProperties gets content of MockDynamicConfiguration
 func (c *MockDynamicConfiguration) GetProperties(_ string, _ ...Option) (string, error) {
 	return c.content, nil
 }
@@ -139,7 +139,7 @@ func (c *MockDynamicConfiguration) GetInternalProperty(key string, opts ...Optio
 	return c.GetProperties(key, opts...)
 }
 
-// GetRule ...
+// GetRule gets properties of MockDynamicConfiguration
 func (c *MockDynamicConfiguration) GetRule(key string, opts ...Option) (string, error) {
 	return c.GetProperties(key, opts...)
 }
diff --git a/config_center/parser/configuration_parser.go b/config_center/parser/configuration_parser.go
index f33b4ba866da69e1d23b493f42152bbb0f437878..6fbdc27d4339150bfec624f7dc5ea0f6a608d7a7 100644
--- a/config_center/parser/configuration_parser.go
+++ b/config_center/parser/configuration_parser.go
@@ -47,7 +47,7 @@ type ConfigurationParser interface {
 	ParseToUrls(content string) ([]*common.URL, error)
 }
 
-// DefaultConfigurationParser for support properties file in config center
+// DefaultConfigurationParser for supporting properties file in config center
 type DefaultConfigurationParser struct{}
 
 // ConfiguratorConfig ...
@@ -71,7 +71,7 @@ type ConfigItem struct {
 	Side              string            `yaml:"side"`
 }
 
-// Parse ...
+// Parse load content
 func (parser *DefaultConfigurationParser) Parse(content string) (map[string]string, error) {
 	pps, err := properties.LoadString(content)
 	if err != nil {
diff --git a/config_center/zookeeper/listener.go b/config_center/zookeeper/listener.go
index 122dfaf4f268a706151de6acdaa78bb46e59f8fb..747c4be352add3f549eaf02e83da6442a8a84c6a 100644
--- a/config_center/zookeeper/listener.go
+++ b/config_center/zookeeper/listener.go
@@ -33,12 +33,12 @@ type CacheListener struct {
 	rootPath     string
 }
 
-// NewCacheListener ...
+// NewCacheListener creates a new CacheListener
 func NewCacheListener(rootPath string) *CacheListener {
 	return &CacheListener{rootPath: rootPath}
 }
 
-// AddListener ...
+// AddListener will add a listener if loaded
 func (l *CacheListener) AddListener(key string, listener config_center.ConfigurationListener) {
 
 	// reference from https://stackoverflow.com/questions/34018908/golang-why-dont-we-have-a-set-datastructure
@@ -50,7 +50,7 @@ func (l *CacheListener) AddListener(key string, listener config_center.Configura
 	}
 }
 
-// RemoveListener ...
+// RemoveListener will delete a listener if loaded
 func (l *CacheListener) RemoveListener(key string, listener config_center.ConfigurationListener) {
 	listeners, loaded := l.keyListeners.Load(key)
 	if loaded {
@@ -58,7 +58,7 @@ func (l *CacheListener) RemoveListener(key string, listener config_center.Config
 	}
 }
 
-// DataChange ...
+// DataChange changes all listeners' event
 func (l *CacheListener) DataChange(event remoting.Event) bool {
 	if event.Content == "" {
 		//meanings new node
diff --git a/filter/filter_impl/hystrix_filter.go b/filter/filter_impl/hystrix_filter.go
index 9fd97b57b677c9aa8ec492151df9aace6dc78b62..4c872bed3e7fef8eca47f51422525a4918d6c1d8 100644
--- a/filter/filter_impl/hystrix_filter.go
+++ b/filter/filter_impl/hystrix_filter.go
@@ -124,7 +124,7 @@ func (hf *HystrixFilter) Invoke(ctx context.Context, invoker protocol.Invoker, i
 	_, _, err := hystrix.GetCircuit(cmdName)
 	configLoadMutex.RUnlock()
 	if err != nil {
-		logger.Errorf("[Hystrix Filter]Errors occurred getting circuit for %s , will invoke without hystrix, error is: ", cmdName, err)
+		logger.Errorf("[Hystrix Filter]Errors occurred getting circuit for %s , will invoke without hystrix, error is: %+v", cmdName, err)
 		return invoker.Invoke(ctx, invocation)
 	}
 	logger.Infof("[Hystrix Filter]Using hystrix filter: %s", cmdName)
diff --git a/filter/filter_impl/token_filter_test.go b/filter/filter_impl/token_filter_test.go
index d7a7f20a5d7648f6ee18fd26f041acb313dd97fe..b8b297e67267640a1c294541afdd4e062bfebb25 100644
--- a/filter/filter_impl/token_filter_test.go
+++ b/filter/filter_impl/token_filter_test.go
@@ -53,10 +53,10 @@ func TestTokenFilter_Invoke(t *testing.T) {
 func TestTokenFilter_InvokeEmptyToken(t *testing.T) {
 	filter := GetTokenFilter()
 
-	url := common.URL{}
+	testUrl := common.URL{}
 	attch := make(map[string]string, 0)
 	attch[constant.TOKEN_KEY] = "ori_key"
-	result := filter.Invoke(context.Background(), protocol.NewBaseInvoker(url), invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+	result := filter.Invoke(context.Background(), protocol.NewBaseInvoker(testUrl), invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
 	assert.Nil(t, result.Error())
 	assert.Nil(t, result.Result())
 }
@@ -64,23 +64,23 @@ func TestTokenFilter_InvokeEmptyToken(t *testing.T) {
 func TestTokenFilter_InvokeEmptyAttach(t *testing.T) {
 	filter := GetTokenFilter()
 
-	url := common.NewURLWithOptions(
+	testUrl := common.NewURLWithOptions(
 		common.WithParams(url.Values{}),
 		common.WithParamsValue(constant.TOKEN_KEY, "ori_key"))
 	attch := make(map[string]string, 0)
-	result := filter.Invoke(context.Background(), protocol.NewBaseInvoker(*url), invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+	result := filter.Invoke(context.Background(), protocol.NewBaseInvoker(*testUrl), invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
 	assert.NotNil(t, result.Error())
 }
 
 func TestTokenFilter_InvokeNotEqual(t *testing.T) {
 	filter := GetTokenFilter()
 
-	url := common.NewURLWithOptions(
+	testUrl := common.NewURLWithOptions(
 		common.WithParams(url.Values{}),
 		common.WithParamsValue(constant.TOKEN_KEY, "ori_key"))
 	attch := make(map[string]string, 0)
 	attch[constant.TOKEN_KEY] = "err_key"
 	result := filter.Invoke(context.Background(),
-		protocol.NewBaseInvoker(*url), invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
+		protocol.NewBaseInvoker(*testUrl), invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, attch))
 	assert.NotNil(t, result.Error())
 }
diff --git a/go.mod b/go.mod
index ba3cf3e2190de476592278c13ba09c9adaaf947d..0fc3599813b1cb96a5988119d27d4596f115e386 100644
--- a/go.mod
+++ b/go.mod
@@ -43,8 +43,7 @@ require (
 	github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
 	github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
 	github.com/zouyx/agollo v0.0.0-20191114083447-dde9fc9f35b8
-	go.etcd.io/bbolt v1.3.3 // indirect
-	go.etcd.io/etcd v3.3.13+incompatible
+	go.etcd.io/bbolt v1.3.4 // indirect
 	go.uber.org/atomic v1.4.0
 	go.uber.org/zap v1.10.0
 	golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
diff --git a/go.sum b/go.sum
index eb84bde1fb26d84ff5a3a3e36ebe178a63cfb4c9..a26694e75f08e37ed963831edbd7700f1f773393 100644
--- a/go.sum
+++ b/go.sum
@@ -509,10 +509,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/zouyx/agollo v0.0.0-20191114083447-dde9fc9f35b8 h1:k8TV7Gz7cpWpOw/dz71fx8cCZdWoPuckHJ/wkJl+meg=
 github.com/zouyx/agollo v0.0.0-20191114083447-dde9fc9f35b8/go.mod h1:S1cAa98KMFv4Sa8SbJ6ZtvOmf0VlgH0QJ1gXI0lBfBY=
-go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
-go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/etcd v3.3.13+incompatible h1:jCejD5EMnlGxFvcGRyEV4VGlENZc7oPQX6o0t7n3xbw=
-go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
+go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
+go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
@@ -563,6 +561,8 @@ golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
 golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
diff --git a/integrate_test.sh b/integrate_test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c9c2f23b5b07f0baf96260d8092e7464d4d15659
--- /dev/null
+++ b/integrate_test.sh
@@ -0,0 +1,66 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+#!/bin/bash
+
+set -e
+set -x
+
+echo 'start integrate-test'
+
+# set root workspace
+ROOT_DIR=$(pwd)
+echo "integrate-test root work-space -> ${ROOT_DIR}"
+
+# show all travis-env
+echo "travis current commit id  -> ${TRAVIS_COMMIT}"
+echo "travis pull request -> ${TRAVIS_PULL_REQUEST}"
+echo "travis pull request branch -> ${TRAVIS_PULL_REQUEST_BRANCH}"
+echo "travis pull request slug -> ${TRAVIS_PULL_REQUEST_SLUG}"
+echo "travis pull request sha -> ${TRAVIS_PULL_REQUEST_SHA}"
+echo "travis pull request repo slug -> ${TRAVIS_REPO_SLUG}"
+
+
+# #start etcd registry  insecure listen in [:]:2379
+# docker run -d --network host k8s.gcr.io/etcd:3.3.10 etcd
+# echo "etcdv3 listen in [:]2379"
+
+# #start consul registry insecure listen in [:]:8500
+# docker run -d --network host consul
+# echo "consul listen in [:]8500"
+
+# #start nacos registry insecure listen in [:]:8848
+# docker run -d --network host nacos/nacos-server:latest
+# echo "ncacos listen in [:]8848"
+
+# default use zk as registry
+#start zookeeper registry insecure listen in [:]:2181
+docker run -d --network host zookeeper
+echo "zookeeper listen in [:]2181"
+
+# build go-server image
+cd ./test/integrate/dubbo/go-server
+docker build . -t  ci-provider --build-arg PR_ORIGIN_REPO=${TRAVIS_PULL_REQUEST_SLUG} --build-arg PR_ORIGIN_COMMITID=${TRAVIS_PULL_REQUEST_SHA}
+cd ${ROOT_DIR}
+docker run -d --network host ci-provider
+
+# build go-client image
+cd ./test/integrate/dubbo/go-client
+docker build . -t  ci-consumer --build-arg PR_ORIGIN_REPO=${TRAVIS_PULL_REQUEST_SLUG} --build-arg PR_ORIGIN_COMMITID=${TRAVIS_PULL_REQUEST_SHA}
+cd ${ROOT_DIR}
+# run provider
+# check consumer status
+docker run -it --network host ci-consumer
diff --git a/metadata/report/delegate/delegate_report.go b/metadata/report/delegate/delegate_report.go
index 4bc781a7f54a19c789dd8a0f7bd2f13bf09fc353..1ab7e4e7c32c0e987a56069c5a5e25653423466a 100644
--- a/metadata/report/delegate/delegate_report.go
+++ b/metadata/report/delegate/delegate_report.go
@@ -130,7 +130,7 @@ func NewMetadataReport() (*MetadataReport, error) {
 		scheduler := gocron.NewScheduler(time.UTC)
 		_, err := scheduler.Every(1).Day().Do(
 			func() {
-				logger.Info("start to publish all metadata in metadata report %s.", url.String())
+				logger.Infof("start to publish all metadata in metadata report %s.", url.String())
 				bmr.allMetadataReportsLock.RLock()
 				bmr.doHandlerMetadataCollection(bmr.allMetadataReports)
 				bmr.allMetadataReportsLock.RUnlock()
diff --git a/protocol/dubbo/listener.go b/protocol/dubbo/listener.go
index 1f4cc0068efb5688b545fa35b784b4fb2e923dc7..f57d89d1a716d2a6056e0e4a581926dc237934e4 100644
--- a/protocol/dubbo/listener.go
+++ b/protocol/dubbo/listener.go
@@ -143,7 +143,7 @@ func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) {
 
 // OnCron ...
 func (h *RpcClientHandler) OnCron(session getty.Session) {
-	rpcSession, err := h.conn.getClientRpcSession(session)
+	clientRpcSession, err := h.conn.getClientRpcSession(session)
 	if err != nil {
 		logger.Errorf("client.getClientSession(session{%s}) = error{%v}",
 			session.Stat(), perrors.WithStack(err))
@@ -151,7 +151,7 @@ func (h *RpcClientHandler) OnCron(session getty.Session) {
 	}
 	if h.conn.pool.rpcClient.conf.sessionTimeout.Nanoseconds() < time.Since(session.GetActive()).Nanoseconds() {
 		logger.Warnf("session{%s} timeout{%s}, reqNum{%d}",
-			session.Stat(), time.Since(session.GetActive()).String(), rpcSession.reqNum)
+			session.Stat(), time.Since(session.GetActive()).String(), clientRpcSession.reqNum)
 		h.conn.removeSession(session) // -> h.conn.close() -> h.conn.pool.remove(h.conn)
 		return
 	}
diff --git a/protocol/dubbo/pool.go b/protocol/dubbo/pool.go
index 918514c2676cfc69336a9f53e6d16d7f23cf7dca..f0bd09ba7c3392dd1dbe10306c7c70cc0eab8ccb 100644
--- a/protocol/dubbo/pool.go
+++ b/protocol/dubbo/pool.go
@@ -219,25 +219,25 @@ func (c *gettyRPCClient) updateSession(session getty.Session) {
 
 func (c *gettyRPCClient) getClientRpcSession(session getty.Session) (rpcSession, error) {
 	var (
-		err        error
-		rpcSession rpcSession
+		err              error
+		rpcClientSession rpcSession
 	)
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	if c.sessions == nil {
-		return rpcSession, errClientClosed
+		return rpcClientSession, errClientClosed
 	}
 
 	err = errSessionNotExist
 	for _, s := range c.sessions {
 		if s.session == session {
-			rpcSession = *s
+			rpcClientSession = *s
 			err = nil
 			break
 		}
 	}
 
-	return rpcSession, perrors.WithStack(err)
+	return rpcClientSession, perrors.WithStack(err)
 }
 
 func (c *gettyRPCClient) isAvailable() bool {
@@ -319,7 +319,8 @@ func (p *gettyRPCClientPool) getGettyRpcClient(protocol, addr string) (*gettyRPC
 	conn, err := p.get()
 	if err == nil && conn == nil {
 		// create new conn
-		rpcClientConn, err := newGettyRPCClientConn(p, protocol, addr)
+		var rpcClientConn *gettyRPCClient
+		rpcClientConn, err = newGettyRPCClientConn(p, protocol, addr)
 		return rpcClientConn, perrors.WithStack(err)
 	}
 	return conn, perrors.WithStack(err)
diff --git a/protocol/invocation.go b/protocol/invocation.go
index f32f2c3449ac063ecb89952bd4653312a07a3df4..eedf5f0253c2b76a3e0e1b52a00124d648351cfc 100644
--- a/protocol/invocation.go
+++ b/protocol/invocation.go
@@ -30,5 +30,8 @@ type Invocation interface {
 	Reply() interface{}
 	Attachments() map[string]string
 	AttachmentsByKey(string, string) string
+	// Refer to dubbo 2.7.6.  It is different from attachment. It is used in internal process.
+	Attributes() map[string]interface{}
+	AttributeByKey(string, interface{}) interface{}
 	Invoker() Invoker
 }
diff --git a/protocol/invocation/rpcinvocation.go b/protocol/invocation/rpcinvocation.go
index b207fd0b0cc4eb7de8409a8c46c6fc9ef0baa5c7..68fe7b92042e6b4cf4a253c9ce354184f79af558 100644
--- a/protocol/invocation/rpcinvocation.go
+++ b/protocol/invocation/rpcinvocation.go
@@ -40,8 +40,10 @@ type RPCInvocation struct {
 	reply           interface{}
 	callBack        interface{}
 	attachments     map[string]string
-	invoker         protocol.Invoker
-	lock            sync.RWMutex
+	// Refer to dubbo 2.7.6.  It is different from attachment. It is used in internal process.
+	attributes map[string]interface{}
+	invoker    protocol.Invoker
+	lock       sync.RWMutex
 }
 
 // NewRPCInvocation ...
@@ -50,6 +52,7 @@ func NewRPCInvocation(methodName string, arguments []interface{}, attachments ma
 		methodName:  methodName,
 		arguments:   arguments,
 		attachments: attachments,
+		attributes:  make(map[string]interface{}, 8),
 	}
 }
 
@@ -59,6 +62,9 @@ func NewRPCInvocationWithOptions(opts ...option) *RPCInvocation {
 	for _, opt := range opts {
 		opt(invo)
 	}
+	if invo.attributes == nil {
+		invo.attributes = make(map[string]interface{})
+	}
 	return invo
 }
 
@@ -111,6 +117,22 @@ func (r *RPCInvocation) AttachmentsByKey(key string, defaultValue string) string
 	return defaultValue
 }
 
+// get attributes
+func (r *RPCInvocation) Attributes() map[string]interface{} {
+	return r.attributes
+}
+
+// get attribute by key. If it is not exist, it will return default value
+func (r *RPCInvocation) AttributeByKey(key string, defaultValue interface{}) interface{} {
+	r.lock.RLock()
+	defer r.lock.RUnlock()
+	value, ok := r.attributes[key]
+	if ok {
+		return value
+	}
+	return defaultValue
+}
+
 // SetAttachments ...
 func (r *RPCInvocation) SetAttachments(key string, value string) {
 	r.lock.Lock()
@@ -121,6 +143,13 @@ func (r *RPCInvocation) SetAttachments(key string, value string) {
 	r.attachments[key] = value
 }
 
+// SetAttribute. If Attributes is nil, it will be inited.
+func (r *RPCInvocation) SetAttribute(key string, value interface{}) {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+	r.attributes[key] = value
+}
+
 // Invoker ...
 func (r *RPCInvocation) Invoker() protocol.Invoker {
 	return r.invoker
diff --git a/protocol/jsonrpc/http.go b/protocol/jsonrpc/http.go
index ba7197dbc857c2ed7acda1a9f246a5b826e86915..70b3abd24f9451b4fa81d02eb9390823e6714470 100644
--- a/protocol/jsonrpc/http.go
+++ b/protocol/jsonrpc/http.go
@@ -172,7 +172,7 @@ func (c *HTTPClient) Do(addr, path string, httpHeader http.Header, body []byte)
 	httpReq.Close = true
 
 	reqBuf := bytes.NewBuffer(make([]byte, 0))
-	if err := httpReq.Write(reqBuf); err != nil {
+	if err = httpReq.Write(reqBuf); err != nil {
 		return nil, perrors.WithStack(err)
 	}
 
@@ -191,7 +191,7 @@ func (c *HTTPClient) Do(addr, path string, httpHeader http.Header, body []byte)
 	}
 	setNetConnTimeout(tcpConn, c.options.HTTPTimeout)
 
-	if _, err := reqBuf.WriteTo(tcpConn); err != nil {
+	if _, err = reqBuf.WriteTo(tcpConn); err != nil {
 		return nil, perrors.WithStack(err)
 	}
 
diff --git a/protocol/jsonrpc/json.go b/protocol/jsonrpc/json.go
index d1c2a858b4e4223ac32fc1160b56f6ee1862c8ce..3176e193816bf95882539374672eeed7f9cddc44 100644
--- a/protocol/jsonrpc/json.go
+++ b/protocol/jsonrpc/json.go
@@ -67,8 +67,8 @@ type Error struct {
 func (e *Error) Error() string {
 	buf, err := json.Marshal(e)
 	if err != nil {
-		msg, err := json.Marshal(err.Error())
-		if err != nil {
+		msg, retryErr := json.Marshal(err.Error())
+		if retryErr != nil {
 			msg = []byte("jsonrpc2.Error: json.Marshal failed")
 		}
 		return fmt.Sprintf(`{"code":%d,"message":%s}`, -32001, string(msg))
@@ -133,7 +133,7 @@ func (c *jsonClientCodec) Write(d *CodecData) ([]byte, error) {
 			}
 		case reflect.Array, reflect.Struct:
 		case reflect.Ptr:
-			switch k := reflect.TypeOf(param).Elem().Kind(); k {
+			switch ptrK := reflect.TypeOf(param).Elem().Kind(); ptrK {
 			case reflect.Map:
 				if reflect.TypeOf(param).Elem().Key().Kind() == reflect.String {
 					if reflect.ValueOf(param).Elem().IsNil() {
@@ -146,7 +146,7 @@ func (c *jsonClientCodec) Write(d *CodecData) ([]byte, error) {
 				}
 			case reflect.Array, reflect.Struct:
 			default:
-				return nil, perrors.New("unsupported param type: Ptr to " + k.String())
+				return nil, perrors.New("unsupported param type: Ptr to " + ptrK.String())
 			}
 		default:
 			return nil, perrors.New("unsupported param type: " + k.String())
diff --git a/protocol/jsonrpc/jsonrpc_protocol.go b/protocol/jsonrpc/jsonrpc_protocol.go
index bed7099ab60a6c05c3799f993c0bb348a4b00f02..64f708652d8cb4bf2a6d53488c9fe17e64f10ad0 100644
--- a/protocol/jsonrpc/jsonrpc_protocol.go
+++ b/protocol/jsonrpc/jsonrpc_protocol.go
@@ -109,8 +109,8 @@ func (jp *JsonrpcProtocol) Destroy() {
 func (jp *JsonrpcProtocol) openServer(url common.URL) {
 	_, ok := jp.serverMap[url.Location]
 	if !ok {
-		_, ok := jp.ExporterMap().Load(strings.TrimPrefix(url.Path, "/"))
-		if !ok {
+		_, loadOk := jp.ExporterMap().Load(strings.TrimPrefix(url.Path, "/"))
+		if !loadOk {
 			panic("[JsonrpcProtocol]" + url.Key() + "is not existing")
 		}
 
diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go
index 8600f02dad3d32d797613823de0bbe40261d2e71..fcea66632e787083823c1d06ca6c1698c45d5b23 100644
--- a/protocol/jsonrpc/server.go
+++ b/protocol/jsonrpc/server.go
@@ -349,9 +349,9 @@ func serveRequest(ctx context.Context,
 			constant.PATH_KEY:    path,
 			constant.VERSION_KEY: codec.req.Version}))
 		if err := result.Error(); err != nil {
-			rspStream, err := codec.Write(err.Error(), invalidRequest)
-			if err != nil {
-				return perrors.WithStack(err)
+			rspStream, codecErr := codec.Write(err.Error(), invalidRequest)
+			if codecErr != nil {
+				return perrors.WithStack(codecErr)
 			}
 			if errRsp := sendErrorResp(header, rspStream); errRsp != nil {
 				logger.Warnf("Exporter: sendErrorResp(header:%#v, error:%v) = error:%s",
diff --git a/registry/consul/listener.go b/registry/consul/listener.go
index b047a4c08c9f6c809ed3dca8bd0d06ceaa576cae..5fac9ec0f9b6c08620021de9d0b92e3b94773c12 100644
--- a/registry/consul/listener.go
+++ b/registry/consul/listener.go
@@ -142,7 +142,6 @@ func (l *consulListener) run() {
 func (l *consulListener) handler(idx uint64, raw interface{}) {
 	var (
 		service *consul.ServiceEntry
-		event   *registry.ServiceEvent
 		url     common.URL
 		ok      bool
 		err     error
@@ -183,7 +182,7 @@ func (l *consulListener) handler(idx uint64, raw interface{}) {
 	}
 
 	l.urls = newUrls
-	for _, event = range events {
+	for _, event := range events {
 		l.eventCh <- event
 	}
 }
diff --git a/registry/directory/directory.go b/registry/directory/directory.go
index d689bc6237c77fef9eb43412817bf30f6ea863c2..253dc597f9981c61574b8af97119653652d51bbc 100644
--- a/registry/directory/directory.go
+++ b/registry/directory/directory.go
@@ -61,7 +61,7 @@ type RegistryDirectory struct {
 	forbidden                      atomic.Bool
 }
 
-// NewRegistryDirectory ...
+// NewRegistryDirectory will create a new RegistryDirectory
 func NewRegistryDirectory(url *common.URL, registry registry.Registry) (cluster.Directory, error) {
 	if url.SubURL == nil {
 		return nil, perrors.Errorf("url is invalid, suburl can not be nil")
@@ -86,6 +86,7 @@ func (dir *RegistryDirectory) subscribe(url *common.URL) {
 	dir.registry.Subscribe(url, dir)
 }
 
+// Notify monitor changes from registry,and update the cacheServices
 func (dir *RegistryDirectory) Notify(event *registry.ServiceEvent) {
 	go dir.update(event)
 }
@@ -152,9 +153,11 @@ func (dir *RegistryDirectory) refreshInvokers(res *registry.ServiceEvent) {
 }
 
 func (dir *RegistryDirectory) toGroupInvokers() []protocol.Invoker {
-	newInvokersList := []protocol.Invoker{}
+	var (
+		err             error
+		newInvokersList []protocol.Invoker
+	)
 	groupInvokersMap := make(map[string][]protocol.Invoker)
-	groupInvokersList := []protocol.Invoker{}
 
 	dir.cacheInvokersMap.Range(func(key, value interface{}) bool {
 		newInvokersList = append(newInvokersList, value.(protocol.Invoker))
@@ -170,6 +173,7 @@ func (dir *RegistryDirectory) toGroupInvokers() []protocol.Invoker {
 			groupInvokersMap[group] = []protocol.Invoker{invoker}
 		}
 	}
+	groupInvokersList := make([]protocol.Invoker, 0, len(groupInvokersMap))
 	if len(groupInvokersMap) == 1 {
 		// len is 1 it means no group setting ,so do not need cluster again
 		for _, invokers := range groupInvokersMap {
@@ -178,9 +182,13 @@ func (dir *RegistryDirectory) toGroupInvokers() []protocol.Invoker {
 	} else {
 		for _, invokers := range groupInvokersMap {
 			staticDir := directory.NewStaticDirectory(invokers)
-			cluster := extension.GetCluster(dir.GetUrl().SubURL.GetParam(constant.CLUSTER_KEY, constant.DEFAULT_CLUSTER))
-			staticDir.BuildRouterChain(invokers)
-			groupInvokersList = append(groupInvokersList, cluster.Join(staticDir))
+			cst := extension.GetCluster(dir.GetUrl().SubURL.GetParam(constant.CLUSTER_KEY, constant.DEFAULT_CLUSTER))
+			err = staticDir.BuildRouterChain(invokers)
+			if err != nil {
+				logger.Error(err)
+				continue
+			}
+			groupInvokersList = append(groupInvokersList, cst.Join(staticDir))
 		}
 	}
 
@@ -244,6 +252,7 @@ func (dir *RegistryDirectory) List(invocation protocol.Invocation) []protocol.In
 	return routerChain.Route(invokers, dir.cacheOriginUrl, invocation)
 }
 
+// IsAvailable  whether the directory is available
 func (dir *RegistryDirectory) IsAvailable() bool {
 	if !dir.BaseDirectory.IsAvailable() {
 		return dir.BaseDirectory.IsAvailable()
@@ -258,6 +267,7 @@ func (dir *RegistryDirectory) IsAvailable() bool {
 	return false
 }
 
+// Destroy method
 func (dir *RegistryDirectory) Destroy() {
 	// TODO:unregister & unsubscribe
 	dir.BaseDirectory.Destroy(func() {
@@ -297,6 +307,7 @@ func newReferenceConfigurationListener(dir *RegistryDirectory, url *common.URL)
 	return listener
 }
 
+// Process handle events and update Invokers
 func (l *referenceConfigurationListener) Process(event *config_center.ConfigChangeEvent) {
 	l.BaseConfigurationListener.Process(event)
 	l.directory.refreshInvokers(nil)
@@ -322,6 +333,7 @@ func (l *consumerConfigurationListener) addNotifyListener(listener registry.Noti
 	l.listeners = append(l.listeners, listener)
 }
 
+// Process handles events from Configuration Center and update Invokers
 func (l *consumerConfigurationListener) Process(event *config_center.ConfigChangeEvent) {
 	l.BaseConfigurationListener.Process(event)
 	l.directory.refreshInvokers(nil)
diff --git a/registry/directory/directory_test.go b/registry/directory/directory_test.go
index 1e3d611bf7c213894edbcbcedde79a93900572b4..04fae049d49bc2970668dc0ae8360f48da9d49dc 100644
--- a/registry/directory/directory_test.go
+++ b/registry/directory/directory_test.go
@@ -25,6 +25,7 @@ import (
 )
 
 import (
+	"github.com/golang/mock/gomock"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -37,6 +38,7 @@ import (
 	"github.com/apache/dubbo-go/common/extension"
 	"github.com/apache/dubbo-go/config"
 	"github.com/apache/dubbo-go/protocol/invocation"
+	"github.com/apache/dubbo-go/protocol/mock"
 	"github.com/apache/dubbo-go/protocol/protocolwrapper"
 	"github.com/apache/dubbo-go/registry"
 	"github.com/apache/dubbo-go/remoting"
@@ -173,7 +175,21 @@ Loop1:
 			break Loop1
 		}
 	}
+}
 
+func Test_toGroupInvokers(t *testing.T) {
+	registryDirectory, _ := normalRegistryDir()
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+	invoker := mock.NewMockInvoker(ctrl)
+	newUrl, _ := common.NewURL("dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider")
+	invoker.EXPECT().GetUrl().Return(newUrl).AnyTimes()
+
+	registryDirectory.cacheInvokersMap.Store("group1", invoker)
+	registryDirectory.cacheInvokersMap.Store("group2", invoker)
+	registryDirectory.cacheInvokersMap.Store("group1", invoker)
+	groupInvokers := registryDirectory.toGroupInvokers()
+	assert.Len(t, groupInvokers, 2)
 }
 
 func normalRegistryDir(noMockEvent ...bool) (*RegistryDirectory, *registry.MockRegistry) {
diff --git a/registry/etcdv3/listener_test.go b/registry/etcdv3/listener_test.go
index e691ae3cf1204ee97f130764496a7fc5bf67ac42..f27e7ce8ba5ab3515f8290b208b4823872ba48a3 100644
--- a/registry/etcdv3/listener_test.go
+++ b/registry/etcdv3/listener_test.go
@@ -24,9 +24,9 @@ import (
 )
 
 import (
+	"github.com/coreos/etcd/embed"
 	"github.com/dubbogo/getty"
 	"github.com/stretchr/testify/suite"
-	"go.etcd.io/etcd/embed"
 )
 
 import (
diff --git a/registry/kubernetes/listener_test.go b/registry/kubernetes/listener_test.go
index c50b5b670a5491b9813652f7aa46bec18a35a7d7..1c9d8bdd5e0b713d61764163eff3b9fd3d5f320a 100644
--- a/registry/kubernetes/listener_test.go
+++ b/registry/kubernetes/listener_test.go
@@ -191,7 +191,6 @@ type KubernetesRegistryTestSuite struct {
 }
 
 func (s *KubernetesRegistryTestSuite) initRegistry() *kubernetesRegistry {
-
 	t := s.T()
 
 	regurl, err := common.NewURL("registry://127.0.0.1:443", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)))
@@ -204,7 +203,7 @@ func (s *KubernetesRegistryTestSuite) initRegistry() *kubernetesRegistry {
 		out := fake.NewSimpleClientset()
 
 		// mock current pod
-		if _, err := out.CoreV1().Pods(s.currentPod.GetNamespace()).Create(&s.currentPod); err != nil {
+		if _, err = out.CoreV1().Pods(s.currentPod.GetNamespace()).Create(&s.currentPod); err != nil {
 			t.Fatal(err)
 		}
 		return out, nil
diff --git a/registry/kubernetes/registry_test.go b/registry/kubernetes/registry_test.go
index ea6d7663a9ceeab241c7a94a91f94288ab2990fc..a650b189c39b94849dee4fbf7fc292e33e87b829 100644
--- a/registry/kubernetes/registry_test.go
+++ b/registry/kubernetes/registry_test.go
@@ -68,9 +68,9 @@ func (s *KubernetesRegistryTestSuite) TestSubscribe() {
 	time.Sleep(1e9)
 
 	go func() {
-		err := r.Register(url)
-		if err != nil {
-			t.Fatal(err)
+		registerErr := r.Register(url)
+		if registerErr != nil {
+			t.Fatal(registerErr)
 		}
 	}()
 
diff --git a/registry/nacos/registry_test.go b/registry/nacos/registry_test.go
index 7475b455c0dda09da65012465711ece264bb3dd5..d0311b200b27081c60bc97b2307a54774ca977bd 100644
--- a/registry/nacos/registry_test.go
+++ b/registry/nacos/registry_test.go
@@ -42,7 +42,7 @@ func TestNacosRegistry_Register(t *testing.T) {
 	urlMap.Set(constant.INTERFACE_KEY, "com.ikurento.user.UserProvider")
 	urlMap.Set(constant.VERSION_KEY, "1.0.0")
 	urlMap.Set(constant.CLUSTER_KEY, "mock")
-	url, _ := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"}))
+	testUrl, _ := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"}))
 
 	reg, err := newNacosRegistry(&regurl)
 	assert.Nil(t, err)
@@ -50,7 +50,7 @@ func TestNacosRegistry_Register(t *testing.T) {
 		t.Errorf("new nacos registry error:%s \n", err.Error())
 		return
 	}
-	err = reg.Register(url)
+	err = reg.Register(testUrl)
 	assert.Nil(t, err)
 	if err != nil {
 		t.Errorf("register error:%s \n", err.Error())
@@ -72,10 +72,10 @@ func TestNacosRegistry_Subscribe(t *testing.T) {
 	urlMap.Set(constant.VERSION_KEY, "1.0.0")
 	urlMap.Set(constant.CLUSTER_KEY, "mock")
 	urlMap.Set(constant.NACOS_PATH_KEY, "")
-	url, _ := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"}))
+	testUrl, _ := common.NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"}))
 
 	reg, _ := newNacosRegistry(&regurl)
-	err := reg.Register(url)
+	err := reg.Register(testUrl)
 	assert.Nil(t, err)
 	if err != nil {
 		t.Errorf("new nacos registry error:%s \n", err.Error())
@@ -84,7 +84,7 @@ func TestNacosRegistry_Subscribe(t *testing.T) {
 
 	regurl.SetParam(constant.ROLE_KEY, strconv.Itoa(common.CONSUMER))
 	reg2, _ := newNacosRegistry(&regurl)
-	listener, err := reg2.(*nacosRegistry).subscribe(&url)
+	listener, err := reg2.(*nacosRegistry).subscribe(&testUrl)
 	assert.Nil(t, err)
 	if err != nil {
 		t.Errorf("subscribe error:%s \n", err.Error())
diff --git a/registry/protocol/protocol.go b/registry/protocol/protocol.go
index aa8fbcbe7d6eca682892d4627878fe6bfc3756fe..a936db80bf2c3b46ba389142cc40686ed3df17b1 100644
--- a/registry/protocol/protocol.go
+++ b/registry/protocol/protocol.go
@@ -56,8 +56,8 @@ type registryProtocol struct {
 	invokers []protocol.Invoker
 	// Registry  Map<RegistryAddress, Registry>
 	registries *sync.Map
-	//To solve the problem of RMI repeated exposure port conflicts, the services that have been exposed are no longer exposed.
-	//providerurl <--> exporter
+	// To solve the problem of RMI repeated exposure port conflicts, the services that have been exposed are no longer exposed.
+	// providerurl <--> exporter
 	bounds                        *sync.Map
 	overrideListeners             *sync.Map
 	serviceConfigurationListeners *sync.Map
@@ -70,10 +70,8 @@ func init() {
 }
 
 func getCacheKey(url *common.URL) string {
-	newUrl := url.Clone()
 	delKeys := gxset.NewSet("dynamic", "enabled")
-	newUrl.RemoveParams(delKeys)
-	return newUrl.String()
+	return url.CloneExceptParams(delKeys).String()
 }
 
 func newRegistryProtocol() *registryProtocol {
@@ -103,16 +101,14 @@ func getUrlToRegistry(providerUrl *common.URL, registryUrl *common.URL) *common.
 // filterHideKey filter the parameters that do not need to be output in url(Starting with .)
 func filterHideKey(url *common.URL) *common.URL {
 
-	//be careful params maps in url is map type
-	cloneURL := url.Clone()
+	// be careful params maps in url is map type
 	removeSet := gxset.NewSet()
-	for k, _ := range cloneURL.GetParams() {
+	for k, _ := range url.GetParams() {
 		if strings.HasPrefix(k, ".") {
 			removeSet.Add(k)
 		}
 	}
-	cloneURL.RemoveParams(removeSet)
-	return cloneURL
+	return url.CloneExceptParams(removeSet)
 }
 
 func (proto *registryProtocol) initConfigurationListeners() {
@@ -138,7 +134,7 @@ func (proto *registryProtocol) Refer(url common.URL) protocol.Invoker {
 		reg = regI.(registry.Registry)
 	}
 
-	//new registry directory for store service url from registry
+	// new registry directory for store service url from registry
 	directory, err := extension.GetDefaultRegistryDirectory(&registryUrl, reg)
 	if err != nil {
 		logger.Errorf("consumer service %v  create registry directory  error, error message is %s, and will return nil invoker!",
@@ -152,7 +148,7 @@ func (proto *registryProtocol) Refer(url common.URL) protocol.Invoker {
 			serviceUrl.String(), registryUrl.String(), err.Error())
 	}
 
-	//new cluster invoker
+	// new cluster invoker
 	cluster := extension.GetCluster(serviceUrl.GetParam(constant.CLUSTER_KEY, constant.DEFAULT_CLUSTER))
 
 	invoker := cluster.Join(directory)
@@ -217,7 +213,7 @@ func (proto *registryProtocol) reExport(invoker protocol.Invoker, newUrl *common
 		oldExporter.(protocol.Exporter).Unexport()
 		proto.bounds.Delete(key)
 		proto.Export(wrappedNewInvoker)
-		//TODO:  unregister & unsubscribe
+		// TODO:  unregister & unsubscribe
 
 	}
 }
@@ -300,7 +296,7 @@ func isMatched(providerUrl *common.URL, consumerUrl *common.URL) bool {
 	providerGroup := providerUrl.GetParam(constant.GROUP_KEY, "")
 	providerVersion := providerUrl.GetParam(constant.VERSION_KEY, "")
 	providerClassifier := providerUrl.GetParam(constant.CLASSIFIER_KEY, "")
-	//todo: public static boolean isContains(String values, String value) {
+	// todo: public static boolean isContains(String values, String value) {
 	//        return isNotEmpty(values) && isContains(COMMA_SPLIT_PATTERN.split(values), value);
 	//    }
 	return (consumerGroup == constant.ANY_VALUE || consumerGroup == providerGroup ||
@@ -353,9 +349,9 @@ func (proto *registryProtocol) Destroy() {
 }
 
 func getRegistryUrl(invoker protocol.Invoker) *common.URL {
-	//here add * for return a new url
+	// here add * for return a new url
 	url := invoker.GetUrl()
-	//if the protocol == registry ,set protocol the registry value in url.params
+	// if the protocol == registry ,set protocol the registry value in url.params
 	if url.Protocol == constant.REGISTRY_PROTOCOL {
 		protocol := url.GetParam(constant.REGISTRY_KEY, "")
 		url.Protocol = protocol
@@ -365,7 +361,7 @@ func getRegistryUrl(invoker protocol.Invoker) *common.URL {
 
 func getProviderUrl(invoker protocol.Invoker) *common.URL {
 	url := invoker.GetUrl()
-	//be careful params maps in url is map type
+	// be careful params maps in url is map type
 	return url.SubURL.Clone()
 }
 
diff --git a/registry/servicediscovery/service_discovery_registry.go b/registry/servicediscovery/service_discovery_registry.go
index 33d22e7339cb98552ec11c08b34c32ed444263c7..949010431f7f08cb5827fd45b799292848f6d9c6 100644
--- a/registry/servicediscovery/service_discovery_registry.go
+++ b/registry/servicediscovery/service_discovery_registry.go
@@ -38,6 +38,7 @@ import (
 	"github.com/apache/dubbo-go/metadata/service"
 	"github.com/apache/dubbo-go/metadata/service/remote"
 	"github.com/apache/dubbo-go/registry"
+	registryCommon "github.com/apache/dubbo-go/registry/common"
 	"github.com/apache/dubbo-go/registry/servicediscovery/proxy"
 	"github.com/apache/dubbo-go/registry/servicediscovery/synthesizer"
 	"github.com/apache/dubbo-go/remoting"
@@ -113,7 +114,11 @@ func creatServiceDiscovery(url *common.URL) (registry.ServiceDiscovery, error) {
 	if !ok {
 		return nil, perrors.Errorf("The service discovery with name: %s is not found", sdcName)
 	}
-	return extension.GetServiceDiscovery(sdc.Protocol, sdcName)
+	originServiceDiscovery, err := extension.GetServiceDiscovery(sdc.Protocol, sdcName)
+	if err != nil {
+		return nil, perrors.WithMessage(err, "Create service discovery fialed")
+	}
+	return registryCommon.NewEventPublishingServiceDiscovery(originServiceDiscovery), nil
 }
 
 func parseServices(literalServices string) *gxset.HashSet {
@@ -155,6 +160,7 @@ func (s *serviceDiscoveryRegistry) Register(url common.URL) error {
 		return nil
 	}
 	ok, err := s.metaDataService.ExportURL(url)
+	s.metaDataService.PublishServiceDefinition(url)
 	if err != nil {
 		logger.Errorf("The URL[%s] registry catch error:%s!", url.String(), err.Error())
 		return err
@@ -506,13 +512,14 @@ func (s *serviceDiscoveryRegistry) cloneExportedURLs(url common.URL, serviceInsa
 		templateExportURLs := s.getTemplateExportedURLs(url, serviceInstance)
 		host := serviceInstance.GetHost()
 		for _, u := range templateExportURLs {
-			u.RemoveParams(removeParamSet)
 			port := strconv.Itoa(getProtocolPort(serviceInstance, u.Protocol))
 			if u.Location != host || u.Port != port {
 				u.Port = port     // reset port
 				u.Location = host // reset host
 			}
-			clonedExportedURLs = append(clonedExportedURLs, u)
+
+			cloneUrl := u.CloneExceptParams(removeParamSet)
+			clonedExportedURLs = append(clonedExportedURLs, *cloneUrl)
 		}
 	}
 	return clonedExportedURLs
diff --git a/remoting/etcdv3/client_test.go b/remoting/etcdv3/client_test.go
index 895cc2954adf93b5899d0ae5daedbd35834b7ef4..e37b6383df55f1c7e7b64be62fc2eb22d1034616 100644
--- a/remoting/etcdv3/client_test.go
+++ b/remoting/etcdv3/client_test.go
@@ -29,11 +29,11 @@ import (
 )
 
 import (
+	"github.com/coreos/etcd/embed"
 	"github.com/coreos/etcd/mvcc/mvccpb"
 	perrors "github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/suite"
-	"go.etcd.io/etcd/embed"
 	"google.golang.org/grpc/connectivity"
 )
 
diff --git a/remoting/zookeeper/client.go b/remoting/zookeeper/client.go
index bd1da547766abb12dc742234787262212e3db314..92ea76046f002cbdf6dbe754453ef8ebb4a14de2 100644
--- a/remoting/zookeeper/client.go
+++ b/remoting/zookeeper/client.go
@@ -87,8 +87,6 @@ func StateToString(state zk.State) string {
 	default:
 		return state.String()
 	}
-
-	return "zookeeper unknown state"
 }
 
 // Options ...
@@ -111,12 +109,10 @@ func WithZkName(name string) Option {
 
 // ValidateZookeeperClient ...
 func ValidateZookeeperClient(container zkClientFacade, opts ...Option) error {
-	var (
-		err error
-	)
-	opions := &Options{}
+	var err error
+	options := &Options{}
 	for _, opt := range opts {
-		opt(opions)
+		opt(options)
 	}
 	connected := false
 	err = nil
@@ -129,17 +125,18 @@ func ValidateZookeeperClient(container zkClientFacade, opts ...Option) error {
 
 	if container.ZkClient() == nil {
 		//in dubbo ,every registry only connect one node ,so this is []string{r.Address}
-		timeout, err := time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT))
+		var timeout time.Duration
+		timeout, err = time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT))
 		if err != nil {
 			logger.Errorf("timeout config %v is invalid ,err is %v",
 				url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT), err.Error())
 			return perrors.WithMessagef(err, "newZookeeperClient(address:%+v)", url.Location)
 		}
 		zkAddresses := strings.Split(url.Location, ",")
-		newClient, err := newZookeeperClient(opions.zkName, zkAddresses, timeout)
+		newClient, err := newZookeeperClient(options.zkName, zkAddresses, timeout)
 		if err != nil {
 			logger.Warnf("newZookeeperClient(name{%s}, zk address{%v}, timeout{%d}) = error{%v}",
-				opions.zkName, url.Location, timeout.String(), err)
+				options.zkName, url.Location, timeout.String(), err)
 			return perrors.WithMessagef(err, "newZookeeperClient(address:%+v)", url.Location)
 		}
 		container.SetZkClient(newClient)
@@ -157,7 +154,7 @@ func ValidateZookeeperClient(container zkClientFacade, opts ...Option) error {
 	}
 
 	if connected {
-		logger.Info("Connect to zookeeper successfully, name{%s}, zk address{%v}", opions.zkName, url.Location)
+		logger.Info("Connect to zookeeper successfully, name{%s}, zk address{%v}", options.zkName, url.Location)
 		container.WaitGroup().Add(1) //zk client start successful, then registry wg +1
 	}
 
diff --git a/remoting/zookeeper/listener.go b/remoting/zookeeper/listener.go
index 097106acf6b44d03708362d587b5faa8281edeab..f9d57ba5c2276181bb551e8b8499d850b87d041a 100644
--- a/remoting/zookeeper/listener.go
+++ b/remoting/zookeeper/listener.go
@@ -18,7 +18,6 @@
 package zookeeper
 
 import (
-	"github.com/apache/dubbo-go/common"
 	"path"
 	"strings"
 	"sync"
@@ -32,6 +31,7 @@ import (
 )
 
 import (
+	"github.com/apache/dubbo-go/common"
 	"github.com/apache/dubbo-go/common/constant"
 	"github.com/apache/dubbo-go/common/logger"
 	"github.com/apache/dubbo-go/remoting"
@@ -96,8 +96,6 @@ func (l *ZkEventListener) ListenServiceNodeEvent(zkPath string, listener ...remo
 			return false
 		}
 	}
-
-	return false
 }
 
 func (l *ZkEventListener) handleZkNodeEvent(zkPath string, children []string, listener remoting.DataListener) {
diff --git a/test/integrate/dubbo/go-client/Dockerfile b/test/integrate/dubbo/go-client/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..d48df36dc72d7e75f8c2c8c91d5acbb01e39757d
--- /dev/null
+++ b/test/integrate/dubbo/go-client/Dockerfile
@@ -0,0 +1,36 @@
+#
+#Licensed to the Apache Software Foundation (ASF) under one or more
+#contributor license agreements.  See the NOTICE file distributed with
+#this work for additional information regarding copyright ownership.
+#The ASF licenses this file to You under the Apache License, Version 2.0
+#(the "License"); you may not use this file except in compliance with
+#the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#Unless required by applicable law or agreed to in writing, software
+#distributed under the License is distributed on an "AS IS" BASIS,
+#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#See the License for the specific language governing permissions and
+#limitations under the License.
+#
+
+FROM golang
+
+WORKDIR /go/src/github.com/apache/dubbo-go/test/integrate/dubbo/go-client
+
+ENV CONF_CONSUMER_FILE_PATH "client.yml"
+ENV APP_LOG_CONF_FILE "log.yml"
+
+ARG PR_ORIGIN_REPO
+ARG PR_ORIGIN_COMMITID
+
+ADD . /go/src/github.com/apache/dubbo-go/test/integrate/dubbo/go-client
+
+# update dubbo-go to current commit id
+RUN test ${PR_ORIGIN_REPO} && echo "github.com/apache/dubbo-go will be replace to github.com/${PR_ORIGIN_REPO}@${PR_ORIGIN_COMMITID}" || echo 'go get github.com/apache/dubbo-go@develop'
+RUN test ${PR_ORIGIN_REPO} && go mod edit  -replace=github.com/apache/dubbo-go=github.com/${PR_ORIGIN_REPO}@${PR_ORIGIN_COMMITID} || go get -u github.com/apache/dubbo-go@develop
+
+RUN go install github.com/apache/dubbo-go/test/integrate/dubbo/go-client
+
+CMD go-client
\ No newline at end of file
diff --git a/test/integrate/dubbo/go-client/client.go b/test/integrate/dubbo/go-client/client.go
new file mode 100644
index 0000000000000000000000000000000000000000..4c62674d33dba7caca72ca7552e73c4c0fdf14c9
--- /dev/null
+++ b/test/integrate/dubbo/go-client/client.go
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"context"
+	"fmt"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	_ "github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	"github.com/apache/dubbo-go/config"
+	_ "github.com/apache/dubbo-go/protocol/dubbo"
+	_ "github.com/apache/dubbo-go/registry/protocol"
+
+	_ "github.com/apache/dubbo-go/filter/filter_impl"
+
+	_ "github.com/apache/dubbo-go/cluster/cluster_impl"
+	_ "github.com/apache/dubbo-go/cluster/loadbalance"
+	_ "github.com/apache/dubbo-go/registry/zookeeper"
+)
+
+var (
+	survivalTimeout int = 10e9
+)
+
+func println(format string, args ...interface{}) {
+	fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...)
+}
+
+// they are necessary:
+// 		export CONF_CONSUMER_FILE_PATH="xxx"
+// 		export APP_LOG_CONF_FILE="xxx"
+func main() {
+	hessian.RegisterPOJO(&User{})
+	config.Load()
+	time.Sleep(3e9)
+
+	println("\n\n\nstart to test dubbo")
+
+	go func() {
+		select {
+		case <-time.After(time.Minute):
+			panic("provider not start after client already running 1min")
+		}
+	}()
+	user := &User{}
+	err := userProvider.GetUser(context.TODO(), []interface{}{"A001"}, user)
+	if err != nil {
+		panic(err)
+	}
+	println("response result: %v\n", user)
+}
diff --git a/test/integrate/dubbo/go-client/client.yml b/test/integrate/dubbo/go-client/client.yml
new file mode 100644
index 0000000000000000000000000000000000000000..df44a13da38a14fa4a81b6189aa05708cf6f5599
--- /dev/null
+++ b/test/integrate/dubbo/go-client/client.yml
@@ -0,0 +1,61 @@
+# dubbo client yaml configure file
+
+
+check: true
+# client
+request_timeout : "3s"
+# connect timeout
+connect_timeout : "3s"
+
+# application config
+application:
+  organization : "ikurento.com"
+  name  : "BDTService"
+  module : "dubbogo user-info client"
+  version : "0.0.1"
+  owner : "ZX"
+  environment : "dev"
+
+registries :
+  "demoZk":
+    protocol: "zookeeper"
+    timeout	: "3s"
+    address: "127.0.0.1:2181"
+    username: ""
+    password: ""
+
+
+references:
+  "UserProvider":
+    # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册
+    registry: "demoZk"
+    protocol : "dubbo"
+    interface : "com.ikurento.user.UserProvider"
+    cluster: "failover"
+    methods :
+    - name: "GetUser"
+      retries: 3
+
+
+protocol_conf:
+  dubbo:
+    reconnect_interval: 0
+    connection_number: 2
+    heartbeat_period: "5s"
+    session_timeout: "20s"
+    pool_size: 64
+    pool_ttl: 600
+    getty_session_param:
+      compress_encoding: false
+      tcp_no_delay: true
+      tcp_keep_alive: true
+      keep_alive_period: "120s"
+      tcp_r_buf_size: 262144
+      tcp_w_buf_size: 65536
+      pkg_rq_size: 1024
+      pkg_wq_size: 512
+      tcp_read_timeout: "1s"
+      tcp_write_timeout: "5s"
+      wait_timeout: "1s"
+      max_msg_len: 1024000
+      session_name: "client"
diff --git a/test/integrate/dubbo/go-client/go.mod b/test/integrate/dubbo/go-client/go.mod
new file mode 100644
index 0000000000000000000000000000000000000000..4708eb1f0f48c10acc254880ecb6dad3a03529f2
--- /dev/null
+++ b/test/integrate/dubbo/go-client/go.mod
@@ -0,0 +1,3 @@
+module github.com/apache/dubbo-go/test/integrate/dubbo/go-client
+
+go 1.13
diff --git a/test/integrate/dubbo/go-client/go.sum b/test/integrate/dubbo/go-client/go.sum
new file mode 100644
index 0000000000000000000000000000000000000000..687fd0f337095443e2627b70a48c524fe335aba1
--- /dev/null
+++ b/test/integrate/dubbo/go-client/go.sum
@@ -0,0 +1,389 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
+github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest v10.15.3+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/Jeffail/gabs v1.1.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
+github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
+github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
+github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/SAP/go-hdb v0.12.0/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0=
+github.com/SermoDigital/jose v0.0.0-20180104203859-803625baeddc/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA=
+github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
+github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
+github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190802083043-4cd0c391755e/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
+github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
+github.com/apache/dubbo-go v1.4.1/go.mod h1:hzP9PQkcYFcBUgedttDeimugDNqbmGzh18QQy/vBjnw=
+github.com/apache/dubbo-go-hessian2 v1.4.0/go.mod h1:VwEnsOMidkM1usya2uPfGpSLO9XUF//WQcWn3y+jFz8=
+github.com/apache/dubbo-go-hessian2 v1.5.0/go.mod h1:VwEnsOMidkM1usya2uPfGpSLO9XUF//WQcWn3y+jFz8=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/asaskevich/govalidator v0.0.0-20180319081651-7d2e70ef918f/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
+github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
+github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
+github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
+github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
+github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/coredns/coredns v1.1.2/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0=
+github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
+github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/creasty/defaults v1.3.0/go.mod h1:CIEEvs7oIVZm30R8VxtFJs+4k201gReYyuYHJxZc68I=
+github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisenkom/go-mssqldb v0.0.0-20180620032804-94c9c97e8c9f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
+github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU=
+github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU=
+github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dubbogo/getty v1.3.3/go.mod h1:U92BDyJ6sW9Jpohr2Vlz8w2uUbIbNZ3d+6rJvFTSPp0=
+github.com/dubbogo/go-zookeeper v1.0.0/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4DdC2ENwRb6E+c=
+github.com/dubbogo/gost v1.5.1/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
+github.com/dubbogo/gost v1.5.2/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
+github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
+github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
+github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
+github.com/emicklei/go-restful/v3 v3.0.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/envoyproxy/go-control-plane v0.8.0/go.mod h1:GSSbY9P1neVhdY7G4wu+IK1rk/dqhiCC/4ExuWJZVuk=
+github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/structs v0.0.0-20180123065059-ebf56d35bba7/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
+github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
+github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
+github.com/go-sql-driver/mysql v0.0.0-20180618115901-749ddf1598b4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/gocql/gocql v0.0.0-20180617115710-e06f8c1bcd78/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
+github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+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-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
+github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
+github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
+github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
+github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
+github.com/hashicorp/consul v1.5.3/go.mod h1:61E2GJCPEP3oq8La7sfDdWGQ66+Zbxzw5ecOdFD7xIE=
+github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
+github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-bexpr v0.1.0/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU=
+github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4=
+github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd/go.mod h1:ueUgD9BeIocT7QNuvxSyJyPAM9dfifBcaWmeybb67OY=
+github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ=
+github.com/hashicorp/go-raftchunking v0.6.1/go.mod h1:cGlg3JtDy7qy6c/3Bu660Mic1JF+7lWqIwCFSb08fX0=
+github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
+github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v0.0.0-20170202080759-03c5bf6be031/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v0.0.0-20180906183839-65a6292f0157/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/hil v0.0.0-20160711231837-1e86c6b523c5/go.mod h1:KHvg/R2/dPtaePb16oW4qIyzkMxXOL38xjRN64adsts=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
+github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
+github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q=
+github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
+github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
+github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hashicorp/vault v0.10.3/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0=
+github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190318174639-195e0e9d07f1/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0=
+github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo=
+github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4=
+github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM=
+github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
+github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
+github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA=
+github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/keybase/go-crypto v0.0.0-20180614160407-5114a9a81e1b/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE=
+github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f/go.mod h1:UGmTpUd3rjbtfIpwAPrcfmGf/Z1HS95TATB+m57TPB8=
+github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0=
+github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
+github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb/go.mod h1:CEkSvEpoveoYjA81m4HNeYQ0sge0LFGKSEqO3JKHllo=
+github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk=
+github.com/oklog/run v0.0.0-20180308005104-6934b124db28/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
+github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
+github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
+github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
+github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
+github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8=
+github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
+github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/zouyx/agollo v0.0.0-20191114083447-dde9fc9f35b8/go.mod h1:S1cAa98KMFv4Sa8SbJ6ZtvOmf0VlgH0QJ1gXI0lBfBY=
+go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20170114055629-f2499483f923/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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+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/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/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-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-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/ory-am/dockertest.v3 v3.3.4/go.mod h1:s9mmoLkaGeAh97qygnNj4xWkiN7e1SKekYC6CovU+ek=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+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=
+istio.io/gogo-genproto v0.0.0-20190124151557-6d926a6e6feb/go.mod h1:eIDJ6jNk/IeJz6ODSksHl5Aiczy5JUq6vFhJWI5OtiI=
+k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
+k8s.io/api v0.0.0-20190325185214-7544f9db76f6/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
+k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
+k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
+k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
+k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
+sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/test/integrate/dubbo/go-client/log.yml b/test/integrate/dubbo/go-client/log.yml
new file mode 100644
index 0000000000000000000000000000000000000000..59fa4279ad85272c4c49d532beaf23b74d00f58a
--- /dev/null
+++ b/test/integrate/dubbo/go-client/log.yml
@@ -0,0 +1,28 @@
+
+level: "debug"
+development: true
+disableCaller: false
+disableStacktrace: false
+sampling:
+encoding: "console"
+
+# encoder
+encoderConfig:
+  messageKey: "message"
+  levelKey: "level"
+  timeKey: "time"
+  nameKey: "logger"
+  callerKey: "caller"
+  stacktraceKey: "stacktrace"
+  lineEnding: ""
+  levelEncoder: "capitalColor"
+  timeEncoder: "iso8601"
+  durationEncoder: "seconds"
+  callerEncoder: "short"
+  nameEncoder: ""
+
+outputPaths:
+  - "stderr"
+errorOutputPaths:
+  - "stderr"
+initialFields:
diff --git a/test/integrate/dubbo/go-client/user.go b/test/integrate/dubbo/go-client/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..ff4486f07975ebbb0064a8c83b71c952e6311dbb
--- /dev/null
+++ b/test/integrate/dubbo/go-client/user.go
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"context"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	"github.com/apache/dubbo-go/config"
+)
+
+var userProvider = new(UserProvider)
+
+func init() {
+	config.SetConsumerService(userProvider)
+	hessian.RegisterPOJO(&User{})
+}
+
+type User struct {
+	Id   string
+	Name string
+	Age  int32
+	Time time.Time
+}
+
+type UserProvider struct {
+	GetUser func(ctx context.Context, req []interface{}, rsp *User) error
+}
+
+func (u *UserProvider) Reference() string {
+	return "UserProvider"
+}
+
+func (User) JavaClassName() string {
+	return "com.ikurento.user.User"
+}
diff --git a/test/integrate/dubbo/go-client/version.go b/test/integrate/dubbo/go-client/version.go
new file mode 100644
index 0000000000000000000000000000000000000000..c6138584f1ddeab3a4927774f44f9e78a8f08da7
--- /dev/null
+++ b/test/integrate/dubbo/go-client/version.go
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+var (
+	Version = "2.6.0"
+)
diff --git a/test/integrate/dubbo/go-server/Dockerfile b/test/integrate/dubbo/go-server/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..c2f2d63462d94df7624ac100023e8b8c24e23e11
--- /dev/null
+++ b/test/integrate/dubbo/go-server/Dockerfile
@@ -0,0 +1,35 @@
+#
+#Licensed to the Apache Software Foundation (ASF) under one or more
+#contributor license agreements.  See the NOTICE file distributed with
+#this work for additional information regarding copyright ownership.
+#The ASF licenses this file to You under the Apache License, Version 2.0
+#(the "License"); you may not use this file except in compliance with
+#the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#Unless required by applicable law or agreed to in writing, software
+#distributed under the License is distributed on an "AS IS" BASIS,
+#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#See the License for the specific language governing permissions and
+#limitations under the License.
+#
+
+FROM golang
+
+WORKDIR /go/src/github.com/apache/dubbo-go/test/integrate/dubbo/go-server
+
+ENV CONF_PROVIDER_FILE_PATH "server.yml"
+ENV APP_LOG_CONF_FILE "log.yml"
+
+ARG PR_ORIGIN_REPO
+ARG PR_ORIGIN_COMMITID
+
+ADD . /go/src/github.com/apache/dubbo-go/test/integrate/dubbo/go-server
+# update dubbo-go to current commit id
+RUN test ${PR_ORIGIN_REPO} && echo "github.com/apache/dubbo-go will be replace to github.com/${PR_ORIGIN_REPO}@${PR_ORIGIN_COMMITID}" || echo 'go get github.com/apache/dubbo-go@develop'
+RUN test ${PR_ORIGIN_REPO} && go mod edit  -replace=github.com/apache/dubbo-go=github.com/${PR_ORIGIN_REPO}@${PR_ORIGIN_COMMITID} || go get -u github.com/apache/dubbo-go@develop
+
+RUN go install github.com/apache/dubbo-go/test/integrate/dubbo/go-server
+
+CMD go-server
diff --git a/test/integrate/dubbo/go-server/go.mod b/test/integrate/dubbo/go-server/go.mod
new file mode 100644
index 0000000000000000000000000000000000000000..9e1162327de374fb131c2a0b89d1be3baa578a1b
--- /dev/null
+++ b/test/integrate/dubbo/go-server/go.mod
@@ -0,0 +1,3 @@
+module github.com/apache/dubbo-go/test/integrate/dubbo/go-server
+
+go 1.13
diff --git a/test/integrate/dubbo/go-server/log.yml b/test/integrate/dubbo/go-server/log.yml
new file mode 100644
index 0000000000000000000000000000000000000000..59fa4279ad85272c4c49d532beaf23b74d00f58a
--- /dev/null
+++ b/test/integrate/dubbo/go-server/log.yml
@@ -0,0 +1,28 @@
+
+level: "debug"
+development: true
+disableCaller: false
+disableStacktrace: false
+sampling:
+encoding: "console"
+
+# encoder
+encoderConfig:
+  messageKey: "message"
+  levelKey: "level"
+  timeKey: "time"
+  nameKey: "logger"
+  callerKey: "caller"
+  stacktraceKey: "stacktrace"
+  lineEnding: ""
+  levelEncoder: "capitalColor"
+  timeEncoder: "iso8601"
+  durationEncoder: "seconds"
+  callerEncoder: "short"
+  nameEncoder: ""
+
+outputPaths:
+  - "stderr"
+errorOutputPaths:
+  - "stderr"
+initialFields:
diff --git a/test/integrate/dubbo/go-server/server.go b/test/integrate/dubbo/go-server/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..115bf0a4d78f171eb7f786808def91879ed93947
--- /dev/null
+++ b/test/integrate/dubbo/go-server/server.go
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	_ "github.com/apache/dubbo-go/cluster/cluster_impl"
+	_ "github.com/apache/dubbo-go/cluster/loadbalance"
+	_ "github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	"github.com/apache/dubbo-go/config"
+	_ "github.com/apache/dubbo-go/filter/filter_impl"
+	_ "github.com/apache/dubbo-go/protocol/dubbo"
+	_ "github.com/apache/dubbo-go/registry/protocol"
+	_ "github.com/apache/dubbo-go/registry/zookeeper"
+)
+
+var (
+	stopC = make(chan struct{})
+)
+
+// they are necessary:
+// 		export CONF_PROVIDER_FILE_PATH="xxx"
+// 		export APP_LOG_CONF_FILE="xxx"
+func main() {
+
+	hessian.RegisterPOJO(&User{})
+	config.Load()
+
+	select {
+	case <-stopC:
+		// wait getty send resp to consumer
+		time.Sleep(3*time.Second)
+		return
+	case <-time.After(time.Minute):
+		panic("provider already running 1 min, but can't be call by consumer")
+	}
+}
diff --git a/test/integrate/dubbo/go-server/server.yml b/test/integrate/dubbo/go-server/server.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8a17297b10119c217e68b39d58a10493f6dfc7a7
--- /dev/null
+++ b/test/integrate/dubbo/go-server/server.yml
@@ -0,0 +1,57 @@
+# dubbo server yaml configure file
+
+
+# application config
+application:
+  organization : "ikurento.com"
+  name : "BDTService"
+  module : "dubbogo user-info server"
+  version : "0.0.1"
+  owner : "ZX"
+  environment : "dev"
+
+registries :
+  "demoZk":
+    protocol: "zookeeper"
+    timeout	: "3s"
+    address: "127.0.0.1:2181"
+
+services:
+  "UserProvider":
+    # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册
+    registry: "demoZk"
+    protocol : "dubbo"
+    # 相当于dubbo.xml中的interface
+    interface : "com.ikurento.user.UserProvider"
+    loadbalance: "random"
+    warmup: "100"
+    cluster: "failover"
+    methods:
+    - name: "GetUser"
+      retries: 1
+      loadbalance: "random"
+
+protocols:
+  "dubbo":
+    name: "dubbo"
+    port: 20000
+
+
+protocol_conf:
+  dubbo:
+    session_number: 700
+    session_timeout: "20s"
+    getty_session_param:
+      compress_encoding: false
+      tcp_no_delay: true
+      tcp_keep_alive: true
+      keep_alive_period: "120s"
+      tcp_r_buf_size: 262144
+      tcp_w_buf_size: 65536
+      pkg_rq_size: 1024
+      pkg_wq_size: 512
+      tcp_read_timeout: "1s"
+      tcp_write_timeout: "5s"
+      wait_timeout: "1s"
+      max_msg_len: 1024000
+      session_name: "server"
diff --git a/test/integrate/dubbo/go-server/user.go b/test/integrate/dubbo/go-server/user.go
new file mode 100644
index 0000000000000000000000000000000000000000..7bff41566152940f885dec2eb256b261d04ad59a
--- /dev/null
+++ b/test/integrate/dubbo/go-server/user.go
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"context"
+	"fmt"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	"github.com/apache/dubbo-go/config"
+)
+
+func init() {
+	config.SetProviderService(new(UserProvider))
+	// ------for hessian2------
+	hessian.RegisterPOJO(&User{})
+}
+
+type User struct {
+	Id   string
+	Name string
+	Age  int32
+	Time time.Time
+}
+
+type UserProvider struct {
+}
+
+func (u *UserProvider) GetUser(ctx context.Context, req []interface{}) (*User, error) {
+	println("req:%#v", req)
+	rsp := User{"A001", "Alex Stocks", 18, time.Now()}
+	println("rsp:%#v", rsp)
+	close(stopC)
+	return &rsp, nil
+}
+
+func (u *UserProvider) Reference() string {
+	return "UserProvider"
+}
+
+func (u User) JavaClassName() string {
+	return "com.ikurento.user.User"
+}
+
+func println(format string, args ...interface{}) {
+	fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...)
+}
diff --git a/test/integrate/dubbo/go-server/version.go b/test/integrate/dubbo/go-server/version.go
new file mode 100644
index 0000000000000000000000000000000000000000..c6138584f1ddeab3a4927774f44f9e78a8f08da7
--- /dev/null
+++ b/test/integrate/dubbo/go-server/version.go
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+var (
+	Version = "2.6.0"
+)