Go语言微服务框架 - 6.用Google风格的API接口打通MySQL操作

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 随着RPC与MySQL的打通,整个框架已经开始打通了数据的出入口。接下来,我们就尝试着实现通过RPC请求操作MySQL数据库,打通整个链路,真正地让这个平台实现可用。

随着RPC与MySQL的打通,整个框架已经开始打通了数据的出入口。

接下来,我们就尝试着实现通过RPC请求操作MySQL数据库,打通整个链路,真正地让这个平台实现可用。

v0.5.0:用Google风格的API接口打通MySQL操作

项目链接 https://github.com/Junedayday/micro_web_service/tree/v0.5.0

目标

从API出发,实现一个数据库表的增删改查。

关键技术点

  1. Google风格的API定义
  2. model与dao的定义
  3. service层的实现

注意,最近buf工具进行了一次不兼容的升级,从v1beta升级到了v1,可通过如下链接下载 https://github.com/bufbuild/buf/releases

目录构造

--- micro_web_service            项目目录
    |-- gen                            从idl文件夹中生成的文件,不可手动修改
       |-- idl                             对应idl文件夹
          |-- demo                             对应idl/demo服务
             |-- demo.pb.go                        demo.proto的基础结构
             |-- demo.pb.gw.go                     demo.proto的HTTP接口,对应gRPC-Gateway
             |-- demo_grpc.pb.go                   demo.proto的gRPC接口代码
            |-- order                            新增:对应idl/order服务
             |-- order.pb.go                       新增:order.proto的基础结构
             |-- order.pb.gw.go                    新增:order.proto的HTTP接口,对应gRPC-Gateway
             |-- order_grpc.pb.go                  新增:order.proto的gRPC接口代码
    |-- idl                            原始的idl定义
       |-- demo                            业务package定义
          |-- demo.proto                       protobuffer的原始定义
       |-- order                           新增:业务order定义
          |-- order.proto                      新增:protobuffer的原始定义
    |-- internal                       项目的内部代码,不对外暴露
       |-- config                          配置相关的文件夹
          |-- viper.go                         viper的相关加载逻辑
       |-- dao                             Data Access Object层
          |-- order.go                         更新:Order对象,订单表,实现model层的OrderRepository
          |-- order_test.go                    Order的单元测试
       |-- model                           新增:model层,定义对象的接口方法
          |-- order.go                         新增:OrderRepository接口,具体实现在dao层
       |-- mysql                           MySQL连接
          |-- init.go                          初始化连接到MySQL的工作
       |-- server                          服务器的实现
          |-- demo.go                          server中对demo这个服务的接口实现
          |-- server.go                        server的定义,须实现对应服务的方法
       |-- service                         新增:service层,作为领域实现的核心部分
          |-- order.go                         新增:Order相关的服务,目前仅简单的CRUD
     |-- zlog                            封装日志的文件夹
        |-- zap.go                           zap封装的代码实现
    |-- buf.gen.yaml                   更新:buf生成代码的定义,从v1beta升到v1
    |-- buf.yaml                       更新:buf工具安装所需的工具,从v1beta升到v1
    |-- gen.sh                         buf生成的shell脚本
    |-- go.mod                         Go Module文件
    |-- main.go                        项目启动的main函数

1.Google风格的API定义

由于整体的定义比较多,这里就以

message CreateOrderRequest {
  Order order = 1;
}

message UpdateOrderRequest {
  Order order = 1;
  google.protobuf.FieldMask update_mask = 2;
}

message GetOrderRequest {
  string name = 1;
}

// Order服务
service OrderService {
  rpc ListOrders(ListOrdersRequest) returns (ListOrdersResponse) {
    option (google.api.http) = {
      get: "/v1/orders"
    };
  }

  // 这里body中的order表示HTTP的body里的数据填充到CreateOrderRequest结构中的order对象
  rpc CreateOrder(CreateOrderRequest) returns (Order) {
    option (google.api.http) = {
      post: "/v1/orders"
      body: "order"
    };
  }

  rpc UpdateOrder(UpdateOrderRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      patch: "/v1/orders"
      body: "*"
    };
  }

  // 这里{name=*}表示这个字段填充到GetOrderRequest里的name字段
  rpc GetOrder(GetOrderRequest) returns (Order) {
    option (google.api.http) = {
      get: "/v1/orders/{name=*}"
    };
  }

  rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/books"
    };
  }
}

