feat: simplify registry and protocol configuration (#2445)

diff --git a/client/options.go b/client/options.go
index c5e1760..53a96fb 100644
--- a/client/options.go
+++ b/client/options.go
@@ -169,25 +169,19 @@
 	}
 }
 
-func WithRegistry(key string, opts ...registry.Option) ClientOption {
-	regOpts := registry.DefaultOptions()
-	for _, opt := range opts {
-		opt(regOpts)
-	}
+func WithRegistry(opts ...registry.Option) ClientOption {
+	regOpts := registry.NewOptions(opts...)
 
 	return func(cliOpts *ClientOptions) {
 		if cliOpts.Registries == nil {
 			cliOpts.Registries = make(map[string]*global.RegistryConfig)
 		}
-		cliOpts.Registries[key] = regOpts.Registry
+		cliOpts.Registries[regOpts.ID] = regOpts.Registry
 	}
 }
 
 func WithShutdown(opts ...graceful_shutdown.Option) ClientOption {
-	sdOpts := graceful_shutdown.DefaultOptions()
-	for _, opt := range opts {
-		opt(sdOpts)
-	}
+	sdOpts := graceful_shutdown.NewOptions(opts...)
 
 	return func(cliOpts *ClientOptions) {
 		cliOpts.Shutdown = sdOpts.Shutdown
diff --git a/graceful_shutdown/options.go b/graceful_shutdown/options.go
index e364bb9..f6d01aa 100644
--- a/graceful_shutdown/options.go
+++ b/graceful_shutdown/options.go
@@ -25,17 +25,22 @@
 	"dubbo.apache.org/dubbo-go/v3/global"
 )
 
-var (
-	defOpts = &Options{
-		Shutdown: global.DefaultShutdownConfig(),
-	}
-)
-
 type Options struct {
 	Shutdown *global.ShutdownConfig
 }
 
-func DefaultOptions() *Options {
+func defaultOptions() *Options {
+	return &Options{
+		Shutdown: global.DefaultShutdownConfig(),
+	}
+}
+
+func NewOptions(opts ...Option) *Options {
+	defOpts := defaultOptions()
+	for _, opt := range opts {
+		opt(defOpts)
+	}
+
 	return defOpts
 }
 
diff --git a/graceful_shutdown/shutdown.go b/graceful_shutdown/shutdown.go
index b560ed6..84fbbe2 100644
--- a/graceful_shutdown/shutdown.go
+++ b/graceful_shutdown/shutdown.go
@@ -59,7 +59,7 @@
 func Init(opts ...Option) {
 	initOnce.Do(func() {
 		protocols = make(map[string]struct{})
-		newOpts := DefaultOptions()
+		newOpts := defaultOptions()
 		for _, opt := range opts {
 			opt(newOpts)
 		}
diff --git a/options.go b/options.go
index b471732..85159e5 100644
--- a/options.go
+++ b/options.go
@@ -220,31 +220,25 @@
 	}
 }
 
-func WithProtocol(key string, opts ...protocol.Option) InstanceOption {
-	proOpts := protocol.DefaultOptions()
-	for _, opt := range opts {
-		opt(proOpts)
-	}
+func WithProtocol(opts ...protocol.Option) InstanceOption {
+	proOpts := protocol.NewOptions(opts...)
 
 	return func(insOpts *InstanceOptions) {
 		if insOpts.Protocols == nil {
 			insOpts.Protocols = make(map[string]*global.ProtocolConfig)
 		}
-		insOpts.Protocols[key] = proOpts.Protocol
+		insOpts.Protocols[proOpts.ID] = proOpts.Protocol
 	}
 }
 
-func WithRegistry(key string, opts ...registry.Option) InstanceOption {
-	regOpts := registry.DefaultOptions()
-	for _, opt := range opts {
-		opt(regOpts)
-	}
+func WithRegistry(opts ...registry.Option) InstanceOption {
+	regOpts := registry.NewOptions(opts...)
 
 	return func(insOpts *InstanceOptions) {
 		if insOpts.Registries == nil {
 			insOpts.Registries = make(map[string]*global.RegistryConfig)
 		}
-		insOpts.Registries[key] = regOpts.Registry
+		insOpts.Registries[regOpts.ID] = regOpts.Registry
 	}
 }
 
@@ -318,10 +312,7 @@
 //}
 
 func WithShutdown(opts ...graceful_shutdown.Option) InstanceOption {
-	sdOpts := graceful_shutdown.DefaultOptions()
-	for _, opt := range opts {
-		opt(sdOpts)
-	}
+	sdOpts := graceful_shutdown.NewOptions(opts...)
 
 	return func(insOpts *InstanceOptions) {
 		insOpts.Shutdown = sdOpts.Shutdown
diff --git a/protocol/options.go b/protocol/options.go
index 6373e59..8741e25 100644
--- a/protocol/options.go
+++ b/protocol/options.go
@@ -18,6 +18,7 @@
 package protocol
 
 import (
+	"fmt"
 	"strconv"
 )
 
@@ -27,12 +28,30 @@
 
 type Options struct {
 	Protocol *global.ProtocolConfig
+
+	ID string
 }
 
-func DefaultOptions() *Options {
+func defaultOptions() *Options {
 	return &Options{Protocol: global.DefaultProtocolConfig()}
 }
 
+func NewOptions(opts ...Option) *Options {
+	defOpts := defaultOptions()
+	for _, opt := range opts {
+		opt(defOpts)
+	}
+
+	if defOpts.Protocol.Name == "" {
+		panic(fmt.Sprintf("Please specify registry, eg. WithTriple()"))
+	}
+	if defOpts.ID == "" {
+		defOpts.ID = defOpts.Protocol.Name
+	}
+
+	return defOpts
+}
+
 type Option func(*Options)
 
 func WithDubbo() Option {
@@ -65,6 +84,14 @@
 	}
 }
 
+// WithID specifies the id of protocol.Options. Then you could configure server.WithProtocolIDs and
+// server.WithServer_ProtocolIDs to specify which protocol you need to use in multi-protocols scenario.
+func WithID(id string) Option {
+	return func(opts *Options) {
+		opts.ID = id
+	}
+}
+
 func WithIp(ip string) Option {
 	return func(opts *Options) {
 		opts.Protocol.Ip = ip
diff --git a/protocol/triple/internal/client/cmd_client_with_registry/main.go b/protocol/triple/internal/client/cmd_client_with_registry/main.go
index 4d2acb9..42d4349 100644
--- a/protocol/triple/internal/client/cmd_client_with_registry/main.go
+++ b/protocol/triple/internal/client/cmd_client_with_registry/main.go
@@ -29,7 +29,7 @@
 	// for the most brief RPC case with Registry
 
 	cli, err := client.NewClient(
-		client.WithRegistry("zk",
+		client.WithRegistry(
 			registry.WithZookeeper(),
 			registry.WithAddress("127.0.0.1:2181"),
 		),
diff --git a/protocol/triple/internal/client/cmd_instance_with_registry/main.go b/protocol/triple/internal/client/cmd_instance_with_registry/main.go
index 38f9d3a..219ae71 100644
--- a/protocol/triple/internal/client/cmd_instance_with_registry/main.go
+++ b/protocol/triple/internal/client/cmd_instance_with_registry/main.go
@@ -31,7 +31,8 @@
 	// configure global configurations and common modules
 	ins, err := dubbo.NewInstance(
 		dubbo.WithName("dubbo_test"),
-		dubbo.WithRegistry("zk",
+		dubbo.WithRegistry(
+			registry.WithID("zk"),
 			registry.WithZookeeper(),
 			registry.WithAddress("127.0.0.1:2181"),
 		),
diff --git a/protocol/triple/internal/server/cmd_instance/main.go b/protocol/triple/internal/server/cmd_instance/main.go
index 4c0006a..b5489b9 100644
--- a/protocol/triple/internal/server/cmd_instance/main.go
+++ b/protocol/triple/internal/server/cmd_instance/main.go
@@ -30,7 +30,7 @@
 	// configure global configurations and common modules
 	ins, err := dubbo.NewInstance(
 		dubbo.WithName("dubbo_test"),
-		dubbo.WithProtocol("tri",
+		dubbo.WithProtocol(
 			protocol.WithTriple(),
 			protocol.WithPort(20000),
 		),
diff --git a/protocol/triple/internal/server/cmd_instance_with_registry/main.go b/protocol/triple/internal/server/cmd_instance_with_registry/main.go
index 070421c..a8857dc 100644
--- a/protocol/triple/internal/server/cmd_instance_with_registry/main.go
+++ b/protocol/triple/internal/server/cmd_instance_with_registry/main.go
@@ -31,11 +31,11 @@
 	// configure global configurations and common modules
 	ins, err := dubbo.NewInstance(
 		dubbo.WithName("dubbo_test"),
-		dubbo.WithRegistry("zk",
+		dubbo.WithRegistry(
 			registry.WithZookeeper(),
 			registry.WithAddress("127.0.0.1:2181"),
 		),
-		dubbo.WithProtocol("tri",
+		dubbo.WithProtocol(
 			protocol.WithTriple(),
 			protocol.WithPort(20000),
 		),
diff --git a/protocol/triple/internal/server/cmd_server/main.go b/protocol/triple/internal/server/cmd_server/main.go
index d7c5e5b..3775644 100644
--- a/protocol/triple/internal/server/cmd_server/main.go
+++ b/protocol/triple/internal/server/cmd_server/main.go
@@ -27,7 +27,7 @@
 
 func main() {
 	srv, err := server.NewServer(
-		server.WithServer_Protocol("tri",
+		server.WithServer_Protocol(
 			protocol.WithTriple(),
 			protocol.WithPort(20000),
 		),
diff --git a/protocol/triple/internal/server/cmd_server_with_registry/main.go b/protocol/triple/internal/server/cmd_server_with_registry/main.go
index de2cc46..92651b0 100644
--- a/protocol/triple/internal/server/cmd_server_with_registry/main.go
+++ b/protocol/triple/internal/server/cmd_server_with_registry/main.go
@@ -28,11 +28,11 @@
 
 func main() {
 	srv, err := server.NewServer(
-		server.WithServer_Registry("zk",
+		server.WithServer_Registry(
 			registry.WithZookeeper(),
 			registry.WithAddress("127.0.0.1:2181"),
 		),
-		server.WithServer_Protocol("tri",
+		server.WithServer_Protocol(
 			protocol.WithTriple(),
 			protocol.WithPort(20000),
 		),
diff --git a/registry/options.go b/registry/options.go
index af40112..563438a 100644
--- a/registry/options.go
+++ b/registry/options.go
@@ -18,6 +18,7 @@
 package registry
 
 import (
+	"fmt"
 	"time"
 )
 
@@ -26,12 +27,34 @@
 	"dubbo.apache.org/dubbo-go/v3/global"
 )
 
+var defaultIDMap = map[string]string{}
+
 type Options struct {
 	Registry *global.RegistryConfig
+
+	ID string
 }
 
-func DefaultOptions() *Options {
-	return &Options{Registry: global.DefaultRegistryConfig()}
+func defaultOptions() *Options {
+	return &Options{
+		Registry: global.DefaultRegistryConfig(),
+	}
+}
+
+func NewOptions(opts ...Option) *Options {
+	defOpts := defaultOptions()
+	for _, opt := range opts {
+		opt(defOpts)
+	}
+
+	if defOpts.Registry.Protocol == "" {
+		panic(fmt.Sprintf("Please specify registry, eg. WithZookeeper()"))
+	}
+	if defOpts.ID == "" {
+		defOpts.ID = defOpts.Registry.Protocol
+	}
+
+	return defOpts
 }
 
 type Option func(*Options)
@@ -40,6 +63,7 @@
 	return func(opts *Options) {
 		// todo(DMwangnima): move etcdv3 to constant
 		opts.Registry.Protocol = "etcdv3"
+
 	}
 }
 
@@ -68,6 +92,14 @@
 	}
 }
 
+// WithID specifies the id of registry.Options. Then you could configure client.WithRegistryIDs and
+// server.WithServer_RegistryIDs to specify which registry you need to use in multi-registries scenario.
+func WithID(id string) Option {
+	return func(opts *Options) {
+		opts.ID = id
+	}
+}
+
 func WithTimeout(timeout time.Duration) Option {
 	return func(opts *Options) {
 		opts.Registry.Timeout = timeout.String()
diff --git a/server/options.go b/server/options.go
index 6dff299..83d78eb 100644
--- a/server/options.go
+++ b/server/options.go
@@ -128,17 +128,14 @@
 	}
 }
 
-func WithServer_Registry(key string, opts ...registry.Option) ServerOption {
-	regOpts := registry.DefaultOptions()
-	for _, opt := range opts {
-		opt(regOpts)
-	}
+func WithServer_Registry(opts ...registry.Option) ServerOption {
+	regOpts := registry.NewOptions(opts...)
 
 	return func(srvOpts *ServerOptions) {
 		if srvOpts.Registries == nil {
 			srvOpts.Registries = make(map[string]*global.RegistryConfig)
 		}
-		srvOpts.Registries[key] = regOpts.Registry
+		srvOpts.Registries[regOpts.ID] = regOpts.Registry
 	}
 }
 
@@ -149,17 +146,14 @@
 	}
 }
 
-func WithServer_Protocol(key string, opts ...protocol.Option) ServerOption {
-	proOpts := protocol.DefaultOptions()
-	for _, opt := range opts {
-		opt(proOpts)
-	}
+func WithServer_Protocol(opts ...protocol.Option) ServerOption {
+	proOpts := protocol.NewOptions(opts...)
 
 	return func(srvOpts *ServerOptions) {
 		if srvOpts.Protocols == nil {
 			srvOpts.Protocols = make(map[string]*global.ProtocolConfig)
 		}
-		srvOpts.Protocols[key] = proOpts.Protocol
+		srvOpts.Protocols[proOpts.ID] = proOpts.Protocol
 	}
 }