这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天,记录一下基于 kitex 和 hertz 的微服务 demo 搭建流程。
简介
上一篇主要讲了 nacos 作为注册中心的配置中心的接入方式,本文主要讲解 api 网关的搭建。
Api 网关
在第一篇文章中提到本来打算使用 nginx 来作为 api 网关的,但 nginx 无法与 nacos 很好的配合,主要存在以下两个问题:
- 服务注册到 nacos 之后,以及服务扩容或者缩容时,需要在 nginx 上手动添加服务的地址,过程较为繁琐。
- nginx 做负载均衡时无法实时监测节点故障。
鉴于以上两个问题,还是需要借助 nacos sdk 手动实现一个 api 网关(当然,可以在手动实现的网关外面再增加一层 nginx 网关)。幸运的是,hertz 有对应的组件库来支持基于 nacos 的服务发现功能以及反向代理功能,而且官方也提供了一个简易的 demo。下面就参考 demo 来构建一个简单的 api 网关。
引入对应的依赖。
go get github.com/hertz-contrib/registry/nacos
go get github.com/hertz-contrib/reverseproxy
创建 hertz 客户端,并给它配置 nacos 服务发现中间件。
// 创建hertz客户端
cli, err := client.NewClient()
if err != nil {
log.Panicf("hertz client init error: %v", err.Error())
}
// 创建resolver, 它需要的nacos client已经提前定义好了, 也可以使用NewDefaultNacosResolver方法使用默认的nacos client创建
resolver := nacos.NewNacosResolver(my_nacos.Client)
// 给hertz客户端配置nacos服务发现中间件
cli.Use(sd.Discovery(resolver))
创建反向代理,配置客户端和代理规则。客户端使用上一步创建好的 hertz 客户端,代理规则作为配置项写到了 nacos 中,目前只支持简单的前缀匹配。
// nacos中的配置: gateway.json
{
"mapping": [
{"prefix": "/user", "service": "user_service"},
{"prefix": "/media", "service": "media_service"}
]
}
// 代码中接收配置的struct
type Gateway struct {
Mapping []struct {
Prefix string `json:"prefix"`
Service string `json:"service"`
} `json:"mapping"`
}
// 创建代理
proxy := &reverseproxy.ReverseProxy{}
// 配置客户端
proxy.SetClient(cli)
// 配置规则
proxy.SetDirector(func(req *protocol.Request) {
serviceName := "error"
// 路由前缀匹配
for _, m := range my_config.C.Mapping {
if strings.HasPrefix(string(req.URI().Path()), m.Prefix) {
serviceName = m.Service
break
}
}
// 此处有坑, serviceName中不能包含大写字母, 原因是字节的网络库会把url的host变成小写
uri := string(reverseproxy.JoinURLPath(req, "http://"+serviceName))
log.Slog.Infof("request: %v", uri)
req.SetRequestURI(uri)
req.Header.SetHostBytes([]byte(serviceName))
// 开启服务发现
req.Options().Apply([]config.RequestOption{config.WithSD(true)})
})
创建 hertz 服务端,配置代理并启动。
// 创建hertz服务端
h := server.Default()
// 代理所有请求
h.Any("/*path", proxy.ServeHTTP)
// 启动
h.Spin()
小结
到此为止,微服务的基础架构已初具雏形。当然,在大型系统中,流控、链路追踪等服务治理工作也是非常重要的,在此就不再做过多的介绍了。