这里,我们重点关注以下几个方法:

  1. List - 查询列表,对应HTTP的GET方法
  2. Get - 查询单个对象,对应HTTP的GET方法
  3. Create - 创建对象,对应HTTP的POST方法
  4. Update - 更新对象,对应HTTP的PATCH方法
  5. Delete - 删除对象,对应HTTP的DELETE方法(本次暂未实现,后续添加软删除时加上)

关于Google定义的标准方法细节,可以参考Google Cloud API链接,了解对资源、字段等命名的逻辑。

而对于gRPC-Gateway中对于proto3的语法,可以参考gRPC-Gateway链接

以上两块内容比较多,建议边实践边学习,不要一开始就钻细节。

2.model与dao的定义

为了将模型的定义与数据库的实现分离,我将两者进行了拆分,分别放置在model与dao目录下,定位的简单介绍如下:

  • model,数据模型的定义,更关注对业务层的数据格式统一,底层可以对应各种存储形式,如mysql、redis
  • dao,真实数据存储的操作,也就是model层的实现,目前实现了一种mysql的操作

Model层

重点是统一的数据结构定义Order,以及关键接口OrderRepository的定义。

// Order针对的是 orders 表中的一行数据
// 在这里定义,是为了分离Model与Dao
type Order struct {
   
    Id    int64
    Name  string
    Price float32
}

// OrderFields 作为一个 数据库Order对象+fields字段的组合
// fields用来指定Order中的哪些字段生效
type OrderFields struct {
   
    Order  *Order
    Fields []string
}

type OrderRepository interface {
   
    AddOrder(order *Order) (err error)
    QueryOrders(pageNumber, pageSize int, condition *OrderFields) (orders []Order, err error)
    UpdateOrder(updated, condition *OrderFields) (err error)
}

Dao层

Dao层代码基本与之前一致,重点关注结构体OrderRepo,它是Model层OrderRepository的一种MySQL实现。

type OrderRepo struct {
   
    db *gorm.DB
}

// 将gorm.DB作为一个参数,在初始化时赋值:方便测试时,放一个mock的db
func NewOrderRepo(db *gorm.DB) *OrderRepo {
   
    return &OrderRepo{
   db: db}
}

3.service层的实现

service是核心业务实现,但目前的示例代码比较简单,基本就是透传CRUD。

// 定义Service的实现,注意orderRepo的定义是model层的interface
type OrderService struct {
   
    orderRepo model.OrderRepository
}

// 创建对象,注意orderRepo的实现为dao层代码
func NewOrderService() *OrderService {
   
    return &OrderService{
   
        orderRepo: dao.NewOrderRepo(mysql.GormDB),
    }
}

// 以List为例,透传查询
func (orderSvc *OrderService) List(ctx context.Context, pageNumber, pageSize int, condition *model.OrderFields) ([]model.Order, error) {
   
    orders, err := orderSvc.orderRepo.QueryOrders(pageNumber, pageSize, condition)
    if err != nil {
   
        return nil, errors.Wrapf(err, "OrderService List pageNumber %d pageSize %d", pageNumber, pageSize)
    }
    return orders, nil
}

4.模拟HTTP接口访问

本服务支持gRPC和HTTP访问,但由于gRPC不方便用工具模拟,我们这里就以HTTP对本服务进行访问

// List
curl --request GET 'http://127.0.0.1:8081/v1/orders'

// Create
curl --request POST 'http://127.0.0.1:8081/v1/orders' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "order1",
    "price": 100.3
}'

