小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

go-zero超强工具goctl的常用命令api,rpc,model及其构建的服务解析

# go-zero,golang,rpc,go-zero,微服务 额外说明

收录于:22天前

goctl api

详细搬家:

归零路由机制分析
基于go-zero和gin的api服务分析对比

goctl rpc

goctl支持多种rpc,比较流行的一种是Google开源的grpc。这里主要介绍goctl rpc protoc的代码生成和使用。

protoc是grpc命令,用于将proto缓冲区文件转换为相应语言的代码。这里gocrl集成了proto buffer。

在这里插入图片描述

--go_out--go-grpc_out分别是生成的pb文件和_grpc.pb文件的目录。

使用protoc命令的前提是有一个proto文件,如下:

syntax = "proto3";

package pb;

option go_package = "./pb";

//获取某用户的认证详细信息
message IdentifyDetailReq{
    
  string Id = 1;
}

message Detail{
    
  string Id = 1;            //客户id
  string Contacts = 2;      //企业联系人
  string Corporation = 3;   //企业联系人身份证号
  int64 Status = 4;         //认证状态 0-待审核;1-已通过;2-未通过
  string CompanyName = 5;   //企业名称
  string Phone = 6;         //企业联系人电话
  string Address = 7;       //通讯录地址
  string Reason = 8;        //认证不通过理由
  int64 Type = 9;           //企业证件类型 0-营业执照三证合一;1-营业执照非三证合一;2-非营业执照
  string qualifications = 10;//企业资质信息
}
message IdentifyDetailResp{
    
  Detail IdentifyInfo = 1;
}

service Identify{
    
  rpc IdentifyDetail(IdentifyDetailReq) returns (IdentifyDetailResp);
}

初始项目目录如下:
在这里插入图片描述
执行命令:
goctl rpc protoc test.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.

在这里插入图片描述
生成目录文件
在这里插入图片描述
grpc最主要的文件是pb文件,rpc远程调用都基于这两个文件。

goctl rpc 生成的go文件和grpc不并不一样,zero对grpc进一步分装,且封装的库放在github.com/zeromicro/go-zero/zrpc中。

原生grpc
和原生grpc使用不同的是:

  1. 开发者自定义UnimplementedXXXServer的实现类

  2. 重写指向UnimplementedXXXServer实现类的所有方法。

  3. 编写服务器端代码并​​注册所有实现的方法

  4. 客户端调用该方法。

在proto文件生成的_grpc.pb文件自定义的接口:
在这里插入图片描述
需要新建该类的实现类并重写所有方法,完成特定功能。由于返回值参数都是在pb文件中,具备任何两个pb文件的够可以构建该同名称函数的rpc远程调用,并返回参数后序列化。

另外需要注意的是,grpc生成的pb文件的客户端和服务端都需要开发者自己编写。

gRPC远程调用服务器与客户端连接详解

零gpc

Go-zero进一步封装了grpc,完成了pb文件的生成和服务端代码的生成。自动生成的目录如下:

在这里插入图片描述

grpc 本机命令仅生成两个 pb 文件。

goctl rpc proto 生成 4 个目录和一个 rpc 服务器启动程序。第二个目录是grpc客户端代码的进一步封装,是一个定制的客户端。

使用goctl rpc proto生成的代码,可以快速构建rpc应用程序并方便地使用rpc客户端。另外zero还集成了etcd,不需要开发者操作。你仍然可以使用 goctl 一键生成。

pb文件不再详细描述。这是第二步看grpc的使用。实现接口方法并注册该方法。零方法的实现同样使用了服务层和逻辑层的调用方式,如下:

  1. server目录实现了_grpc.pb的所有方法,但是在方法中并没有写具体实现,而是直接调用了logic层。
    在这里插入图片描述
  2. 逻辑层具体实现

在这里插入图片描述

这种封装只隐藏了一个输入参数。当然,你也可以用逻辑实现完整的代码,直接在服务点调用,跳过服务器。

唠叨grpc第三步,服务端代码编写与接口注册,这一步也是由goctl生成的。在grpc中一般是调用_grpc.pb中的RegisterXXXServer方法参数为一个初始化的grpc服务端,可以接口。

