go-zero 基础
官网
github
开发规范
1、环境准备
1.1 goctl安装
1.2 protoc & protoc-gen-go安装
# 方式一
goctl env check -i -f --verbose # 方式二: 源文件安装
2、快速开始
本节主要通过对 api/rpc 等服务快速开始来让大家对使用 go-zero 开发的工程有一个宏观概念,更加详细的介绍我们将在后续一一展开。
2.1 单体服务
由于go-zero集成了web/rpc于一体,社区有部分小伙伴会问我,go-zero的定位是否是一款微服务框架,答案是不止于此, go-zero虽然集众多功能于一身,但你可以将其中任何一个功能独立出来去单独使用,也可以开发单体服务, 不是说每个服务上来就一定要采用微服务的架构的设计,这点大家可以看看作者(kevin)的第四期开源说 ,其中对此有详细的讲解。
2.1.1 创建 greet 服务
$ mkdir go-zero-demo
$ cd go-zero-demo
$ go mod init go-zero-demo
$ goctl api new greet
$ go mod tidy
Done.
查看一下greet
服务的目录结构
$ tree greet
greet
├── etc
│ └── greet-api.yaml
├── greet.api
├── greet.go
└── internal├── config│ └── config.go├── handler│ ├── greethandler.go│ └── routes.go├── logic│ └── greetlogic.go├── svc│ └── servicecontext.go└── types└── types.go
由以上目录结构可以观察到,greet
服务虽小,但"五脏俱全"。接下来我们就可以在greetlogic.go
中编写业务代码了。
2.1.2 编写logic
# greet/internal/logic/greetlogic.go
func (l *GreetLogic) Greet(req *types.Request) (*types.Response, error) {return &types.Response{Message: "Hello go-zero",}, nil
}
2.1.3 启动并访问服务
启动服务
$ cd greet
$ go run greet.go -f etc/greet-api.yaml
输出如下,服务启动并侦听在8888端口:
Starting server at 0.0.0.0:8888...
访问服务
curl -i -X GET http://localhost:8888/from/you
返回如下:
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 07 Feb 2021 04:31:25 GMT
Content-Length: 27{"message":"Hello go-zero"}
2.2 微服务
现在我们来演示一下如何快速创建微服务, 在本小节中,api部分其实和单体服务的创建逻辑是一样的,只是在单体服务中没有服务间的通讯而已, 且微服务中api服务会多一些rpc调用的配置。
本小节将以一个订单服务
调用用户服务
来简单演示一下,演示代码仅传递思路,其中有些环节不会一一列举。
2.2.1 演示功能目标
假设我们在开发一个商城项目,而开发者小明负责用户模块(user)和订单模块(order)的开发,我们姑且将这两个模块拆分成两个微服务
- 订单服务(order)提供一个查询接口
- 用户服务(user)提供一个方法供订单服务获取用户信息
user rpc
order api
2.2.2 创建mall工程
$ mkdir mall
$ cd mall
$ go mod init mall
无 cd 改变目录, 所有操作均在 mall 目录执行
2.2.3 创建user rpc服务
- 创建user rpc服务
$ mkdir -p user/rpc
- 添加
user.proto
文件,增加getUser
方法
vim mall/user/rpc/user.proto
增加如下代码:
syntax = "proto3";package user;// protoc-gen-go 版本大于1.4.0, proto文件需要加上go_package,否则无法生成
option go_package = "./user";message IdRequest {string id = 1;
}message UserResponse {// 用户idstring id = 1;// 用户名称string name = 2;// 用户性别string gender = 3;
}service User {rpc getUser(IdRequest) returns(UserResponse);
}
注意: 1、每一个 *.proto文件只允许有一个service error: only one service expected
$ cd user/rpc
$ goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.
Done.
- 填充业务逻辑
// internal/logic/getuserlogic.gopackage logicimport ("context""go-zero-demo/mall/user/rpc/internal/svc""go-zero-demo/mall/user/rpc/types/user""github.com/zeromicro/go-zero/core/logx"
)type GetUserLogic struct {ctx context.ContextsvcCtx *svc.ServiceContextlogx.Logger
}func NewGetUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserLogic {return &GetUserLogic{ctx: ctx,svcCtx: svcCtx,Logger: logx.WithContext(ctx),}
}func (l *GetUserLogic) GetUser(in *user.IdRequest) (*user.UserResponse, error) {return &user.UserResponse{Id: "1",Name: "test",}, nil
}
2.2.4 创建order api服务
- 创建
order api
服务
# 回到 mall 目录
$ mkdir -p order/api && cd order/api
# mall/order/order.apitype(OrderReq {Id string `path:"id"`}OrderReply {Id string `json:"id"`Name string `json:"name"`}
)
service order {@handler getOrderget /api/order/get/:id (OrderReq) returns (OrderReply)
}
生成order服务
$ goctl api go -api order.api -dir .
添加user rpc配置
// internal/config/config.gopackage configimport ("github.com/zeromicro/go-zero/zrpc""github.com/zeromicro/go-zero/rest"
)type Config struct {rest.RestConfUserRpc zrpc.RpcClientConf
}
添加yaml配置
# etc/order.yaml Name: order
Host: 0.0.0.0
Port: 8888
UserRpc:Etcd:Hosts:- 127.0.0.1:2379Key: user.rpc
完善服务依赖
package svcimport ("go-zero-demo/mall/order/api/internal/config""go-zero-demo/mall/user/rpc/userclient""github.com/zeromicro/go-zero/zrpc"
)type ServiceContext struct {Config config.ConfigUserRpc userclient.User
}func NewServiceContext(c config.Config) *ServiceContext {return &ServiceContext{Config: c,UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),}
}
添加order演示逻辑
给 getorderlogic
添加业务逻辑
// internal/logic/getorderlogic.gopackage logicimport ("context""errors""go-zero-demo/mall/order/api/internal/svc""go-zero-demo/mall/order/api/internal/types""go-zero-demo/mall/user/rpc/types/user""github.com/zeromicro/go-zero/core/logx"
)type GetOrderLogic struct {logx.Loggerctx context.ContextsvcCtx *svc.ServiceContext
}func NewGetOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) GetOrderLogic {return GetOrderLogic{Logger: logx.WithContext(ctx),ctx: ctx,svcCtx: svcCtx,}
}func (l *GetOrderLogic) GetOrder(req *types.OrderReq) (*types.OrderReply, error) {user, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.IdRequest{Id: "1",})if err != nil {return nil, err}if user.Name != "test" {return nil, errors.New("用户不存在")}return &types.OrderReply{Id: req.Id,Name: "test order",}, nil
}
2.2.5 启动服务并验证
启动etcd
etcd
启动user rpc
# 在 mall/user/rpc 目录
$ go run user.go -f etc/user.yaml
Starting rpc server at 127.0.0.1:8080...
启动order api
# 在 mall/order/api 目录
$ go run order.go -f etc/order.yaml
Starting server at 0.0.0.0:8888...
访问order api
$ curl -i -X GET http://localhost:8888/api/order/get/1
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 07 Feb 2021 03:45:05 GMT
Content-Length: 30{"id":"1","name":"test order"}
3、组件剖析
go-zero 提供了一系列的组件,包括日志、高并发处理、消息队列等,本分组将为对组件进行详细剖析。
3.1 logx
3.1.1 logx 配置
type LogConf struct {ServiceName string `json:",optional"`Mode string `json:",default=console,options=[console,file,volume]"`Encoding string `json:",default=json,options=[json,plain]"`TimeFormat string `json:",optional"`Path string `json:",default=logs"`Level string `json:",default=info,options=[info,error,severe]"`Compress bool `json:",optional"`KeepDays int `json:",optional"`StackCooldownMillis int `json:",default=100"`
}
ServiceName
:设置服务名称,可选。在 volume
模式下,该名称用于生成日志文件。在 rest/zrpc
服务中,名称将被自动设置为 rest
或zrpc
的名称。
Mode
:输出日志的模式,默认是 console
console
模式将日志写到stdout/stderr
file
模式将日志写到 Path 指定目录的文件中volume
模式在 docker 中使用,将日志写入挂载的卷中
Encoding
: 指示如何对日志进行编码,默认是 json
json
模式以json
格式写日志plain
模式用纯文本写日志,并带有终端颜色显示
TimeFormat
:自定义时间格式,可选。默认是 2006-01-02T15:04:05.000Z07:00
Path
:设置日志路径,默认为 logs
Level
: 用于过滤日志的日志级别。默认为 info
info
,所有日志都被写入error
, info 的日志被丢弃severe
, info 和 error 日志被丢弃,只有 severe 日志被写入
Compress
: 是否压缩日志文件,只在 file
模式下工作
KeepDays
:日志文件被保留多少天,在给定的天数之后,过期的文件将被自动删除。对 console
模式没有影响
StackCooldownMillis
:多少毫秒后再次写入堆栈跟踪。用来避免堆栈跟踪日志过多
3.1.2 打印日志方法
type Logger interface {// Error logs a message at error level.Error(...interface{})// Errorf logs a message at error level.Errorf(string, ...interface{})// Errorv logs a message at error level.Errorv(interface{})// Errorw logs a message at error level.Errorw(string, ...LogField)// Info logs a message at info level.Info(...interface{})// Infof logs a message at info level.Infof(string, ...interface{})// Infov logs a message at info level.Infov(interface{})// Infow logs a message at info level.Infow(string, ...LogField)// Slow logs a message at slow level.Slow(...interface{})// Slowf logs a message at slow level.Slowf(string, ...interface{})// Slowv logs a message at slow level.Slowv(interface{})// Sloww logs a message at slow level.Sloww(string, ...LogField)// WithContext returns a new logger with the given context.WithContext(context.Context) Logger// WithDuration returns a new logger with the given duration.WithDuration(time.Duration) Logger
}
Error
, Info
, Slow
: 将任何类型的信息写进日志,使用 fmt.Sprint(...)
来转换为 string
Errorf
, Infof
, Slowf
: 将指定格式的信息写入日志
Errorv
, Infov
, Slowv
: 将任何类型的信息写入日志,用 json marshal
编码
Errorw
, Infow
, Sloww
: 写日志,并带上给定的 key:value
字段
WithContext
:将给定的 ctx 注入日志信息,例如用于记录 trace-id和span-id
WithDuration
: 将指定的时间写入日志信息中,字段名为 duration
3.1.3 与第三方日志库集成
- zap
实现: - logrus
实现
3.1.4 将日志写到指定的存储
logx
定义了两个接口,方便自定义 logx
,将日志写入任何存储。
logx.NewWriter(w io.Writer)
logx.SetWriter(write logx.Writer)
例如,如果我们想把日志写进kafka,而不是控制台或文件,我们可以像下面这样做。
type KafkaWriter struct {Pusher *kq.Pusher
}func NewKafkaWriter(pusher *kq.Pusher) *KafkaWriter {return &KafkaWriter{Pusher: pusher,}
}func (w *KafkaWriter) Write(p []byte) (n int, err error) {// writing log with newlines, trim them.if err := w.Pusher.Push(strings.TrimSpace(string(p))); err != nil {return 0, err}return len(p), nil
}func main() {pusher := kq.NewPusher([]string{"localhost:9092"}, "go-zero")defer pusher.Close()writer := logx.NewWriter(NewKafkaWriter(pusher))logx.SetWriter(writer)// more code
}
3.1.5 过滤敏感字段
go-zero 基础相关推荐
- java入门 慕路径,Java入门基础知识总结学习教程大全【必看经典】
类型的表达式,是循环条件,表达式3是党执行了一遍循环之后,修改控制循环的变量值. ??? for语句的执行过程是这样的:首先计算表达式1,完成必要的初始化工作:然后判断表达式2的值,如果表达式的值为t ...
- 提交表单自动刷新_Web自动化测试:元素的基础操作和浏览器基础操作
上一节,我们了解了如何定位元素,其实也有涉及对于元素的操作,这一节我们就详细的介绍一下对于元素的操作和对于浏览器的一些操作 一.对于元素的基础操作: clear():清除输入框内的文本 send_ke ...
- java mybatis基础
java mybatis基础 1.1 什么是mybatis? mybatis是一个优秀的持久层框架. 避免几乎所有的JDBC代码和手动设置参数以及获取结果集的过程. 可以使用简单的xml或者注解来配置 ...
- 【J2SE】学习基础
Java基础 语法基础 OO Exception Array 基础类 I/O Stream Collection/Generic Thread TCP/UDP GUI Meta Data Regula ...
- 【Linux系统】基础总结
我不太清楚运维部门具体是做什么的,就接触过一点点运维部门! 也就是是知道他们负责管理服务器,管理网络,管理项目部署 偶尔自己需要部署,不得不接触一些linux命令.简单总结一些基础 linux系统发展 ...
- 【Java 2 Platform Enterprise Edition】基础
问题1:为什么java是无关平台? 你之前用C或者C++写的源代码,编译好后,换一种操作系统,可能就执行不了了.因为新的操作系统不识别,你需要修改你的源码,并在新的操作系统上重新编译才能运行,比如Wi ...
- SpringCloud Alibaba微服务实战(一) - 基础环境搭建
说在前面 Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案.此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来 ...
- Redis概述和基础
Redis 1.NoSQL NoSQL = Not Only SQL(不仅仅是SQL) 泛指非关系型数据库的,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的 ...
- pass基础架构分析
pass基础架构分析 Relay 和 TVM IR,包含一系列优化passes,可提高模型的性能指标,如平均推理,内存占用,或特定设备的功耗.有一套标准优化,及特定机器学习的优化,包括常量折叠,死代码 ...
- LLVM编译器基础架构与DragonEgg示例
LLVM编译器基础架构与DragonEgg示例 LLVM 概述 LLVM 项目是模块化和可重用的编译器和工具链技术的集合.LLVM 与传统的虚拟机几乎没有关系."LLVM"这个名字 ...
最新文章
- python 可视化界面_工具推荐 | 3维数据可视化
- Swift 可选类型(补充)
- Matlab学习笔记——图形标注
- java 模拟ajax上传图片
- python语言的实验心得体会范文_实验报告个人心得体会范文
- 教你如何使用 OpenCV检测图像中的轮廓
- 一个关于sql server索引与填充因子的链接
- linux 邮件发送时间,Linux-No.04 Linux 设置定时任务发送邮件功能
- CSS3 pointer-events的应用
- 如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器
- 如何展开Linux Memory Management学习?
- 为什么 战舰stm32f103开发板32.768k晶振没有接电容
- 机器学习基础(五十四)—— 支持向量机(SVM)
- gaussian 和gaussview_谈谈Gaussian软件中的guess=mix
- 什么是前端开发?什么是后端开发?
- activemq在阿里云部署启动: java.net.UnknownHostException 异常处理
- 【蓝桥杯省赛】冲刺练习题【枚举】倒计时【12】天
- 配置sumlime html,Sublime Text 3使用SublimeLinter配置JS,CSS,HTML语法检查
- mysql gis polygon_把POLYGON转换到MULTIPOLYGON 中
- 中国总裁唐骏:说出微软的秘密