merge 3.0
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 0c5d3e0..5ce1a14 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,5 +1,5 @@
 <!--  Thanks for sending a pull request!
-Read https://github.com/apache/dubbo-go/blob/master/contributing.md before commit pull request.
+Read https://github.com/apache/dubbo-go/blob/master/CONTRIBUTING.md before commit pull request.
 -->
 
 **What this PR does**:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 6ce0286..3bd8d9c 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -9,7 +9,7 @@
     directory: "/" # Location of package manifests
     schedule:
       interval: "weekly"
-    target-branch: "develop"
+    target-branch: "3.0"
 
   - package-ecosystem: "github-actions"
     # Workflow files stored in the
@@ -17,4 +17,4 @@
     directory: "/"
     schedule:
       interval: "weekly"
-    target-branch: "develop"
\ No newline at end of file
+    target-branch: "3.0"
diff --git a/common/constant/key.go b/common/constant/key.go
index ae27581..38db23d 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -125,6 +125,7 @@
 	REGISTRY_PROTOCOL    = "registry"
 	ROLE_KEY             = "registry.role"
 	REGISTRY_DEFAULT_KEY = "registry.default"
+	// Deprecated use CONFIG_TIMEOUT_KEY key
 	REGISTRY_TIMEOUT_KEY = "registry.timeout"
 	REGISTRY_LABEL_KEY   = "label"
 	PREFERRED_KEY        = "preferred"
diff --git a/common/url.go b/common/url.go
index b279eca..5b2885c 100644
--- a/common/url.go
+++ b/common/url.go
@@ -27,6 +27,7 @@
 	"strconv"
 	"strings"
 	"sync"
+	"time"
 )
 
 import (
@@ -860,3 +861,12 @@
 func GetCompareURLEqualFunc() CompareURLEqualFunc {
 	return compareURLEqualFunc
 }
+
+//GetParamDuration get duration if param is invalid or missing will return 3s
+func (c *URL) GetParamDuration(s string, d string) time.Duration {
+
+	if t, err := time.ParseDuration(c.GetParam(s, d)); err == nil {
+		return t
+	}
+	return 3 * time.Second
+}
diff --git a/config/registry_config.go b/config/registry_config.go
index 92d92a6..2b22733 100644
--- a/config/registry_config.go
+++ b/config/registry_config.go
@@ -121,7 +121,7 @@
 	urlMap.Set(constant.GROUP_KEY, c.Group)
 	urlMap.Set(constant.ROLE_KEY, strconv.Itoa(int(roleType)))
 	urlMap.Set(constant.REGISTRY_KEY, c.Protocol)
-	urlMap.Set(constant.REGISTRY_TIMEOUT_KEY, c.TimeoutStr)
+	urlMap.Set(constant.CONFIG_TIMEOUT_KEY, c.TimeoutStr)
 	// multi registry invoker weight label for load balance
 	urlMap.Set(constant.REGISTRY_KEY+"."+constant.REGISTRY_LABEL_KEY, strconv.FormatBool(true))
 	urlMap.Set(constant.REGISTRY_KEY+"."+constant.PREFERRED_KEY, strconv.FormatBool(c.Preferred))
diff --git a/config/remote_config.go b/config/remote_config.go
index 292a89e..820f744 100644
--- a/config/remote_config.go
+++ b/config/remote_config.go
@@ -29,7 +29,6 @@
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/common/logger"
 )
 
 // RemoteConfig: usually we need some middleware, including nacos, zookeeper
@@ -45,8 +44,8 @@
 	Params     map[string]string `yaml:"params" json:"params,omitempty"`
 }
 
-// Prefix
-func (c *RemoteConfig) Prefix() string {
+// Prefix dubbo.remote.
+func (rc *RemoteConfig) Prefix() string {
 	return constant.RemotePrefix
 }
 
@@ -56,8 +55,6 @@
 	if res, err := time.ParseDuration(rc.TimeoutStr); err == nil {
 		return res
 	}
-	logger.Errorf("Could not parse the timeout string to Duration: %s, the default value will be returned",
-		rc.TimeoutStr)
 	return 5 * time.Second
 }
 
diff --git a/go.mod b/go.mod
index bb5c307..2ac6b3f 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@
 	github.com/creasty/defaults v1.5.1
 	github.com/dubbogo/go-zookeeper v1.0.3
 	github.com/dubbogo/gost v1.11.16
-	github.com/dubbogo/triple v1.0.2
+	github.com/dubbogo/triple v1.0.5
 	github.com/emicklei/go-restful/v3 v3.4.0
 	github.com/fsnotify/fsnotify v1.4.9
 	github.com/ghodss/yaml v1.0.0