在这里插入图片描述
第一个参数来自grpc目录(zero集成了grpc),第二个参数也在_grpc.pb为包含自定义方法的接口。
在这里插入图片描述

在go-zero中也是直接实现了服务端编写,查看源码都可以发现实现服务端构建都是使用了zrpc.MustNewServer方法,源码如下:

// A RpcServer is a rpc server.
type RpcServer struct {
    
	server   internal.Server
	register internal.RegisterFn
}

// MustNewServer returns a RpcSever, exits on any error.
func MustNewServer(c RpcServerConf, register internal.RegisterFn) *RpcServer {
    
	server, err := NewServer(c, register)
	logx.Must(err)
	return server
}

该方法传入了RpcServerConf服务端配置,肯定是必须的,要设置ip监听端口等;第二个参数呢是一个是一个参数为grpc.Server的函数,显然安装常规的构建服务端方法,就差一个接口了。

在这里插入图片描述
那么主要在这个方法内部调用pb的注册方法就可以了,看到zero的代码

在这里插入图片描述
调用了_grpc.pb方法注册,但不同的是第二个参数,并不是_grpc.pb的接口,而是server目录的封装的方法。

注册方法的参数是两个接口,可以是任意类型,但是第一个参数必须是grpc.Server

这里zero有一次并没有传入接口,而是自定义的结构体,结构体的方法被注册到grpc服务端。
在这里插入图片描述
pb.UnimplementedIdentifyServer构建grpc服务端的关键,重写了其方法,将其子类通过注册的方式注册到grpc服务端。

以上就是零零对grpc的封装过程。 Goctl直接实现了构建grpc服务的前三步。开发者只需要编写实现逻辑和少量配置。也就是说,goctl生成的rpc服务只需要简单的两个步骤:

  1. 在yaml配置文件配置zrpc.RpcServerConf所需要的参数

在这里插入图片描述
2. logic层编写方法实现的具体逻辑

在这里插入图片描述

上面是go-zero rpc服务器。

其实客户端goctl也生成了。原生grpc创建并实现客户端,有以下几个步骤: 1、配置客户端连接参数; 2. 实例化客户端对象。

源码也在_grpc.pb文件中:

在这里插入图片描述

图中的转换过程有点复杂,界面和界面变化较多。这并不容易理解。目前,您只知道如何使用它。

//配置连连接参数(无加密)
dial, err := grpc.Dial("localhost:1099", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
    
	println("failed grpc connect", err)
}
defer dial.Close()
//创建客户端连接
client := protoInterface.NewInterfaceClient(dial)
//通过客户端调用方法
res, err := client.GetProduct(context.Background(), &protoInterface.Request{
    
	ParamString: "hello",
})

在上述代码中最核心的就是grpc.Dial这步,创建grpc连接,后续调用pb的NewXXXClient传入该参数就得到了一个客户端对象就可以调用方法了。

归零客户端

零的进一步封装,参见零源码(一般是生成文件的第二个目录,即etc下的目录文件就是客户端的封装)。

在这里插入图片描述

第一个表示接口方法是pb客户端方法,第二个是客户端的封装,第三个是创建客户端方法,第四个是方法实现。其实这些都可以在原生pb grpc客户端中概括。完全一样,只是名字不同而已。

那么显然不能再用gprc原生的内容了,使用这些包装的rpc客户端也很简单,显然NewIdentify是构建客户端实例的方法,就差连接对象了。查看zrpc.Client源码如下:

在这里插入图片描述
再查看internal.Client源码:

在这里插入图片描述
巧了吗这不是,到头来还是自己,却有三个名。
在这里插入图片描述
到此思路就清晰了。

实例化一个zrpc.Client或者直接使用grpc.Dial需要注意的是zrpc.Client类型和同款类型是一个接口啊,没法像接口那样直接实例化,需要通过另一个方法实例化

直接在zrpc库中找到就可以了

在这里插入图片描述

官方推荐

conn := zrpc.MustNewClient(zrpc.RpcClientConf{
    
	Target: "dns:///127.0.0.1:8080",
})

