Go-Doudou系列02:如何使用Go-doudou开发GRPC服务
#go #microservices #grpc

自v2.0.0版本以来,go-doudou得到了支持以开发GRPC服务。该方法或工作流与先前版本相同,该版本首先是SVC.GO文件中Golang接口的方法,然后让Go-Doudou生成与您的代码一样多。 go-doudou具有平稳的学习曲线,使其对新手非常友好,尤其是对于具有Java,Nodejs或Python等其他编程语言背景的开发人员。 go-doudou很容易,但富有成效。

在这里,我将使用一个小型演示向您展示开发工作流程如何包括一些最佳实践。我们将使用go-doudou实施Largest Remainder Method GRPC服务,然后我们将看到如何测试。可以从https://github.com/unionj-cloud/go-doudou-tutorials/tree/master/go-stats克隆完整的代码。

准备

Intall Go

您应该安装GO v1.16或更高。

安装GRPC编译器和插件

安装编译器原始

要安装Protobuf编译器ProtoC,请参阅official documentation,以下是通用操作系统的安装命令:

  • Ubuntu系统:
$ apt install -y protobuf-compiler
$ protoc --version # Make sure to install v3 and above
  • Mac系统,您需要安装Homebrew
$ brew install protobuf
$ protoc --version # Make sure to install v3 and above

如果无法安装在Windows系统或Mac系统上,则需要从GitHub下载安装程序包,解开它并将其配置为环境变量。

Windows系统的最新ProtoC下载地址:https://github.com/protocolbuffers/protobuf/releases/download/v21.7/protoc-21.7-win64.zip

Mac系统Intel最新ProtoC下载地址:https://github.com/protocolbuffers/protobuf/releases/download/v21.7/protoc-21.7-osx-x86_64.zip

请在github releases中找到其他包裹。

安装插件

  1. 安装插件:
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
  1. 配置环境变量:
$ export PATH="$PATH:$(go env GOPATH)/bin"

请转到https://grpc.io/docs/languages/go/quickstart/查找最新版本编号。

安装go-doudou

  • 安装go-doudou cli

如果GO版本<1.17,

go get -v github.com/unionj-cloud/go-doudou/v2@v2.0.3

如果GO版本> = 1.17,建议使用以下命令安装GO-Doudou CLI全球

go install -v github.com/unionj-cloud/go-doudou/v2@v2.0.3
  • 下载go-doudou作为模块的依赖性
go get -v -d github.com/unionj-cloud/go-doudou/v2@v2.0.3


如果您遇到了410的错误,请尝试在下面运行命令,然后再次运行安装命令:

export GOSUMDB=off

安装后,如果遇到了go-doudou: command not found错误,请将$HOME/go/bin配置为~/.bash_profile文件,例如:

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:/usr/local/go/bin
PATH=$PATH:$HOME/go/bin

export PATH

验证go-doudou已安装,在命令下运行:

➜  go-doudou -v
go-doudou version v2.0.3

初始化项目

现在我们准备开始编码了。首先,我们应该初始化我们的项目。

go-doudou svc init go-stats -m go-doudou-tutorials/go-stats

go-stats是项目根文件夹路径,如果不存在任何目录,则go-doudou将递归创建目录。 go-doudou-tutorials/go-stats是模块名称,由-m flag指定。

go-doudou生成了下面的这些文件夹和文件。

➜  go-stats git:(master) ✗ tree -L 2
.
├── Dockerfile
├── go.mod
├── svc.go
└── vo
    └── vo.go

1 directory, 4 files

svc.go文件中,已声明了一个接口供您定义映射Protobuf RPC的方法。 vo软件包是为您定义结构以映射Protobuf消息。

设计服务

然后我们有一个svc.go文件。

有两个//go:generate指令,第12行是用于恢复服务的第13行,第13行是用于GRPC服务的,为方便起见。如果您使用Goland(我最喜欢的IDE),则只需单击绿色箭头即可运行go-doudou命令。

Image description

pageusers是一种示例方法,现在我们摆脱了它并写下自己的文章。

我们还需要在vo软件包中定义personagereqvo和peraceAgerespvo。注意,struct类型输入参数和结果参数在这里必须在vo软件包中声明为go-doudou cli仅扫描包装以获取用于生成Protobuf消息的信息。

