🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
前两篇文章分别介绍了本系列文章的背景以及根据业务职能对商城系统做了服务的拆分,其中每个服务又可分为如下三类:
- api服务 - BFF层,对外提供HTTP接口
- rpc服务 - 内部依赖的微服务,实现单一的业务功能
- rmq服务 - 负责流式任务的处理,如消费kafka等等
- admin服务 - 对内部管理后台提供HTTP接口,通常数据操作权限比较高
如果没看过前两篇文章可通过如下传送门查看
前两篇文章比较偏理论,以至于文章发出去后有些同学觉得写得比较水,非常理解大家迫切想要写代码的心情,我也进行了深刻的反思哈哈哈。所以从本篇开始就要进入万众期待的代码环节了。但是,所谓磨刀不误砍柴工,在真正的生产开发过程中,我们一般都会花大量的时间在需求的理解和协议的设计上,如果需求理解的不透彻或者协议设计的不合理就会大大增加我们项目返工的可能,甚至还没上线就得重构。所以前期多投入一些时间也完全是值得的。当我们把需求理解透彻,项目结构和协议定义清晰后,其实写代码就是顺水推舟的事情,速度那是大大滴快。闲言少叙,我们开始今天的内容。
API定义
可能大家在工作中都遇到过这样的场景,就是代码更新了但是文档没有更新,从而产生一些问题导致一些扯皮事情的发生。这个问题的本质是服务和文档是割裂的。我们期望的是文档即协议,协议即服务,这个理念与go-zero的api定义不谋而合。
我们定义了BFF层,BFF是对外提供HTTP接口的统一出口,所以我们这里API的定义主要是针对BFF服务的API的定义。
API的兼容性
我们定义或修改API的时候一定要考虑向前兼容,如下几种情况是向前兼容的:
- 增加新的API接口协议
- 请求参数添加字段,需要保证新老客户端对该字段的处理方式不同
- 响应结果添加字段,该字段信息只会在新版本客户端中展示
如下几种情况是向前不兼容的:
- 删除或重命名服务、字段、方法等,从本质上说,如果客户端代码可以引用某些内容,那么删除或者重命名它都是不兼容的变化,这时必须修改major版本号
- 修改字段类型,这会导致客户端库生成的代码发生变化,因此必须增加major版本号,对于编译型静态语言来说,可能会编译错误
- 修改现有请求的可见行为,客户端通常依赖于API行为和语义,即使这样的行为没有被明确支持或记录。因此,在大多数情况下,修改API数据的行为或语义将被消费者视为是破坏性的
- 给资源消息添加 读取/写入 字段
首页API定义
首页功能主要分为四个部分,搜索、Banner图、限时抢购和推荐商品列表,点击搜索框会跳转到搜索页,推荐部分是分页展示的,用户通过不断地往上滑动可以加载下一页。通过分析首页我们大致需要提供三个接口,分别是Banner接口,限时抢购接口和推荐接口。
这里需要注意的是推荐接口,推荐接口返回的数据是需要支持分页的,这里分页采用游标的方式,Ps参数为每页返回数据条数,默认一页返回20条数据,注意在服务端一定需要再次校验Ps值,防止Ps恶意值导致的性能问题,比如Ps传了10000,当为非法值的时候需要把Ps置为默认值,Cursor为游标值,游标为每页最后一条数据的RecommendTime。
返回值中Products定义了返回的商品列表,IsEnd表示是否是最后一页,客户端通过判断IsEnd是否为true决定是否终止请求,RecommendTime为本页返回数据最后一条数据的推荐时间,推进列表按照推荐时间倒序返回。
RecommendRequest {
Cursor int64 `json:"cursor"`
Ps int64 `form:"ps,default=20"` // 每页大小
}
RecommendResponse {
Products []*Product `json:"products"`
IsEnd bool `json:"is\_end"` // 是否最后一页
RecommendTime int64 `json:"recommend\_time"` // 商品列表最后一个商品的推荐时间
}
Product {
ID int64 `json:"id"` // 商品ID
Name string `json:"name"` // 产品名称
Description string `json:"description"` // 商品描述
Price float64 `json:"price"` // 商品价格
Stock int64 `json:"stock"` // 库存
Category string `json:"category"` // 分类
Status int64 `json:"status"` // 状态:1-正常,2-下架
CreateTime int64 `json:"create\_time"` // 创建时间
UpdateTime int64 `json:"update\_time"` // 更新时间
}
抢购有一个倒计时的功能,我们这里返回抢购开始时间,客户端计算剩余时间进行倒计时。
FlashSaleResponse {
StartTime int64 `json:"start\_time"` // 抢购开始时间
Products []*Product `json:"products"`
}
分类API定义
分类列表中可以切换不同的tab来选择不同的分类,同时在每一种分类下面又可以按照不同的维度进行排序,且支持分页。
分类商品列表和推荐接口的分页方式一样,都是采用游标的方式,同时分类商品列表需要根据不同的分类和排序属性进行排序,此类需要排序的列表我们一般会通过redis的sorted set来实现,score为需要排序的属性,比如销量,member为对应商品的id。
CategoryListRequest {
Cursor int64 `form:"cursor"` // 分页游标
Ps int64 `form:"ps,default=20"` // 每页大小
Category string `form:"category"` // 分类
Sort string `form:"sort"` // 排序
}
CategoryListResponse {
Products []*Product `json:"products"`
IsEnd bool `json:"is\_end"`
LastVal int64 `json:"last\_val"`