Easy Note——快速入门 CloudWeGo 生态

原创
2023/04/03 13:58
阅读数 321

CloudWeGo Study Group 是由 CloudWeGo 社区发起的学习小组,开展以 30 天为一期的源码解读和学习活动,帮助新成员融入社区圈子,和社区 Committer 互动交流,并学习上手 CloudWeGo 几大框架项目。目前 CSG 第四期—— CloudWeGo 业务实践案例解读已经圆满结束!

本期活动期间安排了 4 期直播分享,主题分别为:

  • Bookinfo——基于 CloudWeGo 重写 Istio 经典 demo
  • Open Payment Platform——基于 CloudWeGo 实现 API Gateway
  • EasyNote——CloudWeGo 生态入门
  • BookShop——从上手电商到上手CloudWeGo

本文为 CSG 第四期第二场直播中CloudWeGo Reviewer 李宜茗分享内容。

回放链接:https://meetings.feishu.cn/s/1iraydxgioe81?src_type=2

一、嘉宾介绍

如何快速入门 CloudWeGo 生态,biz-demo Easy Note 解读

本期分享的内容主要分为以下三个部分:

  1. 如何入门 CloudWeGo 生态
  2. Hertz,Kitex,GORM 介绍
  3. Easy Note 解读

二、如何入门 CloudWeGo 生态

Tip 01: 官方文档

“遇事不决先查文档”,获取信息最直接的方式就是查询官方文档。CloudWeGo 具有非常完善的中文文档以及英文文档,并且文档的更新和维护都非常及时。并且文档在 GitHub 上也有对应的仓库,你如果发现了哪里有问题或者语法错误,都可以随时提交 GitHub issue 或者 PR 来帮助进行修正。 在CloudWeGo 的官网,可以通过文档目录查看 CloudWeGo 目前开源的所有产品。以 Hertz 举例,“概览” 板块帮助我们快速了解 Hertz 是什么,同时 “快速开始” 板块能够让你快速入门 Hertz ,它会帮助你以最快速、简单的方式去搭建一个简易的 HTTP 服务。

Tip 02: Examples

如果官方文档还没有解决你的疑问,可以去查看对应的示例仓库。例如 Hertz 和 Kitex,都有对应的示例仓库 hertz-examples 和 kitex-examples。Examples 仓库一般会包含产品各个主要特性的更加细致的使用方法,为你提供一些更加详细的使用示例参考。

比如,通过查看 Hertz-examples 的 readme,可以看到对于 Hertz 常见的一些中间件,包括官网上列出的主要特性,都有对应的示例。假如你在查看一个特性的官方文档后仍觉得比较抽象,你就可以去 Examples 里面查看特性对应的示例,里面会提供更加详细的使用的示例来帮助你快速进行入门。Hertz-examples 也包含了一些常用框架组件和 Hertz 一起使用的 biz-demo,比如 hertz_jwt 是使用 Hertz 和 JWT 中间件的 demo,hertz_session 是使用 Hertz 和 Session,CSRF 中间件的 demo,这些 biz-demo 可以帮助你快速上手 Hertz 和其他组件搭配使用的方法。 包括如果你觉得这些 biz-demo 还不够完善,有一些自己想添加的组件,你可以在 Hertz issues/486 下面评论,就可以去为 hertz-examples 提供一些你自己的一些组件和 Hertz 结合的示例 demo。

Tip 03: 扩展仓库

像 Hertz 和 Kitex ,都有分出一个专门的扩展仓库去维护各自的组件。比如, Hertz 和 Kitex 都对常见的服务发现与注册中心进行了支持,包括 nacos,etcd,consul 等等。同时, Hertz 也对常用的 Web 中间件进行了支持,像 JWT,gzip,sessions 这些。并且大多数的扩展仓库都会有附带使用示例,方便用户进行上手。所以如果你想要去使用一些常用的功能扩展,不妨先看看这些扩展仓库,不需要你自己去进行开发了。 并且,大多数的扩展仓库作者在写这些仓库时候,都会单独分出一个叫 example 的文件夹,你可以去查看这些仓库的 example 文件夹,去获得更加细致的使用方法。比如 Hertz session 中间件,它的 example 文件夹下就包含了它如何和 cookie 结合,以及和 redis 结合的简单示例,这也是一个比较高效获取信息的渠道。

Tip 04: 关于提问

最后一个小 tips 是有关提问,比如平时我们遇到一些技术问题,通常可以通过查询引擎,各大技术社区,比如掘金,或一些产品的官网,GitHub 的历史 issue,包括现在非常火的 ChatGPT,这些都可以为我们提供很多解决方案,并且我们大多数常见问题都可以通过以上方式查询到解决方案。如果这些都解决不了,那么欢迎提 issue,这样一方面可以对问题进行记录,同时也能方便之后遇到相同问题的同学,最后也可以帮助产品本身进一步地完善成长。提 issue 也是我非常推荐的一种解决问题的方式。

三、Hertz,Kitex,GORM 介绍