zrpc.MustNewClient方法可以实例化,其参数是一个zrpc.RpcClientConf结构体。这个参数可以配置在config目录下额文件中,通过配置获取。

到此也可以明白这莫多层的封装的意义了把,就是把下面这些配置集成了grpc中,并能通过yaml文件配置。
在这里插入图片描述

获取到客户端对象实例后,如何直接调用方法来获取服务器返回的数据库呢?只需确保服务器已启动即可。

在这里插入图片描述

集成etcd

上述过程还未使用etcd的服务注册与发现功能,可以看到上之前的一些配置类中如服务端zrpc.RpcServerConfzrpc.RpcClientConf均出现了Etcd的配置类,在go-zero中使用etcd也是十分方便。一般有如下几个步骤:

  1. 安装etcd并确保其正常运行
  2. rpc服务器搭建etcd心跳客户端,持续发送心跳、上传数据
  3. rpc客户端构建etcd普通客户端来获取数据。

go-zero中使用etcd和单独使用没有太大区别,主要是在配置文件上。

详情请移步实践中的零零微服务 - etcd 服务注册和发现

goctl model

goctl模型支持多种数据库,比较常用的是mysql。这里主要介绍goctl模式mysql的代码生成和使用。

在这里插入图片描述
参考

goctl model mysql datasource -url="user:password@tcp(127.0.0.1:3306)/database" -table="table1,table2"  -dir="./model"

运行命令后会在指定的目录下生成三个文件
在这里插入图片描述
其中usermodel.go是用户自定义的DML,DQL,开发者可在此处定义自己编写的sql查询语句;usermodel_gen.go是goctl自动生成的DML,DQL实现了数据库的基本操作即CRUD操作;第三个var.go就是自定义的数据库操作失败的返回值和其他参数。

goclt自动生成数据库引擎,在goctl model mysql命令的datasource参数就是配置数据库引擎的参数。接下来会参数如何使用。

可以看到user_mode_gen.go的userModel接口定义了很多方法:

在这里插入图片描述

而这些接口最终都指向了defaultUserModel

在这里插入图片描述
转到defaultUserModel的定义

defaultUserModel struct {
    
	sqlc.CachedConn
	table string
}

该结构定义了缓存和表名称,它们作为命令参数传递。

同一个源文件下也提供了实例化方法:

func newUserModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultUserModel {
    
	return &defaultUserModel{
    
		CachedConn: sqlc.NewConn(conn, c, opts...),
		table:      "`user`",
	}
}

通过该方法创建defaultUserModel的实例,然后通过该方法创建实例就可以调用该接口的所有方法。但你可以看到这个方法是私有的。

在这里插入图片描述
xxxmodel.go文件下也有一个NewUserModel方法是公开的,如下:

// NewUserModel returns a model for the database table.
func NewUserModel(conn sqlx.SqlConn) UserModel {
    
	return &customUserModel{
    
		defaultUserModel: newUserModel(conn),
	}
}

该方法对defaultUserModel进行了多次封装,并返回用newUserModel构建的defaultUserModel。开发人员可以使用NewUserModel来调用模型生成的方法。

在这里插入图片描述

在defaultUserModel的多重封装过程中,出现了以下接口和结构体:

在这里插入图片描述
UserModel接口内嵌userModel显然是其子接口,继承了userModel的方法且是公开的。customeUserModel也是defaultUserModel子类,并只能通过NewUserModel方法调用。显然该层继承是为了方便开发者拓展model层,实现自定义sql操作数据库。

定制模型的一般步骤包括: 1、在xxxmodel的接口中定义方法; 2、在同一个包中实现该方法,并指向defaultUserModel的实现类。

在这里插入图片描述

您可以直接使用NewUserModel调用自定义方法,如下所示:

在这里插入图片描述

自定义操作数据库的方法

除了上述使用goctl的model规范操作数据库外,也可以通过自定义的方法操作数据库。会看model的的代码,其中操作数据库的核心就是sqlx.SqlConn

这里的sqlx来源与zero的库"github.com/zeromicro/go-zero/core/stores/sqlx"

在sqlx中有一个NewMysql方法返回sqlx.SqlConn实例,就可以直接通过该方法返回的对象直接操作数据库。

