一拍即合
上一篇《.Net 微服务实战之技术选型篇》, 从技术选型角度讲解了微服务实施的中间件的选择与协作, 工欲善其事, 必先利其器, 中间件的选择是作为微服务的基础与开始, 也希望给一直想在. Net 入门微服务的同行有一个很好的方向. 在此篇重新整理了一下整个微服务项目的 demo, 希望对有需要的朋友起到一定的帮助: https://github.com/SkyChenSky/Sikiro
那么我在公司实施微服务的时候, 也不是一拍脑袋想上就上的. 刚入职公司的时候才 3,4 个人, 产品给到我的规划只有一个很简单的系统, 包含权限, 客服 IM, 内容管理三个模块, 我当时想着优先证明我们的开发能力和效率, 于是使用简单的单体架构不到三个星期项目就完成了. 产品在我们开发的期间把整个项目的规划和平台系统的划分给梳理了一遍, 终于让我有一个很明确的技术实施方向, 同时公司的人力成本预算也批了下来开始进行团队扩招.
于是我与老领导商量了一下, 在现在这个情况, 无论业务还是团队都具有使用微服务架构的可操作性, 再采用部分 DevOps 的思想给与微服务实施的支持, 能顺利的实施落地微服务问题不大. 我们俩讨论了一番, 我有良好的微服务技术储备, 他有很好的运维支撑, 就这样咱两达成了共识. 于是我着手翻出了收藏已久的微服务中间件, 架构分层, 服务拆分的资料, 从此开始了我的微服务实施之路.
PS: 我们讨论实施微服务的时候除了以上冠冕堂皇的理由之外, 其实还存有一点私心, 就是现在企业招聘很多需要有实施微服务经验的人才, 但是 80% 的项目和同行又是没有这样的实施必要与经验, 这就是鸡生蛋和蛋生鸡的问题. 我毫无隐瞒的说出我们的私心并不是怂恿大家冒着风险去实施, 而是希望大家通过分析现在团队的组织架构, 技术储备, 业务架构, 在条件允许的情况下满足您的小小要求, 微服务虽不是银弹, 但我们也需要成长.
架构思维
抽象是作为架构思维的核心, 使我们站在大局观察, 屏蔽细节; 这系统划分哪几个模块? 模块之间的如何协作的? 抽象又可以衍生出两种思想划分与协作.
划分的目的是为了定责与拆分, 定责不是交通事故的定责而是划定职责, 明确模块的使用场景, 应该被什么依赖? 应该依赖什么? 拆分其实就是分而治之的思想, 把一个复杂的大问题拆分成一个个简单而小的问题, 化繁为简逐个击破自然就迎刃而解.
协作的目的是整合划分好的模块, 被拆分的模块如果无法整合到一起, 拆分则失去了他原有的意义.
不谋而合
技术服务于架构, 架构服务于业务, 业务服务于商务. 所以有明确的业务蓝图才可以很好的规划架构方向; 选择好合适的技术才能很好的支撑架构. 此时我们开始着手实施微服务, 然而在实施时我们还会考虑一个比较核心点, 究竟如何微? 粒度究竟到什么程度? 怎么明确依赖关系? 大家或多或少都会听说身边同行有实施微服务的失败案例: 拆分粒度过细导致系统复杂度过高; 拆分粒度太粗又没达到微服务该有的效果等. 那么是否在业界有一套科学的指导方法论? 我认为是有的, DDD 战略设计与分层架构.
埃里克, 埃文斯在 2004 年发表了《领域驱动设计》一书的, 此后一直是雷声大雨点小, 在 2014 年软件教父马丁花给微服务一个全面描述, 让它走向一个高潮后, DDD 终于赢来了他的春天. 为什么说 DDD 适合微服务呢? DDD 是一种通过划分业务边界, 将复杂的业务领域简单化的设计思想, 也就是化繁为简. 为什么在上文重点强调 DDD 战略设计? DDD 分为战略设计与战术设计.
战略设计
主要从业务视角出发, 建立业务领域模型, 划分领域边界, 建立通用语言的界限上下文, 界限上下文可以作为微服务设计的参考边界.
战术设计
主要从技术视角出发, 侧重于领域模型的技术实现, 完成软件开发和落地, 例如我们常讨论的聚合根, 实体, 值对象, 领域服务等代码逻辑的设计与实现.
从以上两点的描述可以看出, 战略设计从业务视角出发, 而架构服务于业务, 两者都需要从业务出发, DDD 战略设计与微服务都有同样的设计思想: 分而治之, 化繁为简, 那么战略设计的思想完全可以作为微服务架构设计的指导思想, 此时此刻此场景不谋而合.
分层架构
也可以叫 N 层架构 (N>=2), 其实本质在于划分职责, 隔离关注点, 保证各层之间的差异足够清晰, 边界足够明显, 其特点自顶向下依赖, 逐层传递.
纵向拆分
首先我按照分层架构的思想以纵向维度拆分, 主要共分 5 层, UI 层, 聚合 API 服务层, 基础业务 API 服务层, 基础设施层, 数据库层.
调用链路自顶往下, 用户 -->UI-->API 网关 --> 聚合 API 服务 -->Consul+Consul Template+Nginx--> 业务 API 服务 --> 数据库
UI 层
依赖于聚合 API 服务层, 操作与接口 11 对应, 主要负责可见即可得的工作: 数据展示, 交互动画等.
入站 API 网关
主要负责聚合 API 服务层内外网隔离, 入站规则控制, 防止外部大流量冲垮内部服务.
聚合 API 服务层
被 UI 层依赖, 依赖于基础业务 API 服务层, 主要负责基础业务 API 服务层的接口的逻辑组合, 不直连数据库, 可通过 API 网关暴露给 UI 层调用.
注册服务中心
记录基础业务 API 服务层的服务 IP 列表, 内网使用, 衔接聚合 API 服务层与基础业务 API 服务层.
基础业务 API 服务层,
被聚合 API 服务层依赖, 依赖于数据库层, 可做具体的数据库读写处理, 内网使用, 同层服务之间不互相依赖引用.
数据库层
包括非关系型数据库与关系型数据库.
基础设施服务层
可被所有层都依赖, 如果被 UI 层依赖则通过 API 网关暴露, 如果被内网服务依赖则通过注册发现, 可直连数据库.
出站 API 网关
主要负责基础设施服务层内外网隔离, 转发第三方开放 API 请求, 出站规则控制, 防止被无法把控的第三方服务而拖垮内部服务.
横向拆分
接下来, 我们可以通过 DDD 划分领域的方式进行服务的横向维度的拆分. 举个例子:
我们平台拥有三种不同业务领域的系统: 客户中心, 企业管理系统, 内部管理系统.
那么, 聚合 API 服务层则拥有客户系统 API 服务, 企业管理系统 API 服务, 内部管理系统 API 服务.
客户中心的拥有客户信息管理, 支付, 订单管理等业务模块.
企业管理系统拥有订单管理, 权限管理, 支付, 仓储等业务模块.
内部管理系统拥有权限管理, 报表, 账户管理等业务模块.
所有系统涉及到自定义订单号, 消息推送等业务.
从以上得知, 核心域包括仓储, 订单业务, 客户信息. 通用域包括权限管理, 账户认证, 支付模块, 消息推送等. 支撑域包括自定义订单号.
因此基础业务 API 层可以划分: 仓储 API 服务, 订单 API 服务, 客户 API 服务, 权限 API 服务, 认证 API 服务, 支付 API 服务.
基础设施 API 层可以划分: ID 发号 API 服务, 消息推送 API 服务.
如果随着业务继续扩大, 团队人数增多, 则可以更加的细分, 例如仓储拆分成快运, 集运等. 支付拆分成微信支付, 支付宝等.
项目示例
上一篇《.Net 微服务实战之技术选型篇》我整理了我们公司使用的框架开源到了 GitHub, 这次我拿了部分业务项目作为示例并上传了.
https://github.com/SkyChenSky/Sikiro
首先想说明几点:
1. 这个不是标准, 只是针对我们公司情况取舍后的结果, 每个公司的业务有复杂有简单大家视情况完善自己的项目.
2. 为了保护公司原有的业务隐私, 我做了部分逻辑的删除, 所以大家如果看到不完整的逻辑是正常现象.
3. 希望大家把思维放高, 不要死抠细节, 求同存异.
4. 代码在原有的基础上修改了名称和引用路径会有变化, 如果有问题随时在评论和 GitHub 反馈给我.
来源: https://www.cnblogs.com/skychen1218/p/12653155.html