From aeb166f368c54c536a743c74494ce1c5b9566163 Mon Sep 17 00:00:00 2001
From: Joe Zou <yixian.zou@gmail.com>
Date: Mon, 27 Apr 2020 23:12:12 +0800
Subject: [PATCH] modify implement

---
 config/service_config.go      | 30 +++++++++++++++++++++++++++++-
 config/service_config_test.go | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/config/service_config.go b/config/service_config.go
index 4cd7ae273..45d37961b 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -18,6 +18,7 @@
 package config
 
 import (
+	"container/list"
 	"context"
 	"fmt"
 	"net/url"
@@ -29,6 +30,7 @@ import (
 
 import (
 	"github.com/creasty/defaults"
+	gxnet "github.com/dubbogo/gost/net"
 	perrors "github.com/pkg/errors"
 	"go.uber.org/atomic"
 )
@@ -105,6 +107,24 @@ func NewServiceConfig(id string, context context.Context) *ServiceConfig {
 	}
 }
 
+// Get Random Port
+func getRandomPort(protocolConfigs []*ProtocolConfig) *list.List {
+	l := list.New()
+	for _, proto := range protocolConfigs {
+		if proto.Port != "" {
+			continue
+		}
+
+		tcp, err := gxnet.ListenOnTCPRandomPort(proto.Ip)
+		if err != nil {
+			panic(perrors.New(fmt.Sprintf("Get tcp port error,err is {%v}", err)))
+		}
+		l.PushBack(strings.Split(tcp.Addr().String(), ":")[1])
+		defer tcp.Close()
+	}
+	return l
+}
+
 // Export ...
 func (c *ServiceConfig) Export() error {
 	// TODO: config center start here
@@ -129,6 +149,8 @@ func (c *ServiceConfig) Export() error {
 		return nil
 	}
 
+	ports := getRandomPort(protocolConfigs)
+	nextPort := ports.Front()
 	for _, proto := range protocolConfigs {
 		// registry the service reflect
 		methods, err := common.ServiceMap.Register(c.InterfaceName, proto.Name, c.rpcService)
@@ -137,11 +159,17 @@ func (c *ServiceConfig) Export() error {
 			logger.Errorf(err.Error())
 			return err
 		}
+
+		port := proto.Port
+		if proto.Port == "" {
+			port = nextPort.Value.(string)
+			nextPort = nextPort.Next()
+		}
 		ivkURL := common.NewURLWithOptions(
 			common.WithPath(c.id),
 			common.WithProtocol(proto.Name),
 			common.WithIp(proto.Ip),
-			common.WithPort(proto.Port),
+			common.WithPort(port),
 			common.WithParams(urlMap),
 			common.WithParamsValue(constant.BEAN_NAME_KEY, c.id),
 			common.WithMethods(strings.Split(methods, ",")),
diff --git a/config/service_config_test.go b/config/service_config_test.go
index 6f3230890..c84a381e2 100644
--- a/config/service_config_test.go
+++ b/config/service_config_test.go
@@ -23,6 +23,8 @@ import (
 
 import (
 	"github.com/apache/dubbo-go/common/extension"
+	gxnet "github.com/dubbogo/gost/net"
+	"github.com/stretchr/testify/assert"
 )
 
 func doInitProvider() {
@@ -189,3 +191,35 @@ func Test_Export(t *testing.T) {
 	}
 	providerConfig = nil
 }
+
+func Test_getRandomPort(t *testing.T) {
+	protocolConfigs := make([]*ProtocolConfig, 0, 3)
+
+	ip, err := gxnet.GetLocalIP()
+	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
+		Ip: ip,
+	})
+	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
+		Ip: ip,
+	})
+	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
+		Ip: ip,
+	})
+	assert.NoError(t, err)
+	ports := getRandomPort(protocolConfigs)
+
+	assert.Equal(t, ports.Len(), len(protocolConfigs))
+
+	front := ports.Front()
+	for {
+		if front == nil {
+			break
+		}
+		t.Logf("port:%v", front.Value)
+		front = front.Next()
+	}
+
+	protocolConfigs = make([]*ProtocolConfig, 0, 3)
+	ports = getRandomPort(protocolConfigs)
+	assert.Equal(t, ports.Len(), len(protocolConfigs))
+}
-- 
GitLab