// Update 这里 order 表示数据,update_mask表示更新的字段是price
curl --request PATCH 'http://127.0.0.1:8081/v1/orders' \
--header 'Content-Type: application/json' \
--data-raw '{
    "order": {
        "id": "1",
        "name": "order1",
        "price": 110.9
    },
    "update_mask": "price"
}'

// Get 查询name=order1的对象
curl --request GET 'http://127.0.0.1:8081/v1/orders/order1'

关于Google风格的API总结

Google风格的API和目前的主流RESTful标准的API有很多相似点、也存在一定的区别。

我们没有必要去抠API风格的细节实现、一定要与Google风格完全一致。API接口是一个通用协议,不同团队有自己的理解,就像RESTful标准的细节实现都有差异。

作为对外协议,最重要的是可读性,每个人都可以根据实际项目情况,对接口风格做一些适配性调整。这里介绍Google风格,主要是为了扩展大家的视野、拥有更多的技术实现方式。

总结

通过这个版本,我们打通了API接口到MySQL数据库操作的全流程,是对整个框架的一次初步整合。接下来,我们会对这一流程进行精雕细琢,使其更具通用性和易用性。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
JavaScript Java Go
探索Go语言在微服务架构中的优势
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出。本文将深入探讨Go语言在构建微服务时的性能优势,包括其在内存管理、网络编程、并发模型以及工具链支持方面的特点。通过对比其他流行语言,我们将揭示Go语言如何成为微服务架构中的一股清流。
128 53
|
1月前
|
API
用 Koa 框架实现一个简单的 RESTful API
用 Koa 框架实现一个简单的 RESTful API
|
21天前
|
开发框架 Go 计算机视觉
纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C++ 库,如 OpenCV 或 dlib,但通过 cgo 调用 C 程序会引入巨大的延迟,并在性能方面产生显著的权衡。此外,在许多情况下,在各种平台上安装 OpenCV 是很麻烦的。使用纯Go开发的插件不仅在开发时方便,在项目部署和项目维护也能省很多时间精力。
|
1月前
|
Go API 数据库
Go 语言中常用的 ORM 框架,如 GORM、XORM 和 BeeORM,分析了它们的特点、优势及不足,并从功能特性、性能表现、易用性和社区活跃度等方面进行了比较,旨在帮助开发者根据项目需求选择合适的 ORM 框架。
本文介绍了 Go 语言中常用的 ORM 框架,如 GORM、XORM 和 BeeORM,分析了它们的特点、优势及不足,并从功能特性、性能表现、易用性和社区活跃度等方面进行了比较,旨在帮助开发者根据项目需求选择合适的 ORM 框架。
82 4
|
1月前
|
缓存 API 数据库
Python哪个框架合适开发速卖通商品详情api?
在跨境电商平台速卖通的商品详情数据获取与整合中,Python 语言及其多种框架(如 Flask、Django、Tornado 和 FastAPI)提供了高效解决方案。Flask 简洁灵活,适合快速开发;Django 功能全面,适用于大型项目;Tornado 性能卓越,擅长处理高并发;FastAPI 结合类型提示和异步编程,开发体验优秀。选择合适的框架需综合考虑项目规模、性能要求和团队技术栈。
26 2
|
1月前
|
中间件 Go API
Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架
本文概述了Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架。
73 1
|
1月前
|
JSON JavaScript 中间件
Koa框架下的RESTful API设计与实现
在现代 Web 开发中,构建高效、可维护的 API 是至关重要的。Koa 是一个流行的 Node.js Web 应用框架,它具有简洁、灵活和强大的特性,非常适合用于设计和实现 RESTful API。
|
1月前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
1月前
|
开发框架 Java 关系型数据库
Java哪个框架适合开发API接口?
在快速发展的软件开发领域,API接口连接了不同的系统和服务。Java作为成熟的编程语言,其生态系统中出现了许多API开发框架。Magic-API因其独特优势和强大功能,成为Java开发者优选的API开发框架。本文将从核心优势、实际应用价值及未来展望等方面,深入探讨Magic-API为何值得选择。
44 2
|
1月前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。