go-zero 微服务实战系列(二、服务拆分)
微服务概述
微服务架构是一种架构风格,它将一个大的系统构建为多个微服务的集合,这些微服务是围绕业务功能构建的,服务关注单一的业务功能,这些服务具有以下特点:
- 高度可维护和可测试
- 松散的耦合
- 可独立部署
- 围绕业务功能进行构建
- 由不同的小团队进行维护
微服务架构能够快速、频繁、可靠地交付大型、复杂的应用程序,通过业务拆分实现服务组件化,使用组件进行组合从而快速开发系统。
服务划分
我们首先进行微服务的划分,在实际的项目开发中,我们通常采用两种微服务划分策略,第一种方式是通过业务职能进行微服务边界的划分,第二种方式是通过DDD的界限上下文进行微服务边界的划分,我们这里采用大家比较容易理解的业务职能的方式进行微服务划分,再次贴上我们电商项目的思维导图:
从以上思维导图可以看出整个电商系统功能还是比较多的,我们根据业务职能做如下微服务的划分:
- 商品服务(product) - 商品的添加、信息查询、库存管理等功能
- 购物车服务(cart) - 购物车的增删改查
- 订单服务(order) - 生成订单,订单管理
- 支付服务(pay) - 通过调用第三方支付实现支付功能
- 账号服务(user) - 用户信息、等级、封禁、地址管理
- 推荐服务(recommend) - 首页商品推荐
- 评论服务(reply) - 商品的评论功能、评论的回复功能
BFF层
一般对客户端我们都会采用HTTP接口的方式提供服务,那是不是以上划分的这些微服务都需要直接提供HTTP接口对外提供服务呢?这样当然可以,架构整体看起来也比较简单。
但对于一个复杂的高并发的系统来说,我们需要处理各种异常的场景,比如某个页面需要依赖多个微服务提供的数据,为了避免串行请求导致的耗时过长,我们一般会并行的请求多个微服务,这个时候其中的某个服务请求异常的话我们可能需要做一些特殊的处理,比如提供一些降级的数据等。还有我们的页面展示的数据往往都是面向业务功能的,而不是单单某一个微服务的数据,这时候我们往往需要组装多个微服务的数据来满足需求,如果我们每个微服务都直接对外提供HTTP接口的话,那么这些复杂的数据组装和异常处理等工作只能由客户端来完成。众所周知客户端是不宜做复杂的业务逻辑的,客户端的重点应该更多是做交互体验上的优化,我们的整体架构需要做到前轻后重,即客户端逻辑尽量少而把比较重的业务处理逻辑下沉到服务端,而服务端又根据业务职能拆分成了不同的微服务,这些微服务只关注单一的业务,那么这些面向业务场景的复杂逻辑的处理应该放到哪里呢?我们的解决方案就是加一层,即BFF层,通过BFF对外提供HTTP接口,客户端只与BFF进行交互。
BFF层的引入解决了我们上面遇到的问题,但增加一层就会增加架构的复杂度,所以如果你的服务是一个单体应用的话,那么BFF是不必要的,引入它不会增加任何价值。对于我们这个项目来说,我们的应用程序依赖于微服务,同时我们需要面向业务功能提供HTTP接口和要保证接口的高可用,所以BFF对于我们这个项目来说是一个合适的选择。
我们可以提供多个BFF吗?答案是当然可以。BFF的目的是为客户端提供一个集中的接口,例如移动端页面和浏览器页面的数据协议不同,这种情况下为了更好的表示数据,可以使用两个BFF,同时只供一个BFF如果该BFF异常就会导致所有的业务受影响,提供多个BFF也可以提高服务的可用性,降低业务异常的影响面。多个BFF架构图如下:
我们的这个项目为了简化只会采用一个BFF服务。
工程结构
我们采用集中管理的方式,把所有的服务放到一个大仓库中,仓库的目录结构如下:
lebron为工程名,lebron下面有apps和pkg两个目录,其中apps存放的是我们所有的微服务,比如order为订单相关的微服务,pkg目录为所有服务共同依赖的包的存放路径,比如所有的服务都需要依赖鉴权就可以放到pkg目录下。
- app - BFF服务
- cart - 购物车服务
- order - 订单服务
- pay - 支付服务
- product - 商品服务
- recommend - 推荐服务
- reply - 评论服务
- user - 账号服务
在每个服务目录下我们又会分为多个服务,主要会有如下几类服务:
- api - 对外的BFF服务,接受来自客户端的请求,暴露HTTP接口
- rpc - 对内的微服务,仅接受来自内部其他微服务或者BFF的请求,暴露gRPC接口
- rmq - 负责进行流式任务处理,上游一般依赖消息队列,比如kafka等
- admin - 也是对内的服务,区别于rpc,更多的是面向运营侧的且数据权限较高,通过隔离可带来更好的代码级别的安全,直接提供HTTP接口
apps目录下每个服务的结构如下:
大多服务都会拆分成rpc、rmq和admin来满足对内提供rpc接口和运营数据的需求,同时通过rmq来处理流式任务。比较特殊的是app下只有api服务,因为app是BFF所有只有api服务,后面可能会增加rmq服务,比如来流式处理用户每天首次登陆加经验之类的逻辑,我们后面可以随时扩展,暂时先只提供api服务。recommend只有rpc服务,因为推荐服务需要依赖AI团队或者大数据团队提供的数据,我们只需要请求对应的数据接口和做一些满足业务的处理即可,所以这里recommend只有rpc服务。
代码初始化
整个工程的结构已经定义清楚了,下面我们做服务代码的初始化
我们使用goctl来进行项目的初始化,比如我们先初始化order,先进入order目录下:
$ cd lebron/apps/order
执行如下命令即可初始化order rpc代码
$ goctl rpc new rpc
生成的代码结构如下:
执行如下命令即可初始化order admin代码,注意order admin为api服务,直接对前端提供HTTP接口
$ goctl api new admin
生成的代码结构如下:
生成的服务代码我们可以直接运行,默认侦听在8888端口
$ go run admin.go
Starting server at 0.0.0.0:8888...
对于rmq服务我们会使用go-zero提供的 kq 功能,这里先初始化main.go
到这里order服务的代码初始化已经完成,其他服务和order服务类似,这里就不再赘述了。
pkg下目前不需要初始化,当我们需要提供业务通用功能的时候我们再进行添加。
结束语
本篇我们讲解了微服务的定义,微服务是围绕业务功能构建的,服务关注单一的业务,服务间采用轻量级的通讯机制,每个微服务都可以独立的部署和测试。
我们根据商城功能进行了微服务的拆分,主要拆分了购物车、订单、支付、商品、评论、推荐、账号等服务,然后我们又说明了为什么需要引入BFF服务,BFF本质上是一个用于做数据组装的服务,对外提供面向业务功能的或者说面向客户端UI的HTTP接口。
接着我们定义了我们这个工程的目录结构,主要分为api、rpc、rmq和admin等服务,不同服务的职责不同,api对外提供HTTP接口,rpc对内提供RPC接口,rmq做流式数据的处理,admin面向运营后台提供HTTP接口。
最后我们通过goctl对项目做了初始化,使用goctl可一键生成项目框架代码,大大提供了生产力。
希望本篇文章对你有所帮助,谢谢。
每周一、周四更新
代码仓库:https://github.com/zhoushuguang/lebron
参考
https://microservices.io/index.html
https://blog.bitsrc.io/bff-pattern-backend-for-frontend-an-introduction-e4fa965128bf
项目地址
https://github.com/zeromicro/go-zero
欢迎使用 go-zero
并 star 支持我们!
微信交流群
关注『微服务实践』公众号并点击 交流群 获取社区群二维码。
go-zero 微服务实战系列(二、服务拆分)的更多相关文章
- 微服务实战系列--Nginx官网发布(转)
这是Nginx官网写的一个系列,共七篇文章,如下 Introduction to Microservices (this article) Building Microservices: Using ...
- 微服务实战(二):使用API Gateway
微服务实战(一):微服务架构的优势与不足 微服务实战(二):使用API Gateway 微服务实战(三):深入微服务架构的进程间通信 微服务实战(四):服务发现的可行方案以及实践案例 微服务实践(五) ...
- 微服务实战(二):使用API Gateway - DockOne.io
原文:微服务实战(二):使用API Gateway - DockOne.io [编者的话]本系列的第一篇介绍了微服务架构模式.它讨论了采用微服务的优点和缺点,除了一些复杂的微服务,这种模式还是复杂应用 ...
- go-zero微服务实战系列(三、API定义和表结构设计)
前两篇文章分别介绍了本系列文章的背景以及根据业务职能对商城系统做了服务的拆分,其中每个服务又可分为如下三类: api服务 - BFF层,对外提供HTTP接口 rpc服务 - 内部依赖的微服务,实现单一 ...
- go-zero微服务实战系列(十一、大结局)
本篇是整个系列的最后一篇了,本来打算在系列的最后一两篇写一下关于k8s部署相关的内容,在构思的过程中觉得自己对k8s知识的掌握还很不足,在自己没有理解掌握的前提下我觉得也很难写出自己满意的文章,大家看 ...
- Chris Richardson微服务实战系列
微服务实战(一):微服务架构的优势与不足 微服务实战(二):使用API Gateway 微服务实战(三):深入微服务架构的进程间通信 微服务实战(四):服务发现的可行方案以及实践案例 微服务实践(五) ...
- ASP.NET Core微服务实战系列
希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,码字辛苦,如果你吃了蛋觉得味道不错,希望点个赞,谢谢关注. 前言 这里记录的是个人奋斗和成长的地方,该篇只是一个系列目录和构想 ...
- 微服务实战(二):使用API Gateway--转
原文地址:http://dockone.io/article/482 [编者的话]本系列的第一篇介绍了微服务架构模式.它讨论了采用微服务的优点和缺点,除了一些复杂的微服务,这种模式还是复杂应用的理想选 ...
- go-zero 微服务实战系列(一、开篇)
前言 在社区中经常看到有人问有没有基于 go-zero 的比较完整的项目参考,该类问题本质上是想知道基于 go-zero 的项目的最佳实践.完整的项目应该是一个完整的产品功能,包含产品需求.架构设计. ...
随机推荐
- String和int、long、double等基本数据类型的转换
学习目标: 掌握Java的基本数据类型与String的转换 学习内容: 1.转化规则 String 转 基本数据类型 基本数据类型 变量 = 包装类.Parse基本数据类型(String); // c ...
- 小程序picker的使用
效果图: 代码: <view class='infoItem'> <view class='infoItem-left'><text style='color:red'& ...
- (动态模型类,我的独创)Django的原生ORM框架如何支持MongoDB,同时应对客户使用时随时变动字段
1.背景知识 需要开发一个系统,处理大量EXCEL表格信息,各种类别.表格标题多变,因此使用不需要预先设计数据表结构的MongoDB,即NoSQL.一是字段不固定,二是同名字段可以存储不同的字段类型. ...
- What is ACPI
What is ACPI, OnNow, and PCI Power Management? Microsoft began an initiative called OnNow to shorten ...
- Java学习day13
泛型类格式: 修饰符 class 类名<类型>{ } 常用T.E.K.V等形式的参数表示泛型 使用方式与C++的类模板相似,在创建对象时要明确数据类型 泛型方法定义格式: 修饰符<类 ...
- 牛客网 第十八届浙大城市学院程序设计竞赛(同步赛)J--万万没想到 啦啦啦啦啦
我觉得我可以继续wa下去(手动魔鬼笑)-------------------------------------------- 原题链接:https://ac.nowcoder.com/acm/c ...
- 【远程文件浏览器】Unity+Lua开发调试利器
Remote File Explorer是一个跨平台的远程文件浏览器,用户通过Unity Editor就能操作运行在手机上的游戏或是应用的的目录文件.比如当项目打包运行到设备上时,可通过Remote ...
- Istio实践(3)- 路由控制及多应用部署(netcore&springboot)
前言:接上一篇istio应用部署及服务间调用,本文介绍通过构建.netcore与springboot简单服务应用,实现服务间调用及相关路由控制等 1..netcore代码介绍及应用部署 新建.netc ...
- python学习-Day22
目录 今日内容详细 hashlib加密模块 什么是加密 加密算法 加密的使用 基本使用 指定算法(md5) 将明文数据传递给算法对象 获取加密之后的密文数据 加密补充 加盐处理 动态加盐 加密应用场景 ...
- 攻防世界-MISC:a_good_idea
这是攻防世界高手进阶区的第十题,题目如下: 点击下载附件一,解压后得到一张图片,把图片放到kali用binwalk查看一下,果然包含了几个文件, 用命令把文件分离出来, 得到一个misc文件和一个压缩 ...