框架概述

  • Hertz 和 Kitex 都是由字节跳动开源的一款 HTTP 框架,它参考了其他开源框架,像Gim、 Echo 的一些优势,并且结合了字节跳动内部的一些需求,具有高应用、高性能以及高拓展性的特点。
  • Kitex 是字节开源的 Golang 微服务 RPC 框架,具有高性能,强可扩展的主要特点,支持多协议并且拥有丰富的开源扩展。
  • GORM 则是一个迭代 10 多年的非常非常强大的 RM 框架,在字节内部已经进行了广泛使用,同时也是一种非常丰富的开源拓展。

Hertz - 架构设计

https://www.cloudwego.io/zh/docs/hertz/overview/

可以看到这里是 Hertz 简单的架构设计图。

Hertz 自带的 hz 的代码生成工具,可以帮助我们快速地生成脚手架代码,简化开发流程。包括 Hertz 也具有丰富的协议支持,比如 HTTP 1.1,HTTP 2 和 HTTP 3,其中 2 和 3 以扩展的方式存放于 hertz-contrib 仓库下。包括 Hertz 也支持切换底层的网络库,可以使用 CloudWeGo 开源的 netpoll 代替和 go 原生的网络库。你也可以去自己进行扩展,Hertz 提供了丰富的扩展接口,方便你去完成自己的一些实现。

Kitex

https://www.cloudwego.io/zh/docs/kitex/overview/

Kitex 也是自带代码生成工具的 kitex。它可以帮我们非常方便地生成一些脚手架代码,包括也支持一些插件扩展,帮助我们简化开发流程,同时也支持了非常多的消息协议以及传输类型,以及各种消息方式。它也可以使用 netpoll 以及 go 原生库去进行切换。

GORM

  • 全功能 ORM
  • 关联 (has one,has many,belongs to,many to many,多态,单表继承)
  • Create,Save,Update,Delete,Find 中钩子方法
  • 支持 Preload、Joins 的预加载
  • 事务,嵌套事务,Save Point,Rollback To to Saved Point
  • Context、预编译模式、DryRun 模式
  • 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
  • SQL 构建器,Upsert,锁,Optimizer/Index/Comment Hint,命名参数,子查询
  • 复合主键,索引,约束
  • Auto Migration
  • 自定义 Logger
  • 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
  • 每个特性都经过了测试的重重考验
  • 开发者友好

四、Easy Note 解读

技术架构

下图是Easy Note 技术栈,主要分为三层,分别使用 Hertz, Kitex 和 GORM 去编写。

  1. Hertz 负责处理用户请求,处理负责客用户直接访问的 HTTP 请求,包括这里也使用了 Hertz 的 4 个中间件 ,requestid 中间件、jwt 中间件、 pproof 以及 gzip 中间件。
  2. Kitex 主要使用了它的 etcd 的扩展作为服务注册与发现中心,并且也使用了一个 Kitex 的代码生成扩展,thrift-gen-validator 去对 RPC 请求做校验。最后对数据库操作,使用了 GORM 框架,同时使用 MySQL 数据库作 RDBMS。同时也集成了 OpenTelemetry 以及 Jaeger 对链路进行追踪。
  3. 最后,用 Logrus 日志对 Hertz, Kitex 与 GORM 默认的日志进行替换,达成统一。

调用关系

下图则是 Easy Note 这个biz - demo 的服务调用关系图。 Easy Note 是一个微服务项目,主要分为三个微服务:demoapi、 demonote 以及 demouser。

其中 demoapi 是一个 HTTP 服务, demonote 和 demouser 是一个 RPC 服务,用户通过访问通过 HTTP 访问 demoapi 服务, demoapi 服务会通过 RPC 访问 demouser 服务以及 demonote 服务。同时我们 demonote 服务也会通过 RPC 请求 demouser 服务,完成我们的逻辑。

目录介绍

刚刚提到,Easy Note 是一个微服务项目,分为三个微服务。其中在 CMD 环节下就包含了三个微服务的主要代码。 API 就是我们使用各自搭建的 HTTP 服务,它为用户直接提供服务。

user 就是我们刚才提及到的 demouser 服务,它是使用 Kitex 和 GORM 去搭建的一个 RPC 服务,还负责用户的创建、查询以及校验等功能。最后是 demonote 服务,它是我们用 Kitex 和 GORM 搭建的 RPC 服务,主要是负责笔记的增删改查功能。 dal 是数据库操作目录,里面包含了使用 GORM 去编写代码,对数据库表进行资源改查操作。 pack 则是我们的数据包装文件夹,它会包装 RPC 响应,这样的一些 RPC 响应方便统一服务之间的交流。 pkg 文件夹下, mw 目录则是我们为 Kitex 定义的一些 RPC 中间件,包括 client 侧中间件,server 侧中间件以及 common 中间件。而 consts 类目录是包含了整个项目全局定义的常量。 errno 则是自定义的错误码,对整个错误的处理进行规范。 configs 是 SQL 脚本以及 OpenTelementry 的 Tracing 的配置。

开发流程

  1. 定义 IDL