var mysql = sqlx.NewMysql(datasource)

func Test2(t *testing.T) {
    
	mysql := sqlx.NewMysql("username:password@tcp(ip:3306)/databasename?charset=utf8mb4&parseTime=True")
	sql_ := "select * from user"
	user := User{
    }
	mysql.QueryRowCtx(context.Background(), &user, sql_)
	fmt.Println(user)
}

只需调用sqlx.SqlConn实例即可操作数据库。

集成第三方框架

也可以整合一些第三方框架如gorm,xorm等,这就比较简单了,go get [address]安装。1. 封装工具类,暴露数据库引擎实例;2. 通过实例方法操作数据库。

gin、iris、beego等框架都可以通过同样的方式集成xorm,这里不再赘述。

. . .

相关推荐

额外说明

Maven打包springboot项目插件 spring-boot-maven-plugin

在不使用spring-boot-maven-plugin插件打包springboot的web项目生成的jar包是无法直接运行的。因为直接打包的jar包仅仅是一个普通的jar包,没有打包依赖也没有指定main-class,所以无法直接运行。 所以需要在po

额外说明

IDEA中如何断点调试

文章目录 1. 设置断点 2. 调试 3. 调试的基本操作 3.1 step over 3.2 step into 跟 Force step into 3.3 step out 3.4 resume program 3.5 mute breakpoint

额外说明

Java高并发-线程池原理(架构思想)

最近在学线程池,了解线程池的原理,对以后学习多线程有更好的理解。 目录 线程、线程任务的关系 为什么要使用线程池 线程池的实现原理 线程池的类型 优化接口实战 线程、线程任务的关系 开启线程,执行任务的流程: 1.创建线程任务;(三种方法) 1.继承Th

额外说明

【Python入门教程】第38章filter()函数

本篇我们将会学习使用 Python 内置的 filter() 函数过滤列表中的元素。 filter() 函数简介 有时候我们需要对列表中的元素进行遍历并基于指定条件选择某些元素。 加入存在以下列表: scores = [70, 60, 80, 90, 5

额外说明

winform程序textbox滚动条保持在最下面 内容不闪烁

感谢博主 帮我解决了问题 自己摘抄记录一下 在开发winform程序时,会用到textbox控件来显示信息,当把textbox的Multiline属性改为Ture时(即多行显示状态),ScrollBars属性改为Vertical(内容过多时,显示竖状滚动

额外说明

4.Python基础语法(二)【常用标准库概览】

目录: Python基础语法(二) 11. Python3 标准库概览 11.1 文件通配符 11.2 命令行参数 ①命令行参数: ②标准输入输出函数 延伸—标准输入、输出和错误流文件对象 11.3 访问互联网 11.4 日期和时间 Python基础语法

额外说明

VanillaNet实战:使用VanillaNet实现图像分类(二)

文章目录 训练部分 导入项目使用的库 设置随机因子 设置全局参数 图像预处理与增强 读取数据 设置Loss 设置模型 设置优化器和学习率调整算法 设置混合精度,DP多卡,EMA 定义训练和验证函数 训练函数 验证函数 调用训练和验证方法 运行以及结果查看

额外说明

[Ext JS 4] 拖放[drag and drop]

定义拖放 一个拖动操作,就是在某个页面元素上按下鼠标并移动。一个放下操作,就是在拖动动作之后放开鼠标。可以从下图来看: Ext JS 的Ext.dd 类中定义了基本的拖放操作。 拖放类的组织 所有的拖放类基本上都归类到Drag or  Drop 组中

额外说明

MySQL实战 | MySQL日志模块—redo log和 binlog

一个更新语句执行的时候整个过程跟查询的步骤是类似的,具体可以看之前的文章:MySQL实战 | MySQL逻辑架构—一条查询SQL是如何执行的,在一个表上有更新的时候,跟这个表有关的查询缓存会失效,所以这条语句就会把表上所有缓存结果都清空。这也就是我们一般

额外说明

mfc110enu.dll文件丢失找不到如何解决?

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或者损坏了,这时你只需下载这个mfc110enu.dll文件进行安装(前提是找到适合的版本)

ads via 小工具