You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2022/12/25 16:32:18 UTC

[dubbo-go-samples] branch master updated: async rpc samples (#479)

This is an automated email from the ASF dual-hosted git repository.

alexstocks pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-go-samples.git


The following commit(s) were added to refs/heads/master by this push:
     new df89852d async rpc samples (#479)
df89852d is described below

commit df89852dbba4a3e66f34a08a1443b7e2b80cf3dd
Author: Wenkang Huang <52...@users.noreply.github.com>
AuthorDate: Mon Dec 26 00:32:14 2022 +0800

    async rpc samples (#479)
    
    Co-authored-by: huangwenkang <64...@qq>
---
 async/README.md                         |  16 +++++
 async/README_zh.md                      |  14 ++++
 async/go-client/cmd/client.go           |  84 ++++++++++++++++++++++++
 async/go-client/conf/dubbogo.yml        |  17 +++++
 async/go-client/pkg/user.go             | 113 ++++++++++++++++++++++++++++++++
 async/go-server/cmd/server.go           |  84 ++++++++++++++++++++++++
 async/go-server/conf/dubbogo.yml        |  18 +++++
 async/go-server/pkg/user.go             | 109 ++++++++++++++++++++++++++++++
 async/go-server/pkg/user_provider.go    |  49 ++++++++++++++
 async/go-server/pkg/user_provider_v2.go |  33 ++++++++++
 10 files changed, 537 insertions(+)

diff --git a/async/README.md b/async/README.md
new file mode 100644
index 00000000..7ade4ee5
--- /dev/null
+++ b/async/README.md
@@ -0,0 +1,16 @@
+# Async RPC Dubbo for Dubbo-go
+
+For api definition and go client and server startup, please refer to [dubbo-go 3.0 quickstart](https://dubbogo.github.io/zh-cn/docs/user/quickstart/3.0/quickstart.html)
+
+## Instructions
+### 1. Start zookeeper
+Execute the command `docker run --rm -p 2181:2181 zookeeper` or `make -f $DUBBO_GO_SAMPLES_ROOT_PATH/build/Makefile docker-up`.
+   If you choose the second way, please ensure that you have set the environment $DUBBO_GO_SAMPLES_ROOT_PATH.
+   
+### 2. Start the server
+
+Use goland to start async/go-server/cmd/server.go
+
+### 3. Start the client
+
+Use goland to start async/go-client/cmd/client.go
\ No newline at end of file
diff --git a/async/README_zh.md b/async/README_zh.md
new file mode 100644
index 00000000..c538649e
--- /dev/null
+++ b/async/README_zh.md
@@ -0,0 +1,14 @@
+# 异步 RPC Dubbo for Dubbo-go 3.0
+
+api 定义以及 go 客户端、服务端启动,可以参考 [dubbo-go 3.0 快速开始](https://dubbogo.github.io/zh-cn/docs/user/quickstart/3.0/quickstart.html)
+
+## 使用方法
+1. 启动 zookeeper
+
+2. 启动服务端
+
+使用 goland 启动 async/go-server/cmd/server.go
+
+3. 启动客户端
+
+使用 goland 启动 async/go-client/com/client.go
diff --git a/async/go-client/cmd/client.go b/async/go-client/cmd/client.go
new file mode 100644
index 00000000..40a49659
--- /dev/null
+++ b/async/go-client/cmd/client.go
@@ -0,0 +1,84 @@
+/*
+ * 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 (
+	"dubbo.apache.org/dubbo-go/v3/config"
+	_ "dubbo.apache.org/dubbo-go/v3/imports"
+
+	hessian "github.com/apache/dubbo-go-hessian2"
+
+	"github.com/dubbogo/gost/log/logger"
+)
+
+import (
+	"github.com/apache/dubbo-go-samples/async/go-client/pkg"
+)
+
+var (
+	userProvider   = &pkg.UserProvider{}
+	userProviderV2 = &pkg.UserProviderV2{}
+)
+
+// need to setup environment variable "DUBBO_GO_CONFIG_PATH" to "conf/dubbogo.yml" before run
+func main() {
+	hessian.RegisterJavaEnum(pkg.MAN)
+	hessian.RegisterJavaEnum(pkg.WOMAN)
+	hessian.RegisterPOJO(&pkg.User{})
+
+	config.SetConsumerService(userProvider)
+	config.SetConsumerService(userProviderV2)
+
+	err := config.Load()
+	if err != nil {
+		panic(err)
+	}
+
+	testAsync()
+	testAsyncOneWay()
+}
+
+// two-way
+func testAsync() {
+	reqUser := &pkg.User{}
+	reqUser.ID = "003"
+	_, err := userProvider.GetUser(context.TODO(), reqUser)
+	if err != nil {
+		panic(err)
+	}
+
+	// Mock do something else
+	logger.Info("non-blocking before async callback resp: do something ... ")
+
+	// Wait for Callback
+	time.Sleep(time.Second)
+}
+
+// one-way
+func testAsyncOneWay() {
+	err := userProviderV2.SayHello(context.TODO(), "003")
+	if err != nil {
+		panic(err)
+	}
+	logger.Info("test end")
+}
diff --git a/async/go-client/conf/dubbogo.yml b/async/go-client/conf/dubbogo.yml
new file mode 100644
index 00000000..6f115620
--- /dev/null
+++ b/async/go-client/conf/dubbogo.yml
@@ -0,0 +1,17 @@
+# dubbo client yaml configure file
+
+dubbo:
+  registries:
+    demoZK:
+      protocol: zookeeper
+      address: 127.0.0.1:2181
+  consumer:
+    references:
+      UserProvider:
+        protocol: dubbo
+        interface: org.apache.dubbo.sample.UserProvider
+        async: true
+      UserProviderV2:
+        protocol: dubbo
+        interface: org.apache.dubbo.sample.UserProviderV2
+        async: true
\ No newline at end of file
diff --git a/async/go-client/pkg/user.go b/async/go-client/pkg/user.go
new file mode 100644
index 00000000..9e5a88ef
--- /dev/null
+++ b/async/go-client/pkg/user.go
@@ -0,0 +1,113 @@
+/*
+ * 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 pkg
+
+import (
+	"context"
+	"dubbo.apache.org/dubbo-go/v3/common"
+	"dubbo.apache.org/dubbo-go/v3/protocol"
+	"dubbo.apache.org/dubbo-go/v3/remoting"
+	"fmt"
+	gxlog "github.com/dubbogo/gost/log"
+	"strconv"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+type Gender hessian.JavaEnum
+
+const (
+	MAN Gender = iota
+	WOMAN
+)
+
+var genderName = map[Gender]string{
+	MAN:   "MAN",
+	WOMAN: "WOMAN",
+}
+
+var genderValue = map[string]Gender{
+	"MAN":   MAN,
+	"WOMAN": WOMAN,
+}
+
+func (g Gender) JavaClassName() string {
+	return "org.apache.dubbo.sample.Gender"
+}
+
+func (g Gender) String() string {
+	s, ok := genderName[g]
+	if ok {
+		return s
+	}
+
+	return strconv.Itoa(int(g))
+}
+
+func (g Gender) EnumValue(s string) hessian.JavaEnum {
+	v, ok := genderValue[s]
+	if ok {
+		return hessian.JavaEnum(v)
+	}
+
+	return hessian.InvalidJavaEnum
+}
+
+type User struct {
+	// !!! Cannot define lowercase names of variable
+	ID   string `hessian:"id"`
+	Name string
+	Age  int32
+	Time time.Time
+	Sex  Gender // notice: java enum Object <--> go string
+}
+
+func (u User) String() string {
+	return fmt.Sprintf(
+		"User{ID:%s, Name:%s, Age:%d, Time:%s, Sex:%s}",
+		u.ID, u.Name, u.Age, u.Time, u.Sex,
+	)
+}
+
+func (u *User) JavaClassName() string {
+	return "org.apache.dubbo.sample.User"
+}
+
+type UserProvider struct {
+	GetUser func(ctx context.Context, req *User) (*User, error)
+}
+
+// CallBack for async callback
+func (u *UserProvider) CallBack(response common.CallbackResponse) {
+	resp := response.(remoting.AsyncCallbackResponse).Reply.(*remoting.Response)
+	if resp.Error != nil {
+		panic(resp.Error)
+	}
+
+	user := resp.Result.(*protocol.RPCResult).Rest.(*User)
+	gxlog.CInfo("async callback response! got result :%v\n", user)
+	return
+}
+
+// UserProviderV2 for one way
+type UserProviderV2 struct {
+	SayHello func(ctx context.Context, name string) error
+}
diff --git a/async/go-server/cmd/server.go b/async/go-server/cmd/server.go
new file mode 100644
index 00000000..5af5df70
--- /dev/null
+++ b/async/go-server/cmd/server.go
@@ -0,0 +1,84 @@
+/*
+ * 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 (
+	"fmt"
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/config"
+	_ "dubbo.apache.org/dubbo-go/v3/imports"
+
+	hessian "github.com/apache/dubbo-go-hessian2"
+
+	"github.com/dubbogo/gost/log/logger"
+)
+
+import (
+	"github.com/apache/dubbo-go-samples/async/go-server/pkg"
+)
+
+var (
+	survivalTimeout = int(3e9)
+)
+
+// need to setup environment variable "DUBBO_GO_CONFIG_PATH" to "conf/dubbogo.yml" before run
+func main() {
+
+	// ------for hessian2------
+	hessian.RegisterJavaEnum(pkg.MAN)
+	hessian.RegisterJavaEnum(pkg.WOMAN)
+	hessian.RegisterPOJO(&pkg.User{})
+	config.SetProviderService(&pkg.UserProvider{})
+	config.SetProviderService(&pkg.UserProviderV2{})
+	// ------------
+
+	if err := config.Load(); err != nil {
+		panic(err)
+	}
+
+	initSignal()
+}
+
+func initSignal() {
+	signals := make(chan os.Signal, 1)
+	// It is not possible to block SIGKILL or syscall.SIGSTOP
+	signal.Notify(signals, os.Interrupt, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
+	for {
+		sig := <-signals
+		logger.Infof("get signal %s", sig.String())
+		switch sig {
+		case syscall.SIGHUP:
+			// reload()
+		default:
+			time.AfterFunc(time.Duration(survivalTimeout), func() {
+				logger.Warnf("app exit now by force...")
+				os.Exit(1)
+			})
+
+			// The program exits normally or timeout forcibly exits.
+			fmt.Println("provider app exit now...")
+			return
+		}
+	}
+}
diff --git a/async/go-server/conf/dubbogo.yml b/async/go-server/conf/dubbogo.yml
new file mode 100644
index 00000000..511b62e9
--- /dev/null
+++ b/async/go-server/conf/dubbogo.yml
@@ -0,0 +1,18 @@
+# dubbo server yaml configure file
+
+dubbo:
+  registries:
+    demoZK:
+      protocol: zookeeper
+      timeout: 3s
+      address: 127.0.0.1:2181
+  protocols:
+    dubbo:
+      name: dubbo
+      port: 20000
+  provider:
+    services:
+      UserProvider:
+        interface: org.apache.dubbo.sample.UserProvider
+      UserProviderV2:
+        interface: org.apache.dubbo.sample.UserProviderV2
\ No newline at end of file
diff --git a/async/go-server/pkg/user.go b/async/go-server/pkg/user.go
new file mode 100644
index 00000000..ca9f763f
--- /dev/null
+++ b/async/go-server/pkg/user.go
@@ -0,0 +1,109 @@
+/*
+ * 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 pkg
+
+import (
+	"fmt"
+	"strconv"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+type Gender hessian.JavaEnum
+
+const (
+	MAN Gender = iota
+	WOMAN
+)
+
+var genderName = map[Gender]string{
+	MAN:   "MAN",
+	WOMAN: "WOMAN",
+}
+
+var genderValue = map[string]Gender{
+	"MAN":   MAN,
+	"WOMAN": WOMAN,
+}
+
+func (g Gender) JavaClassName() string {
+	return "org.apache.dubbo.sample.Gender"
+}
+
+func (g Gender) String() string {
+	s, ok := genderName[g]
+	if ok {
+		return s
+	}
+
+	return strconv.Itoa(int(g))
+}
+
+func (g Gender) EnumValue(s string) hessian.JavaEnum {
+	v, ok := genderValue[s]
+	if ok {
+		return hessian.JavaEnum(v)
+	}
+
+	return hessian.InvalidJavaEnum
+}
+
+type (
+	User struct {
+		// !!! Cannot define lowercase names of variable
+		ID   string `hessian:"id"`
+		Name string
+		Age  int32
+		Time time.Time
+		Sex  Gender // notice: java enum Object <--> go string
+	}
+)
+
+var (
+	DefaultUser = User{
+		ID: "000", Name: "Alex Stocks", Age: 31,
+		Sex: MAN,
+	}
+
+	userMap = make(map[string]User)
+)
+
+func init() {
+	userMap["000"] = DefaultUser
+	userMap["001"] = User{ID: "001", Name: "ZhangSheng", Age: 18, Sex: MAN}
+	userMap["002"] = User{ID: "002", Name: "Lily", Age: 20, Sex: WOMAN}
+	userMap["003"] = User{ID: "113", Name: "Moorse", Age: 30, Sex: WOMAN}
+	for k, v := range userMap {
+		v.Time = time.Now()
+		userMap[k] = v
+	}
+}
+
+func (u User) String() string {
+	return fmt.Sprintf(
+		"User{ID:%s, Name:%s, Age:%d, Time:%s, Sex:%s}",
+		u.ID, u.Name, u.Age, u.Time, u.Sex,
+	)
+}
+
+func (u User) JavaClassName() string {
+	return "org.apache.dubbo.sample.User"
+}
diff --git a/async/go-server/pkg/user_provider.go b/async/go-server/pkg/user_provider.go
new file mode 100644
index 00000000..79792457
--- /dev/null
+++ b/async/go-server/pkg/user_provider.go
@@ -0,0 +1,49 @@
+/*
+ * 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 pkg
+
+import (
+	"context"
+	"fmt"
+	gxlog "github.com/dubbogo/gost/log"
+)
+
+type UserProvider struct {
+}
+
+func (u *UserProvider) getUser(userID string) (*User, error) {
+	if user, ok := userMap[userID]; ok {
+		return &user, nil
+	}
+
+	return nil, fmt.Errorf("invalid user id:%s", userID)
+}
+
+func (u *UserProvider) GetUser(ctx context.Context, req *User) (*User, error) {
+	var (
+		err  error
+		user *User
+	)
+
+	gxlog.CInfo("req:%#v", req)
+	user, err = u.getUser(req.ID)
+	if err == nil {
+		gxlog.CInfo("rsp:%#v", user)
+	}
+	return user, err
+}
diff --git a/async/go-server/pkg/user_provider_v2.go b/async/go-server/pkg/user_provider_v2.go
new file mode 100644
index 00000000..0e92db0a
--- /dev/null
+++ b/async/go-server/pkg/user_provider_v2.go
@@ -0,0 +1,33 @@
+package pkg
+
+import (
+	"context"
+	"fmt"
+	gxlog "github.com/dubbogo/gost/log"
+)
+
+type UserProviderV2 struct {
+}
+
+func (u *UserProviderV2) getUser(userID string) (*User, error) {
+	if user, ok := userMap[userID]; ok {
+		return &user, nil
+	}
+
+	return nil, fmt.Errorf("invalid user id:%s", userID)
+}
+
+func (u *UserProviderV2) SayHello(ctx context.Context, userID string) error {
+	var (
+		err  error
+		user *User
+	)
+
+	user, err = u.getUser(userID)
+	if err != nil {
+		panic(err)
+	}
+
+	gxlog.CInfo("hello, %s", user.Name)
+	return nil
+}