惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
Cisco Talos Blog
Cisco Talos Blog
MongoDB | Blog
MongoDB | Blog
IT之家
IT之家
N
News and Events Feed by Topic
博客园 - 叶小钗
Help Net Security
Help Net Security
美团技术团队
Attack and Defense Labs
Attack and Defense Labs
雷峰网
雷峰网
S
Security @ Cisco Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
AI
AI
Hacker News: Ask HN
Hacker News: Ask HN
T
The Blog of Author Tim Ferriss
Security Latest
Security Latest
Last Week in AI
Last Week in AI
S
Secure Thoughts
Simon Willison's Weblog
Simon Willison's Weblog
TaoSecurity Blog
TaoSecurity Blog
N
News and Events Feed by Topic
A
Arctic Wolf
Y
Y Combinator Blog
MyScale Blog
MyScale Blog
Cyberwarzone
Cyberwarzone
酷 壳 – CoolShell
酷 壳 – CoolShell
S
SegmentFault 最新的问题
罗磊的独立博客
Vercel News
Vercel News
D
DataBreaches.Net
博客园 - 聂微东
P
Palo Alto Networks Blog
N
News | PayPal Newsroom
GbyAI
GbyAI
B
Blog
A
About on SuperTechFans
PCI Perspectives
PCI Perspectives
S
Schneier on Security
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
The GitHub Blog
The GitHub Blog
P
Privacy International News Feed
Blog — PlanetScale
Blog — PlanetScale
博客园_首页
T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
aimingoo的专栏
aimingoo的专栏
Google DeepMind News
Google DeepMind News

Chenxu's Blog

RAG检索优化:从 68% 到 82.2% 学习深度学习 北邮计算机研究生选课指北 学习机器学习 上海篇 提出一个好问题 写代码的环境 选购一台合适的设备 计算机的第零课 序言 内蒙古篇 山东篇 一篇对transformers的疑惑 浅析GPUStack 浅谈后端项目分层 浙江篇 河南篇 一些三端协同的开发工具记录 浅谈编程语言中的 GC 在 Windows 上安装 Rust 美化博客 消息队列 MyBatis 现代交换原理2024年题目 回忆版 北邮计科本科课程指北 ClkLog埋点用户分析系统研究报告 大数据梧桐实验分享 大数据HBase实验分享 国产向量数据库研究实践 —— 基于 Milvus 的电影推荐系统 服务器环境配置 大数据HDFS实验分享 SSE多服务之间推送数据 数据库系统原理 操作系统 编译原理 手把手教你gozero从开发到部署 (番外篇): 介绍 gtodolist 前端项目 天津篇 北京篇 手把手教你gozero从开发到部署 (5): gtodolist 之任务的删除 前端相关问题 vue3 + element-plus学习 git相关命令 人工智能原理 使用 MongoTemplate 时开启事务 MySQL Redis 力扣刷题笔记之动态规划 记录一次 VSCode 出现的各种奇怪的问题 手把手教你gozero从开发到部署 (4): 在 model 中自己编写函数实现数据库分页查询 记录平时用到的 windows 右键管理 记录平时使用的 linux 的指令 安装 gstore 并使用 java api 手把手教你gozero从开发到部署 (3): gtodolist 之任务的创建和修改 手把手教你gozero从开发到部署 (番外篇): 记录第一次部署 CI/CD 的流程 记录完成 gtodolist 中遇到的 bug 手把手教你gozero从开发到部署 (2): gtodolist 之 user 模块开发 手把手教你gozero从开发到部署 (1): gtodolist 项目说明和环境准备 vue部署在nginx上的相关问题 记一次安装scrapy的报错 将博客部署至服务器 Java CS143: Compliers 《MySQL必知必会》读书笔记(2) 初识 GORM 初识 gin 框架 Spring 《MySQL必知必会》读书笔记(1) 本地搭建博客 🤝友链 🙋🏻‍♂️关于 Browser and Device Check
快速入门 gozero 框架
Chenxu · 2023-08-28 · via Chenxu's Blog

依旧推荐官方文档: 快速开始指南

安装

安装 goctl

go install github.com/zeromicro/go-zero/tools/goctl@latest

安装完成后在你的 ${GOPATH}/bin 目录下会有一个 goctl.exe 文件, 执行 goctl --version 出现版本信息即安装成功 (如果出现类似于找不到命令的报错的话, 那么需要将 ${GOPATH}/bin 目录添加到环境变量中)

PS D:\goprojects> goctl --version
goctl version 1.5.4 windows/amd64

安装工具包

goctl env check --install --verbose --force

这里可能会因为某些原因安装失败, 如果是 windows 系统的话, 那可以直接在 这里 下载压缩包, 下载完成后只需要将压缩包中的文件夹移到 ${GOPATH} 目录下即可

