feat: Support for multiple rpc service generation and rpc grouping (#1972)
* Add group & compatible flag * Add group & compatible flag * Support for multiple rpc service generation and rpc grouping * Support for multiple rpc service generation and rpc grouping * Format code * Format code * Add comments * Fix unit test * Refactor function name * Add example & Update grpc readme * go mod tidy * update mod * update mod
This commit is contained in:
@@ -7,7 +7,7 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
|
||||
* 简单易用
|
||||
* 快速提升开发效率
|
||||
* 出错率低
|
||||
* 贴近protoc
|
||||
* 贴近 protoc
|
||||
|
||||
|
||||
## 快速开始
|
||||
@@ -24,168 +24,41 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
|
||||
|
||||
执行后代码结构如下:
|
||||
|
||||
```golang
|
||||
```text
|
||||
.
|
||||
├── etc // yaml配置文件
|
||||
│ └── greet.yaml
|
||||
├── go.mod
|
||||
├── greet // pb.go文件夹①
|
||||
│ └── greet.pb.go
|
||||
├── greet.go // main函数
|
||||
├── greet.proto // proto 文件
|
||||
├── greetclient // call logic ②
|
||||
│ └── greet.go
|
||||
└── internal
|
||||
├── config // yaml配置对应的实体
|
||||
│ └── config.go
|
||||
├── logic // 业务代码
|
||||
│ └── pinglogic.go
|
||||
├── server // rpc server
|
||||
│ └── greetserver.go
|
||||
└── svc // 依赖资源
|
||||
└── servicecontext.go
|
||||
```
|
||||
|
||||
> ① pb文件夹名(老版本文件夹固定为pb)称取自于proto文件中option go_package的值最后一层级按照一定格式进行转换,若无此声明,则取自于package的值,大致代码如下:
|
||||
|
||||
```go
|
||||
if option.Name == "go_package" {
|
||||
ret.GoPackage = option.Constant.Source
|
||||
}
|
||||
...
|
||||
if len(ret.GoPackage) == 0 {
|
||||
ret.GoPackage = ret.Package.Name
|
||||
}
|
||||
ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
|
||||
...
|
||||
└── greet
|
||||
├── etc
|
||||
│ └── greet.yaml
|
||||
├── greet
|
||||
│ ├── greet.go
|
||||
│ ├── greet.pb.go
|
||||
│ └── greet_grpc.pb.go
|
||||
├── greet.go
|
||||
├── greet.proto
|
||||
└── internal
|
||||
├── config
|
||||
│ └── config.go
|
||||
├── logic
|
||||
│ └── pinglogic.go
|
||||
├── server
|
||||
│ └── greetserver.go
|
||||
└── svc
|
||||
└── servicecontext.go
|
||||
```
|
||||
> GoSanitized方法请参考google.golang.org/protobuf@v1.25.0/internal/strs/strings.go:71
|
||||
|
||||
> ② call 层文件夹名称取自于proto中service的名称,如该sercice的名称和pb文件夹名称相等,则会在srervice后面补充client进行区分,使pb和call分隔。
|
||||
|
||||
```go
|
||||
if strings.ToLower(proto.Service.Name) == strings.ToLower(proto.GoPackage) {
|
||||
callDir = filepath.Join(ctx.WorkDir, strings.ToLower(stringx.From(proto.Service.Name+"_client").ToCamel()))
|
||||
}
|
||||
```
|
||||
|
||||
rpc一键生成常见问题解决,见 <a href="#常见问题解决">常见问题解决</a>
|
||||
|
||||
### 方式二:通过指定proto生成rpc服务
|
||||
|
||||
* 生成proto模板
|
||||
|
||||
```Bash
|
||||
goctl rpc template -o=user.proto
|
||||
```
|
||||
|
||||
```golang
|
||||
syntax = "proto3";
|
||||
|
||||
package remote;
|
||||
|
||||
message Request {
|
||||
// 用户名
|
||||
string username = 1;
|
||||
// 用户密码
|
||||
string password = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
// 用户名称
|
||||
string name = 1;
|
||||
// 用户性别
|
||||
string gender = 2;
|
||||
}
|
||||
|
||||
service User {
|
||||
// 登录
|
||||
rpc Login(Request)returns(Response);
|
||||
}
|
||||
```
|
||||
|
||||
* 生成rpc服务代码
|
||||
|
||||
```Bash
|
||||
goctl rpc proto -src=user.proto
|
||||
```
|
||||
|
||||
## 准备工作
|
||||
|
||||
* 安装了go环境
|
||||
* 安装了protoc&protoc-gen-go,并且已经设置环境变量
|
||||
* 更多问题请见 <a href="#注意事项">注意事项</a>
|
||||
|
||||
## 用法
|
||||
|
||||
### rpc服务生成用法
|
||||
|
||||
```Bash
|
||||
goctl rpc proto -h
|
||||
$ goctl rpc template -o=user.proto
|
||||
```
|
||||
|
||||
```Bash
|
||||
NAME:
|
||||
goctl rpc proto - generate rpc from proto
|
||||
|
||||
USAGE:
|
||||
goctl rpc proto [command options] [arguments...]
|
||||
|
||||
OPTIONS:
|
||||
--src value, -s value the file path of the proto source file
|
||||
--proto_path value, -I value native command of protoc, specify the directory in which to search for imports. [optional]
|
||||
--go_opt value native command of protoc-gen-go, specify the mapping from proto to go, eg --go_opt=proto_import=go_package_import. [optional]
|
||||
--dir value, -d value the target path of the code
|
||||
--style value the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
|
||||
--idea whether the command execution environment is from idea plugin. [optional]
|
||||
|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
* --src 必填,proto数据源,目前暂时支持单个proto文件生成
|
||||
* --proto_path 可选,protoc原生子命令,用于指定proto import从何处查找,可指定多个路径,如`goctl rpc -I={path1} -I={path2} ...`
|
||||
,在没有import时可不填。当前proto路径不用指定,已经内置,`-I`的详细用法请参考`protoc -h`
|
||||
* --go_opt 可选,protoc-gen-go插件原生flag,用于指定go_package
|
||||
* --dir 可选,默认为proto文件所在目录,生成代码的目标目录
|
||||
* --style 可选,指定生成文件名的命名风格
|
||||
* --idea 可选,是否为idea插件中执行,终端执行可以忽略
|
||||
|
||||
|
||||
### 开发人员需要做什么
|
||||
|
||||
关注业务代码编写,将重复性、与业务无关的工作交给goctl,生成好rpc服务代码后,开发人员仅需要修改
|
||||
|
||||
* 服务中的配置文件编写(etc/xx.json、internal/config/config.go)
|
||||
* 服务中业务逻辑编写(internal/logic/xxlogic.go)
|
||||
* 服务中资源上下文的编写(internal/svc/servicecontext.go)
|
||||
|
||||
|
||||
### 注意事项
|
||||
|
||||
* proto不支持暂多文件同时生成
|
||||
* proto不支持外部依赖包引入,message不支持inline
|
||||
* 目前main文件、shared文件、handler文件会被强制覆盖,而和开发人员手动需要编写的则不会覆盖生成,这一类在代码头部均有
|
||||
|
||||
```shell script
|
||||
// Code generated by goctl. DO NOT EDIT!
|
||||
// Source: xxx.proto
|
||||
```
|
||||
|
||||
的标识,请注意不要将也写业务性代码写在里面。
|
||||
|
||||
## proto import
|
||||
* 对于rpc中的requestType和returnType必须在main proto文件定义,对于proto中的message可以像protoc一样import其他proto文件。
|
||||
|
||||
proto示例:
|
||||
|
||||
### 错误import
|
||||
|
||||
```proto
|
||||
syntax = "proto3";
|
||||
|
||||
package greet;
|
||||
|
||||
import "base/common.proto"
|
||||
package user;
|
||||
option go_package="./user";
|
||||
|
||||
message Request {
|
||||
string ping = 1;
|
||||
@@ -195,40 +68,136 @@ message Response {
|
||||
string pong = 1;
|
||||
}
|
||||
|
||||
service Greet {
|
||||
rpc Ping(base.In) returns(base.Out);// request和return 不支持import
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 正确import
|
||||
```proto
|
||||
syntax = "proto3";
|
||||
|
||||
package greet;
|
||||
|
||||
import "base/common.proto"
|
||||
|
||||
message Request {
|
||||
base.In in = 1;// 支持import
|
||||
}
|
||||
|
||||
message Response {
|
||||
base.Out out = 2;// 支持import
|
||||
}
|
||||
|
||||
service Greet {
|
||||
service User {
|
||||
rpc Ping(Request) returns(Response);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 常见问题解决(go mod工程)
|
||||
* 生成rpc服务代码
|
||||
|
||||
* 错误一:
|
||||
```text
|
||||
A required privilege is not held by the client.
|
||||
```bash
|
||||
$ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
|
||||
```
|
||||
这个问题只有goctl 版本在`goctl.exe version 1.2.1` 以后的 Windows操作系统出现,主要原因是goctl需要以管理员身份运行,这样才能将`goctl.exe` 创建一个 `ptocot-gen-gcotl`
|
||||
的符号链接。
|
||||
|
||||
|
||||
## 用法
|
||||
|
||||
### rpc 服务生成用法
|
||||
|
||||
```Bash
|
||||
$ goctl rpc protoc -h
|
||||
Generate grpc code
|
||||
|
||||
Usage:
|
||||
goctl rpc protoc [flags]
|
||||
|
||||
Examples:
|
||||
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
|
||||
|
||||
Flags:
|
||||
--branch string The branch of the remote repo, it does work with --remote
|
||||
-h, --help help for protoc
|
||||
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
|
||||
-m, --multiple Generated in multiple rpc service mode
|
||||
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
|
||||
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
|
||||
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
|
||||
-v, --verbose Enable log output
|
||||
--zrpc_out string The zrpc output directory
|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
* --branch 指定远程仓库模板分支
|
||||
* --home 指定goctl模板根目录
|
||||
* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service,且多个 rpc service 会分组。
|
||||
* --style 指定文件输出格式
|
||||
* -v, --verbose 显示日志
|
||||
* --zrpc_out 指定zrpc输出目录
|
||||
|
||||
> ## --multiple
|
||||
> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性
|
||||
> 1. 支持 1 到多个 rpc service
|
||||
> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service)
|
||||
> 3. rpc client 的文件目录变更为固定名称 `client`
|
||||
>
|
||||
> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容)
|
||||
> 1. 有且只能有一个 rpc service
|
||||
|
||||
|
||||
## rpc 服务生成 example
|
||||
详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example)
|
||||
|
||||
## --multiple 为 true 和 false 的目录区别
|
||||
源 proto 文件
|
||||
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
|
||||
package hello;
|
||||
|
||||
option go_package = "./hello";
|
||||
|
||||
message HelloReq {
|
||||
string in = 1;
|
||||
}
|
||||
|
||||
message HelloResp {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
service Greet {
|
||||
rpc SayHello(HelloReq) returns (HelloResp);
|
||||
}
|
||||
```
|
||||
|
||||
### --multiple=true
|
||||
|
||||
```text
|
||||
hello
|
||||
├── client // 区别1:rpc client 目录固定为 client 名称
|
||||
│ └── greet // 区别2:会按照 rpc service 名称分组
|
||||
│ └── greet.go
|
||||
├── etc
|
||||
│ └── hello.yaml
|
||||
├── hello.go
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── greet // 区别2:会按照 rpc service 名称分组
|
||||
│ │ └── sayhellologic.go
|
||||
│ ├── server
|
||||
│ │ └── greet // 区别2:会按照 rpc service 名称分组
|
||||
│ │ └── greetserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
└── pb
|
||||
└── hello
|
||||
├── hello.pb.go
|
||||
└── hello_grpc.pb.go
|
||||
```
|
||||
|
||||
### --multiple=false (旧版本目录,向后兼容)
|
||||
```text
|
||||
hello
|
||||
├── etc
|
||||
│ └── hello.yaml
|
||||
├── greet
|
||||
│ └── greet.go
|
||||
├── hello.go
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go
|
||||
│ ├── logic
|
||||
│ │ └── sayhellologic.go
|
||||
│ ├── server
|
||||
│ │ └── greetserver.go
|
||||
│ └── svc
|
||||
│ └── servicecontext.go
|
||||
└── pb
|
||||
└── hello
|
||||
├── hello.pb.go
|
||||
└── hello_grpc.pb.go
|
||||
```
|
||||
Reference in New Issue
Block a user