You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by GitBox <gi...@apache.org> on 2020/11/03 13:45:19 UTC

[GitHub] [dubbo-go] AlexStocks commented on a change in pull request #818: Ftr: Add dubbo-go-cli telnet tool support

AlexStocks commented on a change in pull request #818:
URL: https://github.com/apache/dubbo-go/pull/818#discussion_r516430902



##########
File path: tools/cli/README.md
##########
@@ -0,0 +1,18 @@
+# dubbo-go-cli
+
+### 1. 解决问题

Review comment:
       hey, guy, pls using English in an Apache project. Or u rename this file to readme_cn.md and add an English readme.

##########
File path: tools/cli/client/client.go
##########
@@ -0,0 +1,200 @@
+/*
+ * 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 client
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"net"
+	"sync"
+	"time"
+)
+
+import (
+	"go.uber.org/atomic"
+)
+
+import (
+	"github.com/apache/dubbo-go/tools/cli/common"
+	"github.com/apache/dubbo-go/tools/cli/protocol"
+	_ "github.com/apache/dubbo-go/tools/cli/protocol/dubbo"
+)
+
+const defaultBufferSize = 4096
+
+// TelnetClient maintain a connection to target
+type TelnetClient struct {
+	responseTimeout time.Duration
+	protocolName    string
+	requestList     []*protocol.Request
+	conn            *net.TCPConn
+	proto           protocol.Protocol
+
+	sequence         atomic.Uint64
+	pendingResponses *sync.Map
+	waitNum          atomic.Uint64
+}
+
+// NewTelnetClient create a new tcp connection, and create default request
+func NewTelnetClient(host string, port int, protocolName, interfaceID, version, group, method string, reqPkg interface{}) (*TelnetClient, error) {
+	tcpAddr := createTCPAddr(host, port)
+	resolved := resolveTCPAddr(tcpAddr)
+	conn, err := net.DialTCP("tcp", nil, resolved)
+	if err != nil {
+		return nil, err
+	}
+	log.Printf("connected to %s:%d!\n", host, port)
+	log.Printf("try calling interface:%s.%s\n", interfaceID, method)
+	log.Printf("with protocol:%s\n\n", protocolName)
+	proto := common.GetProtocol(protocolName)
+
+	return &TelnetClient{
+		conn:             conn,
+		responseTimeout:  100000000, //default timeout
+		protocolName:     protocolName,
+		pendingResponses: &sync.Map{},
+		proto:            proto,
+		requestList: []*protocol.Request{
+			{
+				InterfaceID: interfaceID,
+				Version:     version,
+				Method:      method,
+				Group:       group,
+				Params:      []interface{}{reqPkg},
+			},
+		},
+	}, nil
+}
+
+func createTCPAddr(host string, port int) string {
+	var buffer bytes.Buffer
+	buffer.WriteString(host)
+	buffer.WriteByte(':')
+	buffer.WriteString(fmt.Sprintf("%d", port))
+	return buffer.String()
+}
+
+func resolveTCPAddr(addr string) *net.TCPAddr {
+	resolved, error := net.ResolveTCPAddr("tcp", addr)
+	if nil != error {
+		log.Fatalf("Error occured while resolving TCP address \"%v\": %v\n", addr, error)
+	}
+
+	return resolved
+}
+
+// ProcessRequests send all requests
+func (t *TelnetClient) ProcessRequests(userPkg interface{}) {
+	for i, _ := range t.requestList {
+		t.processSingleRequest(t.requestList[i], userPkg)
+	}
+}
+
+// addPendingResponse add a response @model to pending queue
+// once the rsp got, the model will be used.
+func (t *TelnetClient) addPendingResponse(model interface{}) uint64 {
+	seqId := t.sequence.Load()
+	t.pendingResponses.Store(seqId, model)
+	t.waitNum.Inc()
+	t.sequence.Inc()
+	return seqId
+}
+
+// removePendingResponse delete item from pending queue by @seq
+func (t *TelnetClient) removePendingResponse(seq uint64) {
+	if t.pendingResponses == nil {
+		return
+	}
+	if _, ok := t.pendingResponses.Load(seq); ok {
+		t.pendingResponses.Delete(seq)
+		t.waitNum.Dec()
+	}
+	return
+}
+
+// processSingleRequest call one req.
+func (t *TelnetClient) processSingleRequest(req *protocol.Request, userPkg interface{}) {
+	// proto create package procedure
+	req.ID = t.sequence.Load()
+	inputData, err := t.proto.Write(req)
+	if err != nil {
+		log.Fatalln("error: handler.Writer err = ", err)
+	}
+	startTime := time.Now()
+
+	// init rsp Package and add to pending queue
+	seqId := t.addPendingResponse(userPkg)
+	defer t.removePendingResponse(seqId)
+
+	requestDataChannel := make(chan []byte)
+	doneChannel := make(chan bool)
+	responseDataChannel := make(chan []byte)

Review comment:
       the same as above

##########
File path: tools/cli/common/protocol.go
##########
@@ -0,0 +1,39 @@
+/*
+ * 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 common
+
+import (
+	"github.com/apache/dubbo-go/tools/cli/protocol"
+)
+
+var (
+	protocols = make(map[string]func() protocol.Protocol)

Review comment:
       pls set its init length param, such as 8

##########
File path: tools/cli/client/client.go
##########
@@ -0,0 +1,200 @@
+/*
+ * 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 client
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"net"
+	"sync"
+	"time"
+)
+
+import (
+	"go.uber.org/atomic"
+)
+
+import (
+	"github.com/apache/dubbo-go/tools/cli/common"
+	"github.com/apache/dubbo-go/tools/cli/protocol"
+	_ "github.com/apache/dubbo-go/tools/cli/protocol/dubbo"
+)
+
+const defaultBufferSize = 4096
+
+// TelnetClient maintain a connection to target
+type TelnetClient struct {
+	responseTimeout time.Duration
+	protocolName    string
+	requestList     []*protocol.Request
+	conn            *net.TCPConn
+	proto           protocol.Protocol
+
+	sequence         atomic.Uint64
+	pendingResponses *sync.Map
+	waitNum          atomic.Uint64
+}
+
+// NewTelnetClient create a new tcp connection, and create default request
+func NewTelnetClient(host string, port int, protocolName, interfaceID, version, group, method string, reqPkg interface{}) (*TelnetClient, error) {
+	tcpAddr := createTCPAddr(host, port)
+	resolved := resolveTCPAddr(tcpAddr)
+	conn, err := net.DialTCP("tcp", nil, resolved)
+	if err != nil {
+		return nil, err
+	}
+	log.Printf("connected to %s:%d!\n", host, port)
+	log.Printf("try calling interface:%s.%s\n", interfaceID, method)
+	log.Printf("with protocol:%s\n\n", protocolName)
+	proto := common.GetProtocol(protocolName)
+
+	return &TelnetClient{
+		conn:             conn,
+		responseTimeout:  100000000, //default timeout
+		protocolName:     protocolName,
+		pendingResponses: &sync.Map{},
+		proto:            proto,
+		requestList: []*protocol.Request{
+			{
+				InterfaceID: interfaceID,
+				Version:     version,
+				Method:      method,
+				Group:       group,
+				Params:      []interface{}{reqPkg},
+			},
+		},
+	}, nil
+}
+
+func createTCPAddr(host string, port int) string {
+	var buffer bytes.Buffer
+	buffer.WriteString(host)
+	buffer.WriteByte(':')
+	buffer.WriteString(fmt.Sprintf("%d", port))
+	return buffer.String()
+}
+
+func resolveTCPAddr(addr string) *net.TCPAddr {
+	resolved, error := net.ResolveTCPAddr("tcp", addr)
+	if nil != error {
+		log.Fatalf("Error occured while resolving TCP address \"%v\": %v\n", addr, error)
+	}
+
+	return resolved
+}
+
+// ProcessRequests send all requests
+func (t *TelnetClient) ProcessRequests(userPkg interface{}) {
+	for i, _ := range t.requestList {
+		t.processSingleRequest(t.requestList[i], userPkg)
+	}
+}
+
+// addPendingResponse add a response @model to pending queue
+// once the rsp got, the model will be used.
+func (t *TelnetClient) addPendingResponse(model interface{}) uint64 {
+	seqId := t.sequence.Load()
+	t.pendingResponses.Store(seqId, model)
+	t.waitNum.Inc()
+	t.sequence.Inc()
+	return seqId
+}
+
+// removePendingResponse delete item from pending queue by @seq
+func (t *TelnetClient) removePendingResponse(seq uint64) {
+	if t.pendingResponses == nil {
+		return
+	}
+	if _, ok := t.pendingResponses.Load(seq); ok {
+		t.pendingResponses.Delete(seq)
+		t.waitNum.Dec()
+	}
+	return
+}
+
+// processSingleRequest call one req.
+func (t *TelnetClient) processSingleRequest(req *protocol.Request, userPkg interface{}) {
+	// proto create package procedure
+	req.ID = t.sequence.Load()
+	inputData, err := t.proto.Write(req)
+	if err != nil {
+		log.Fatalln("error: handler.Writer err = ", err)
+	}
+	startTime := time.Now()
+
+	// init rsp Package and add to pending queue
+	seqId := t.addPendingResponse(userPkg)
+	defer t.removePendingResponse(seqId)
+
+	requestDataChannel := make(chan []byte)

Review comment:
       do not need to set its length for this chan?

##########
File path: tools/cli/client/client.go
##########
@@ -0,0 +1,200 @@
+/*
+ * 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 client
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"net"
+	"sync"
+	"time"
+)
+
+import (
+	"go.uber.org/atomic"
+)
+
+import (
+	"github.com/apache/dubbo-go/tools/cli/common"
+	"github.com/apache/dubbo-go/tools/cli/protocol"
+	_ "github.com/apache/dubbo-go/tools/cli/protocol/dubbo"
+)
+
+const defaultBufferSize = 4096
+
+// TelnetClient maintain a connection to target
+type TelnetClient struct {
+	responseTimeout time.Duration
+	protocolName    string
+	requestList     []*protocol.Request
+	conn            *net.TCPConn
+	proto           protocol.Protocol
+
+	sequence         atomic.Uint64
+	pendingResponses *sync.Map
+	waitNum          atomic.Uint64
+}
+
+// NewTelnetClient create a new tcp connection, and create default request
+func NewTelnetClient(host string, port int, protocolName, interfaceID, version, group, method string, reqPkg interface{}) (*TelnetClient, error) {
+	tcpAddr := createTCPAddr(host, port)
+	resolved := resolveTCPAddr(tcpAddr)
+	conn, err := net.DialTCP("tcp", nil, resolved)
+	if err != nil {
+		return nil, err
+	}
+	log.Printf("connected to %s:%d!\n", host, port)
+	log.Printf("try calling interface:%s.%s\n", interfaceID, method)
+	log.Printf("with protocol:%s\n\n", protocolName)
+	proto := common.GetProtocol(protocolName)
+
+	return &TelnetClient{
+		conn:             conn,
+		responseTimeout:  100000000, //default timeout
+		protocolName:     protocolName,
+		pendingResponses: &sync.Map{},
+		proto:            proto,
+		requestList: []*protocol.Request{
+			{
+				InterfaceID: interfaceID,
+				Version:     version,
+				Method:      method,
+				Group:       group,
+				Params:      []interface{}{reqPkg},
+			},
+		},
+	}, nil
+}
+
+func createTCPAddr(host string, port int) string {

Review comment:
       pls using net.JoinHostPort instead.

##########
File path: tools/cli/example/README.md
##########
@@ -0,0 +1,132 @@
+# dubbo-go-cli 使用示例

Review comment:
       the same as above readme. pls rename this file to readme_cn.md and add an english readme.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org