其他系统的话可以选择手动安装三个工具:

protoc 需要前往 github 下载安装包, 然后同样直接把安装包里面的文件放到你的 ${GOPATH} 目录下即可

# proto-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

安装完成后进行验证

PS D:\goprojects> goctl env check --verbose
[goctl-env]: preparing to check env

[goctl-env]: looking up "protoc"
[goctl-env]: "protoc" is installed

[goctl-env]: looking up "protoc-gen-go"
[goctl-env]: "protoc-gen-go" is installed

[goctl-env]: looking up "protoc-gen-go-grpc"
[goctl-env]: "protoc-gen-go-grpc" is installed

[goctl-env]: congratulations! your goctl environment is ready!

安装 gozero

在一个有 go mod 的项目下执行 go get 获取 gozero

$ mkdir usercenter && cd usercenter
$ go mod init usercenter
$ go get -u github.com/zeromicro/go-zero@latest

如果报错的话可能是因为没有开启 gomod 或者是网络问题:

$ go env -w GO111MODULE=on # 开启 gomod 模式
$ go env -w GOPROXY=https://goproxy.cn,direct # 设置代理

单体服务写法

编写 api 文件

gozero 是根据 api 文件 来生成代码, 所以我们使用上面生成的 usercenter 项目, 并写一个简单的 api demo

usercenter 目录下新建 api 目录, 在 api 目录中新建 user.api 文件, 写入以下内容

syntax = "v1"

info(
	title: "Usercenter API"
	desc: "API for usercenter"
	author: "GuoChenxu"
	email: "guochenxu11@outlook.com"
	version: "1.0"
)

// 定义数据结构
type (
	PingReq {
		Id int64 `path:"id"`
	}
	PingResp {
		Pong string `json:"string"`
	}
)

// 这里定义了路径前缀, 此外还可以定义jwt 开关、中间件、路由分组、路由前缀等
// server 对下面 service 中的所有服务有效
@server(
	prefix: user
)

// 定义具体的服务请求路径
service user {
	@doc "ping"
	@handler ping
	get /ping/:id (PingReq) returns (PingResp)
}

参数的 tag 和传参形式的对应:

tag 传参形式
path Path 传参
form Query 传参
json Body 传参

生成代码

在 api 文件所在目录下生成代码

# --api 指定 api 文件
# --dir 指定生成代码目录
# --style 指定命名风格
PS D:\goprojects\src\usercenter\api> goctl api go --api .\user.api --dir .\ --style=go_zero
Done.

注意, 有些同学 比如我 用了 gowork 管理项目, 那么在生成代码之前需要将项目加到 gowork 文件中 具体代码如下:

# .\src\ 是你的项目目录
go work use -r .\src\

现在的文件目录如下:

D:\GOPROJECTS\SRC\USERCENTER
│  go.mod
│  go.sum
└─api
    │  user.api  # api 文件
    │  user.go   # 项目入口文件
    ├─etc
    │      user.yaml   # 配置文件
    └─internal
        ├─config
        │      config.go   # 读取配置
        ├─handler   # 路由
        │      ping_handler.go
        │      routes.go
        ├─logic   # 核心逻辑
        │      ping_logic.go
        ├─svc   # 上下文
        │      service_context.go
        └─types   # 项目中的数据结构
                types.go

编写逻辑代码

gozero 的魅力在于他几乎生成了所有其他的代码, 你只需要关注最核心的逻辑代码

打开 internal/logic/ping_logic.go 开始编写代码

func (l *PingLogic) Ping(req *types.PingReq) (resp *types.PingResp, err error) {
	id := strconv.FormatInt(req.Id, 10)
	return &types.PingResp{
		Pong: "pong: " + id,
	}, nil
}

运行项目

PS D:\goprojects\src\usercenter\api> go run .\user.go
Starting server at 0.0.0.0:8888...

因为默认的 json 格式日志不好看, 所以我们在 etc/user.yaml 中修改日志格式

Name: user
Host: 0.0.0.0
Port: 8888

Log:
  Encoding: plain

成功响应:

日志打印:

至此一个简单的单体 demo 就写完了

rpc 服务写法

编写 proto 文件

与 api 文件类似, rpc 是根据 proto 文件 生成代码

usercenter 目录下新建 rpc 目录, 在 rpc 目录中新建 user.proto 文件, 写入以下功能

syntax = "proto3";

package pb;
option go_package="./pb";

// 定义消息类型
message Request {
  int64 id = 1;
}

message Response {
  string Pong = 1;
}

// 定义服务
service userrpc {
  rpc Ping(Request) returns(Response);
}

生成代码

在 proto 文件目录下生成代码

