开坑第一问
微服务HTTP框架?What?
老友们想了解到微服务HTTP框架,我们可以先解决一下什么是HTTP框架。
顾名思义HTTP框架是基于HTTP协议能够提供web服务的一种框架。具体实现的就是它提供了路由、中间件、请求处理等功能。谈及此处,是不是有些熟悉了,怎么这么像Gin。没错,这它喵的Gin就是啊!我Gin都快学完了,你给我又整这么个东西,玩捏。
其实不然,我们要了解的微服务HTTP框架——Hertz在设计之初参考了其他开源框架 fasthttp、gin、echo 的优势,具有使其具有高易用性、高性能、高扩展性等特点。
此处再跟大家浅谈一下微服务,只个人见解。微服务是一种架构风格,它将应用程序拆分成一组小型、自治的服务,每个服务专注于完成特定的业务功能。也是近几年很火热的概念。如同我们之前一般都是使用后端大端接口提供服务,如今微服务好像是解体了的后端,但各自的分工更加明确且精细。微服务实现了一种1+1>2的一种效果。是不是有些手痒想去学。
讲了这么多,开始咱们的正题。
Hello World
Hertz需要的Go版本至少为1.15,如果低于1.15的请更新Go版本
安装
go install github.com/cloudwego/hertz/cmd/hz@latest
可使用 hz -v 查看是否安装完成
hz -v
hz默认是在GOPATH/src路径下创建目录结构的,可以使用-mod指定在当前目录下创建目录结构通过,通过指定module形式创建注意应启用GOMODULE
hz new -mod MODULENAME
另如果当前路径下有go.mod文件,可直接在当前目录下使用
hz new
项目初始化后,hertz会自动创建对应项目文件,文件结构如下
├── biz
│ ├── handler
│ │ └── ping.go
│ └── router
│ └── register.go
├── go.mod
├── main.go
├── router.go
└── router_gen.go
运行
hertz默认的监听端口为8888,可以通过 server.WithHostPorts() 来指定运行端口
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:9090"))
register(h)
h.Spin()
}
运行结果为:
访问
localhost:9090/ping 浏览器的响应
{"message":"pong"}
代码生成工具
hz 是 Hertz 框架提供的一个用于生成代码的命令行工具。目前,hz 可以基于 thrift 和 protobuf 的 IDL 生成 Hertz 项目的脚手架。
要使用 thrift 或 protobuf 的 IDL 生成代码,需要安装相应的编译器:thriftgo 或 protoc 。 hz 生成的代码里,一部分是底层的编译器生成的(通常是关于 IDL 里定义的结构体),另一部分是 IDL 中用户定义的路由、method 等信息。用户可直接运行该代码。
从执行流上来说,当 hz 使用 thrift IDL 生成代码时,hz 会调用 thriftgo 来生成 go 结构体代码,并将自身作为 thriftgo 的一个插件(名为 thrift-gen-hertz)来执行来生成其他代码。当用于 protobuf IDL 时亦是如此。
安装thriftgo:
go install github.com/cloudwego/thriftgo@latest
安装proto请使用Github自行下载protoc
IDL
这里我又想发言了,这个东西是我最新体验的,学起来也不是很难。IDL(inteface description language),接口描述语言。还是不理解?那我接下来说他可以让你的后端接口按照你的想法一键生成,是不是有点夸张。
写过后端接口可能知道,接口暴露在外面,接收外界参数,处理结果,返回数据(主Json)。细心同学会发现,其中有很多的必经之路。这可能就是大佬们提到过的二八定律,20%的代码重复使用完成80%的功能。
IDL将接口里的必经之路抽象出来,可以更加方便的实现接口。让开发人员投入更多的精力完成业务。它是我继Markdown之后,再次感慨优美的语言。
感兴趣的友友们,我这有传送门。
使用IDL创建项目
thrift IDL
创建一个hello.thrift 文件
// idl/hello.thrift
namespace go hello.example
struct HelloReq {
1: string Name (api.query="name"); // 添加 api 注解为方便进行参数绑定
}
struct HelloResp {
1: string RespBody;
}
service HelloService {
HelloResp HelloMethod(1: HelloReq request) (api.get="/hello");
}
注意一下基于go module依赖管理
# 不在`$GOPATH`下的项目通过工具提供的`-module`命令指定一个自定义 module 名称即可:
hz new -module example.com/m -idl idl/hello.thrift
# 整理 & 拉取依赖
go mod tidy
# 查看 go.mod 中 github.com/apache/thrift 版本是否为 v0.13.0,如果不是则继续执行剩余代码
go mod edit -replace github.com/apache/thrift=github.com/apache/thrift@v0.13.0
# 整理 & 拉取依赖
go mod tidy
注:解释第三行代码,thrift其他版本较v0.13.0方法更改较多,生成的代码会出现兼容的问题。
update: 更新一个已有的项目
// idl/hello.thrift
namespace go hello.example
struct HelloReq {
1: string Name (api.query="name");
}
struct HelloResp {
1: string RespBody;
}
struct OtherReq {
1: string Other (api.body="other");
}
struct OtherResp {
1: string Resp;
}
service HelloService {
HelloResp HelloMethod(1: HelloReq request) (api.get="/hello");
OtherResp OtherMethod(1: OtherReq request) (api.post="/other");
}
service NewService {
HelloResp NewMethod(1: HelloReq request) (api.get="/new");
}
执行一下命令
hz update -idl idl/hello.thrift
protobuf IDL
这里不打算过多介绍,详细可以前往hz 使用 (protobuf)
// idl/hello/hello.proto
syntax = "proto3";
package hello;
option go_package = "hertz/hello";
message HelloReq {
string Name = 1;
}
message HelloResp {
string RespBody = 1;
}
service HelloService {
rpc Method1(HelloReq) returns(HelloResp);
}
使用 hz 创建项目目录
hz new -I idl -idl idl/hello/hello.proto -mod helloIdlProto
hz update -I idl -idl idl/hello/hello.proto -mod helloIdlProto
如果主IDL的依赖和主IDL不在同一路径下,需要加入 -I 选项,其含义为IDL搜索路径,等同于 protoc 的 -I 命令
结语
铁子们,感觉写的差没必要划走,点点举报也行啊,有赞最好。不要让白嫖成为程序员前进的最大阻力。