第7行中的go-doudou name是一个小型CLI工具,用于创建或更新每个结构中每个字段的JSON标签,默认为较低的骆驼盒。

生成代码

现在,我们可以运行go-doudou svc grpc命令来生成原始文件,服务器和客户端存根代码。

➜  go-stats git:(master) ✗ tree -L 3 -a
.
├── .dockerignore
├── .env
├── .gitignore
├── Dockerfile
├── cmd
│   └── main.go
├── config
│   └── config.go
├── db
│   └── db.go
├── go.mod
├── svc.go
├── svcimpl.go
├── transport
│   └── grpc
│       ├── annotation.go
│       ├── gostats.pb.go
│       ├── gostats.proto
│       └── gostats_grpc.pb.go
└── vo
    └── vo.go

13 directories, 16 files

我们可以看到还有更多的文件夹和文件生成。

  • .dockerignore:忽略**/*.local文件
  • .env:dotenv配置文件
  • cmd:有main.go作为入口点
  • config:映射环境变量config struct
  • db:对于数据库连接,在此处无用
  • svcimpl.go:实施您自己的业务逻辑
  • transport:原始文件,服务器和客户量存根代码

在潜入代码之前,我们应该运行go mod tidy下载依赖项。然后,我们启动该程序,以确保一切正常工作到现在。

go-doudou依靠go.uber.org/automaxprocs来有效使用资源,因此您可以看到第2行。

让我们打开transport/grpc/gostats.proto文件并解释代码。

正如我们所看到的,每个消息中的所有字段名称均为较低的骆驼盒,这不是常规的蛇案例,因为VO包中的所有JSON标签都是较低的骆驼盒。当然,您可以双方使用Snake Case,但是您必须使它们彼此一致,否则您可能必须将Protoc生成的结构转换为Vo struct(如果您使用VO structs)。

go-doudou将把所有结果参数包裹起来,但在生成proto文件时,错误将错误纳入一条消息,例如largenremainderrpcrespsess,并将所有注释复制到其中。

go-doudou仅支持Protobuf V3 Grammer。

实施存根

现在,我们将在svcimpl.go文件中实现我们的业务逻辑。让我们看看现在有什么。

代码行13分配A *gostatsimpl type nil nil到接口类型pb.gostatsserviceserver,以确保指针类型Gostatsimpl始终实现PB.GostatsServiceserver界面。

,如果需要的话,我们可以将任何字段添加到gostatsimpl,例如外部服务客户端实例,数据库连接实例,任何队列或池实例等。有一个软件包级别的出厂函数newGostats供您注入任何依赖关系并创建指针类型Gostatsimpl实例以后使用。

现在让我们实现lastremainderrpc方法。这是您不必直接实现PB。 Gateway和Grpc-Web,首先实现GOSTAT可以让您重复使用代码以在将来必要时添加剩余端点。

因此,即使您目前不需要休息,我们也更喜欢一开始运行go-doudou svc http -c

Image description

当前的项目结构看起来像这样。

  go-stats git:(master)  tree -L 3   
.
├── Dockerfile
├── client
│   ├── client.go
│   ├── clientproxy.go
│   └── iclient.go
├── cmd
│   └── main.go
├── config
│   └── config.go
├── db
│   └── db.go
├── go.mod
├── go.sum
├── gostats_openapi3.go
├── gostats_openapi3.json
├── svc.go
├── svcimpl.go
├── transport
│   ├── grpc
│   │   ├── annotation.go
│   │   ├── gostats.pb.go
│   │   ├── gostats.proto
│   │   └── gostats_grpc.pb.go
│   └── httpsrv
│       ├── handler.go
│       ├── handlerimpl.go
│       └── middleware.go
└── vo
    └── vo.go

8 directories, 21 files

我们可以看到用于实现Restful的go-doudou生成的httpsrv软件包。我们可以简单地将其删除或将其留在那里。然后让我们看看svcimpl.go文件中发生了什么。

我们可以看到第17行,第36-42行是新代码。第17行是用于确保指针类型Gostatsimpl始终实现Gostats接口。第36-42行是我们完成的存根代码。

go-doudou为我们提供了github.com/unionj-cloud/go-doudou/v2/toolkit/numberutils软件包中的助手功能。我们在这里省略了算法解释,因为这不是关注的问题。

现在,我们可以实现这样的tashremainderrpc方法:

我们不必担心手动从Protoc生成的struct转换为Vo struct,因为一个字段与另一个字段具有相同的JSON标签,因此我们可以在github.com/unionj-cloud/go-doudou/v2/toolkit/copier软件包中使用DeepCopy函数来帮助我们进行转换。

测试服务

我们再次开始服务。不要忘记运行go mod tidy,因为我们在编码时生成了新代码并导入了新的依赖项。

  go-stats git:(master)  go mod tidy && go run cmd/main.go
2022/11/23 13:18:13 maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined
                           _                    _
                          | |                  | |
  __ _   ___   ______   __| |  ___   _   _   __| |  ___   _   _
 / _` | / _ \ |______| / _` | / _ \ | | | | / _` | / _ \ | | | |
| (_| || (_) |        | (_| || (_) || |_| || (_| || (_) || |_| |
 \__, | \___/          \__,_| \___/  \__,_| \__,_| \___/  \__,_|
  __/ |
 |___/
2022-11-23 13:18:13 INF ================ Registered Services ================
2022-11-23 13:18:13 INF +------------------------------------------+----------------------+
2022-11-23 13:18:13 INF |                 SERVICE                  |         RPC          |
2022-11-23 13:18:13 INF +------------------------------------------+----------------------+
2022-11-23 13:18:13 INF | go_stats.GoStatsService                  | LargestRemainderRpc  |
2022-11-23 13:18:13 INF | grpc.reflection.v1alpha.ServerReflection | ServerReflectionInfo |
2022-11-23 13:18:13 INF +------------------------------------------+----------------------+
2022-11-23 13:18:13 INF ===================================================
2022-11-23 13:18:13 INF Grpc server is listening at [::]:50051
2022-11-23 13:18:13 INF Grpc server started in 1.001238ms

就个人而言,我更喜欢使用evans测试GRPC。

  go-stats git:(master)  evans -r repl -p 50051

  ______
 |  ____|
 | |__    __   __   __ _   _ __    ___
 |  __|   \ \ / /  / _. | | '_ \  / __|
 | |____   \ V /  | (_| | | | | | \__ \
 |______|   \_/    \__,_| |_| |_| |___/

 more expressive universal gRPC client


go_stats.GoStatsService@127.0.0.1:50051> show service
+----------------+---------------------+-----------------+-----------------------------+
|    SERVICE     |         RPC         |  REQUEST TYPE   |        RESPONSE TYPE        |
+----------------+---------------------+-----------------+-----------------------------+
| GoStatsService | LargestRemainderRpc | PercentageReqVo | LargestRemainderRpcResponse |
+----------------+---------------------+-----------------+-----------------------------+

go_stats.GoStatsService@127.0.0.1:50051> service GoStatsService

go_stats.GoStatsService@127.0.0.1:50051> call LargestRemainderRpc
<repeated> data::value (TYPE_INT32) => 20
<repeated> data::key (TYPE_STRING) => apple
<repeated> data::value (TYPE_INT32) => 30
<repeated> data::key (TYPE_STRING) => banana
<repeated> data::value (TYPE_INT32) => 40
<repeated> data::key (TYPE_STRING) => pear
<repeated> data::value (TYPE_INT32) => 
places (TYPE_INT32) => 2
{
  "data": [
    {
      "key": "apple",
      "percent": 22.22,
      "percentFormatted": "22.22%",
      "value": 20
    },
    {
      "key": "banana",
      "percent": 33.33,
      "percentFormatted": "33.33%",
      "value": 30
    },
    {
      "key": "pear",
      "percent": 44.45,
      "percentFormatted": "44.45%",
      "value": 40
    }
  ]
}

请参阅,我们输入苹果20公斤,香蕉30kg,梨40kg,我们想要2位数字,然后我们得到预期的结果,结果是22.22 + 33.33 + 44.45 = 100。

概括

在本教程中,我们了解了如何使用Go-Doudou Microservice Framework开发GRPC服务的基本技能。 go-doudou不仅可以帮助您构建GRPC服务以实现业务逻辑,还包含了充满服务的政府功能,以帮助您构建整个微服务系统。 go-doudou年轻,但非常有前途,希望越来越多的开发人员能够加入我们的贡献。