基于kitex和hertz的微服务demo搭建(下)| 青训营笔记

490 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天,记录一下基于 kitex 和 hertz 的微服务 demo 搭建流程。

简介

上一篇主要讲了 nacos 作为注册中心的配置中心的接入方式,本文主要讲解 api 网关的搭建。

Api 网关

第一篇文章中提到本来打算使用 nginx 来作为 api 网关的,但 nginx 无法与 nacos 很好的配合,主要存在以下两个问题:

  1. 服务注册到 nacos 之后,以及服务扩容或者缩容时,需要在 nginx 上手动添加服务的地址,过程较为繁琐。
  2. 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()
小结

到此为止,微服务的基础架构已初具雏形。当然,在大型系统中,流控、链路追踪等服务治理工作也是非常重要的,在此就不再做过多的介绍了。