# protoc 指定 proto文件
# *_out  指定代码文件的输出目录
PS D:\goprojects\src\usercenter\rpc> goctl rpc protoc .\user.proto --go_out=.\ --go-grpc_out=.\ --zrpc_out=.\ --style=go_zero
Done.

文件目录

D:\GOPROJECTS\SRC\USERCENTER
│  go.mod
│  go.sum
├─api
└─rpc
    │  user.go
    │  user.proto
    ├─etc
    │      user.yaml
    ├─internal
    │  ├─config
    │  │      config.go
    │  │
    │  ├─logic
    │  │      ping_logic.go
    │  │
    │  ├─server
    │  │      userrpc_server.go
    │  │
    │  └─svc
    │          service_context.go
    ├─pb
    │      user.pb.go
    │      user_grpc.pb.go
    └─userrpc
            userrpc.go

安装 etcd

rpc 默认生成的代码是使用 etcd 注册发现服务的, 所以还需要安装 etcd

前往 github 下载合适的版本, 解压后放在合适的目录下, 并添加进环境变量

验证安装成功

PS D:\Tools\etcd> etcd --version
etcd Version: 3.5.9
Git SHA: bdbbde998
Go Version: go1.19.9
Go OS/Arch: windows/amd64

启动 etcd

如果你在尝试了 下载最新版本、使用管理员权限运行、启动端口没有被占用、关闭防火墙 之后仍旧无法正常启动 etcd, 那么请重启电脑后再次运行

编写逻辑代码

编写 rpc 目录下的 internal/logic/ping_logic.go

func (l *PingLogic) Ping(in *pb.Request) (*pb.Response, error) {
	id := strconv.FormatInt(in.Id, 10)
	return &pb.Response{
		Pong: "pong: " + id,
	}, nil
}

运行项目

修改一下项目的运行端口, etcd 的监听地址和 log 格式

Name: user.rpc
ListenOn: 0.0.0.0:8889
Etcd:
  Hosts:
    - 0.0.0.0:2379
  Key: user.rpc

Log:
  Encoding: plain

运行项目

单独测试 rpc 服务

你可以对每个 rpc 服务都写一个客户端进行测试, 但是这样过于繁琐, 所以我们希望可以单独对 rpc 服务进行测试

这里推荐 apifox (最新版), 可以像 http 接口一样测试 rpc 服务

  1. 点击新建项目, 选择新建 gRpc 项目

  2. 点击左上角加号, 直接导入 proto 文件

  3. 然后就可以像普通的 http 接口一样发送请求进行测试

测试成功

单体项目升级成微服务

在编写了 rpc 服务之后, 我们可以将之前的 api 单体服务升级成微服务项目

服务发现

现在下述操作均在 api 目录下执行

打开 etc/user.yaml 增加如下配置

Name: user
Host: 0.0.0.0
Port: 8888

Log:
  Encoding: plain

# 客户端 etcd 配置
UserRpcConfig:
  Etcd:
    Hosts:
      - 127.0.0.1:2379
    Key: user.rpc

internal/config/config.go 文件中增加配置

package config

import (
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
)

type Config struct {
	rest.RestConf
	UserRpcConfig zrpc.RpcClientConf   // 读取 rpc 配置
}

internal/svc/service_context.go 文件中增加代码

package svc

import (
	"usercenter/api/internal/config"
	"usercenter/rpc/userrpc"

	"github.com/zeromicro/go-zero/zrpc"
)

type ServiceContext struct {
	Config        config.Config
	UserRpcClient userrpc.Userrpc   // 注册 rpc 客户端
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config:        c,
		UserRpcClient: userrpc.NewUserrpc(zrpc.MustNewClient(c.UserRpcConfig)),
	}
}

至此客户端的服务发现已经配置完成

修改核心代码

升级成微服务后就要将逻辑代码交给 rpc 服务端去做, 客户端需要给服务端发送请求, 所以需要修改核心的逻辑代码

修改 api 目录下的 internal/logic/ping_logic.go 文件

func (l *PingLogic) Ping(req *types.PingReq) (resp *types.PingResp, err error) {
    // 向服务端发送请求
	pong, err := l.svcCtx.UserRpcClient.Ping(l.ctx, &userrpc.Request{
		Id: req.Id,
	})
	return &types.PingResp{
		Pong: pong.GetPong(),
	}, err
}

运行项目

先运行服务端, 再运行客户端

测试成功

查看日志, 确实是服务端接受请求并处理

至此 gozero 的快速入门就结束了, 后续会有文章讲述 在 gozero 中使用 gorm, gozero 的 api 文件编写 以及 在 gozero 中使用 nacos 进行服务的注册发现等 咕咕咕, 先立个 flag

参考文章

快速开始

指南