首先第一步,需要去定义服务的IDL。通过 thrift IDL 去定义这些服务的接口。比如我们这里可以用 API 注解去使用 Hertz 参数绑定与验证的功能,方便 Hertz 生成代码。同时,也可以去通过 API 注解, api.post、 api.get 一些注解去定义 HTTP 请求方式与路由。这样 Hertz 会根据一些路由为我们生成对应的脚手架代码。同时 Hertz 也会对一些路由进行分组,方便后面我们对各个不同路由集成各自不同的中间件。

包括前面提到,我们使用了 thrift-gen-validator 插件,让 Kitex 帮助生成对应的代码以及 thrift-gen-validator。它可以帮助对 RPC 请求的结构体进行简单的校验。

  1. 建立数据库表

第二步,我们需要去建立一个数据库表,可以通过 gorm.Model,快速地去设计数据库表的结构。包括使用 gorm.Model 以后, GORM 也会支像软删除这样的一些功能,非常方便。

同时,也可以使用在 docker-compose.yaml 中配置 volumes 属性将 SQL 脚本挂载到 MySQL 容器中,这样 MySQL 的官方镜像会在容器启动时候自动执行 /docker-entrypoint-initdb.d 这个文件夹下的 SQL 脚本,从而去完成数据库的初始化。在 pkg/config/sql 目录中,init.sql 包含了对数据库表的初始化代码。创建了 user 表和 note 表来存储用户信息以及笔记的信息。这样我们在创建 MySQL 容器的时候,init.sql 就会自动执行,从而完成数据库表的初始化。

  1. 代码生成

第三步就是代码生成,我们刚刚提到 Hertz 有 hz 工具, Kitex 有它的 kitex 工具,可以非常方便地帮我们生成很多脚手架代码,从而简化开发流程。同时 CloudWeGo 最近也开源了一款新的产品 cwgo,它集成了 Hertz , Kitex 以及 gorm-gen 这些代码生成工具,并且它提供了更加丰富的模板以及代码生成功能。

cwgo 项目链接:https://github.com/cloudwego/cwgo

可以访问上方链接,去 GitHub 上看这个项目,这是一个 all-in-one 工具,结合了各个组件优势,非常的方便。并且它也支持动态命令,简化用户的使用难度。

  1. demouser,demonote

接下来是 demouser 服务和 demonote 服务的开发流程,它们的开发流程非常的相似。

  • demouser

    • 利用 GORM 完成对用户的创建与查询
    • 完成用户创建,检查,查询的具体业务逻辑
    • 将服务注册进 etcd 以供其他服务调用
  • demonote

    • 利用 GORM 完成对笔记的增删改查
    • 通过 RPC 调用 demouser 服务获取用户信息
    • 完成笔记增删改查具体的业务逻辑
    • 将服务注册进 etcd 以供其他服务调用
  1. demoapi

最后,是demoapi服务的开发。

  • 使用 jwt,requestid,gzip,pprof 中间件
  • 完成用户注册登录功能
  • 通过 jwt 认证授权后的用户才能对笔记进行一系列操作
  • 通过 RPC 调用 demouser 和 demonote 服务完成业务逻辑
  • 返回响应数据给前端。

代码细节

  1. 链路追踪

Hertz、 Kitex 与 GORM 都对 OpenTelemetry 扩展提供了支持,提供 tracing 、metrics 以及 logging 的支持。

Easy Note 项目中只使用了一个 Jaeger 进行业务上的链路追踪。同时我们还可以通过 Gafana 面板进行观测。

在 Request ID 中间件里,我们通过 trace ID 去替换掉默认的 Request ID,这样我们就可以直接可以通过 HTTP 响应头中的 X-Request-ID,获取到 trace ID。在 Jaeger 面板中可以对链路的信息进行查询。

  1. Kitex 中间件

前面提到,我们定义了一个 server 端, client 端,以及 comment 中间件,并且它会以选项的模式去嵌入我们的 Kitex。这里我们定义的中间件可以对 RPC 的调用信息以及其他的信息进行详细的输出。

  1. 错误码封装

我们对错误码也进行了封装,可以预先在 thrift IDL 中定义错误码,这样 Kitex 会生成对应的代码,再去直接去使用就可以了。我们可以去制定一些错误类型与函数,可以去对于业务的异常进行转换,从而让错误处理一致化。

总结回顾

以上就是 Easy Note 的简单分享。

第一部分我们从 CloudWeGo 生态入门开始,谈到如何去查看文档,以及 CloudWeGo 的一些扩展,最后我们了解了一些如何提问的 Tips。

第二部分去对 Hertz,Kitex 以及 GORM 这三个框架进简单的介绍。

最后我们对 Easy Note 的架构、代码生成以及开发流程,从代码细节方面进行的解读,希望可以帮助到大家对 Easy Note 以及 CloudWeGo 生态有一个更深的了解。

同时也非常欢迎大家为 Hertz,Kitex 以及 GORM 进行贡献代码,三者都是非常优秀的开源项目。


项目地址

活动链接:https://github.com/cloudwego/community/issues/58

图片

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部