diff --git a/go.sum b/go.sum
index 3529106..6532779 100644
--- a/go.sum
+++ b/go.sum
@@ -155,8 +155,8 @@
 github.com/dubbogo/jsonparser v1.0.1/go.mod h1:tYAtpctvSP/tWw4MeelsowSPgXQRVHHWbqL6ynps8jU=
 github.com/dubbogo/net v0.0.3 h1:2k53mh+1U8h1gFjJ8ykzyP4wNdAdgjc5moD+xVHI/AE=
 github.com/dubbogo/net v0.0.3/go.mod h1:B6/ka3g8VzcyrmdCH4VkHP1K0aHeI37FmclS+TCwIBU=
-github.com/dubbogo/triple v1.0.2 h1:+QKw6XbTyHP4yqUQ4gXRvV1FbhJZ7ldl9WrN0AjmCPM=
-github.com/dubbogo/triple v1.0.2/go.mod h1:O6vQD2XLCWugzAk0P27HTW4+Uhkd8sjaQn0BZijdGzU=
+github.com/dubbogo/triple v1.0.5 h1:bDASS3u0ILC+KaUmWaDDuZ7/pVZcljyO/1TkwXMvcsM=
+github.com/dubbogo/triple v1.0.5/go.mod h1:tCl0mV54+V8Br9z71sFbS1IQUG41QKZUrW6FGaLheM0=
 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
diff --git a/metadata/report/etcd/report.go b/metadata/report/etcd/report.go
index 836b43b..2d83fa3 100644
--- a/metadata/report/etcd/report.go
+++ b/metadata/report/etcd/report.go
@@ -20,7 +20,6 @@
 import (
 	"encoding/json"
 	"strings"
-	"time"
 )
 
 import (
@@ -146,7 +145,7 @@
 
 // CreateMetadataReport get the MetadataReport instance of etcd
 func (e *etcdMetadataReportFactory) CreateMetadataReport(url *common.URL) report.MetadataReport {
-	timeout, _ := time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT))
+	timeout := url.GetParamDuration(constant.CONFIG_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)
 	addresses := strings.Split(url.Location, ",")
 	client, err := gxetcd.NewClient(gxetcd.MetadataETCDV3Client, addresses, timeout, 1)
 	if err != nil {
diff --git a/registry/etcdv3/registry.go b/registry/etcdv3/registry.go
index 3ab9a2e..c777154 100644
--- a/registry/etcdv3/registry.go
+++ b/registry/etcdv3/registry.go
@@ -22,7 +22,6 @@
 	"path"
 	"strings"
 	"sync"
-	"time"
 )
 
 import (
@@ -75,12 +74,7 @@
 }
 
 func newETCDV3Registry(url *common.URL) (registry.Registry, error) {
-	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 nil, perrors.WithMessagef(err, "new etcd registry(address:%+v)", url.Location)
-	}
+	timeout := url.GetParamDuration(constant.CONFIG_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)
 
 	logger.Infof("etcd address is: %v, timeout is: %s", url.Location, timeout.String())
 
diff --git a/registry/nacos/service_discovery.go b/registry/nacos/service_discovery.go
index 174bf0b..57d4bec 100644
--- a/registry/nacos/service_discovery.go
+++ b/registry/nacos/service_discovery.go
@@ -216,6 +216,7 @@
 		serviceName := t.(string)
 		err := n.namingClient.Client().Subscribe(&vo.SubscribeParam{
 			ServiceName: serviceName,
+			GroupName:   n.group,
 			SubscribeCallback: func(services []model.SubscribeService, err error) {
 				if err != nil {
 					logger.Errorf("Could not handle the subscribe notification because the err is not nil."+
diff --git a/registry/zookeeper/service_discovery.go b/registry/zookeeper/service_discovery.go
index b2a966d..15cf134 100644
--- a/registry/zookeeper/service_discovery.go
+++ b/registry/zookeeper/service_discovery.go
@@ -102,7 +102,7 @@
 		common.WithParams(make(url.Values)),
 		common.WithPassword(remoteConfig.Password),
 		common.WithUsername(remoteConfig.Username),
-		common.WithParamsValue(constant.REGISTRY_TIMEOUT_KEY, remoteConfig.TimeoutStr))
+		common.WithParamsValue(constant.CONFIG_TIMEOUT_KEY, remoteConfig.TimeoutStr))
 	url.Location = remoteConfig.Address
 	zksd := &zookeeperServiceDiscovery{
 		url:      url,
diff --git a/remoting/nacos/builder.go b/remoting/nacos/builder.go
index c42cc93..037169f 100644
--- a/remoting/nacos/builder.go
+++ b/remoting/nacos/builder.go
@@ -68,10 +68,7 @@
 		serverConfigs = append(serverConfigs, nacosConstant.ServerConfig{IpAddr: ip, Port: uint64(port)})
 	}
 
-	timeout, err := time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT))
-	if err != nil {
-		return []nacosConstant.ServerConfig{}, nacosConstant.ClientConfig{}, err
-	}
+	timeout := url.GetParamDuration(constant.CONFIG_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)
 
 	clientConfig := nacosConstant.ClientConfig{
 		TimeoutMs:           uint64(int32(timeout / time.Millisecond)),
diff --git a/remoting/nacos/builder_test.go b/remoting/nacos/builder_test.go
index 959d27e..89992d6 100644
--- a/remoting/nacos/builder_test.go
+++ b/remoting/nacos/builder_test.go
@@ -19,8 +19,8 @@
 
 import (
 	"net/url"
-	"strconv"
 	"testing"
+	"time"
 )
 
 import (
@@ -83,15 +83,54 @@
 	assert.NotNil(t, client)
 }
 
-func getRegUrl() *common.URL {
-
+func TestTimeoutConfig(t *testing.T) {
 	regurlMap := url.Values{}
-	regurlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))
 	regurlMap.Set(constant.NACOS_NOT_LOAD_LOCAL_CACHE, "true")
 	// regurlMap.Set(constant.NACOS_USERNAME, "nacos")
 	// regurlMap.Set(constant.NACOS_PASSWORD, "nacos")
 	regurlMap.Set(constant.NACOS_NAMESPACE_ID, "nacos")
-	regurlMap.Set(constant.REGISTRY_TIMEOUT_KEY, "5s")
+
+	t.Run("default timeout", func(t *testing.T) {
+		newURL, _ := common.NewURL("registry://console.nacos.io:80", common.WithParams(regurlMap))
+
+		_, cc, err := GetNacosConfig(newURL)
+		assert.Nil(t, err)
+
+		assert.Equal(t, cc.TimeoutMs, uint64(int32(10*time.Second/time.Millisecond)))
+	})
+
+	t.Run("right timeout", func(t *testing.T) {
+
+		regurlMap.Set(constant.CONFIG_TIMEOUT_KEY, "5s")
+
+		newURL, _ := common.NewURL("registry://console.nacos.io:80", common.WithParams(regurlMap))
+
+		_, cc, err := GetNacosConfig(newURL)
+		assert.Nil(t, err)
+
+		assert.Equal(t, cc.TimeoutMs, uint64(int32(5*time.Second/time.Millisecond)))
+	})
+
+	t.Run("invalid timeout", func(t *testing.T) {
+		regurlMap.Set(constant.CONFIG_TIMEOUT_KEY, "5ab")
+
+		newURL, _ := common.NewURL("registry://console.nacos.io:80", common.WithParams(regurlMap))
+		_, cc, err := GetNacosConfig(newURL)
+		assert.Nil(t, err)
+
+		assert.Equal(t, cc.TimeoutMs, uint64(int32(3*time.Second/time.Millisecond)))
+	})
+
+}
+
+func getRegUrl() *common.URL {
+
+	regurlMap := url.Values{}
+	regurlMap.Set(constant.NACOS_NOT_LOAD_LOCAL_CACHE, "true")
+	// regurlMap.Set(constant.NACOS_USERNAME, "nacos")
+	// regurlMap.Set(constant.NACOS_PASSWORD, "nacos")
+	regurlMap.Set(constant.NACOS_NAMESPACE_ID, "nacos")
+	regurlMap.Set(constant.CONFIG_TIMEOUT_KEY, "5s")
 
 	regurl, _ := common.NewURL("registry://console.nacos.io:80", common.WithParams(regurlMap))
 
diff --git a/remoting/zookeeper/client.go b/remoting/zookeeper/client.go
index 1ed183f..a324fc7 100644
--- a/remoting/zookeeper/client.go
+++ b/remoting/zookeeper/client.go
@@ -19,7 +19,6 @@
 
 import (
 	"strings"
-	"time"
 )
 
 import (
@@ -55,12 +54,8 @@
 
 	if container.ZkClient() == nil {
 		// in dubbo, every registry only connect one node, so this is []string{r.Address}
-		timeout, paramErr := time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT))
-		if paramErr != nil {
-			logger.Errorf("timeout config %v is invalid, err is %v",
-				url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT), paramErr.Error())
-			return perrors.WithMessagef(paramErr, "newZookeeperClient(address:%+v)", url.Location)
-		}
+		timeout := url.GetParamDuration(constant.CONFIG_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)
+
 		zkAddresses := strings.Split(url.Location, ",")
 		newClient, cltErr := gxzookeeper.NewZookeeperClient(zkName, zkAddresses, true, gxzookeeper.WithZkTimeOut(timeout))
 		if cltErr != nil {