通常,我们可能已有有一个巨大的单块系统,如何实现微服务,我们需要把它分解。

从哪里开始拆分:接缝

接缝:从接缝处可以抽取相对独立的一部分代码,对这部分代码的修改不会影响系统的其他部分。这些接缝就可以作为服务的边界。

那如何识别出接缝呢?我们可以使用前面所提到的限界上下文,也可通过程序中的命名空间来帮助我们,也可以通过工具来帮助我们,如structure101这样的工具来可视化包之间的依赖。

杂乱依赖的根源:数据库

为什么这么说?因为,通常情况下,我们在业务层的代码已经通过分层组织到相应的包中了,但是只有数据库是共用的,数据库对所有的代码都允许访问,是一个巨大的API。我们举例说明:有一张仓储表,它被“产品目录”、“仓库”、“财务”等服务所共用,那么在单块应用程序中,通常会是下面的结构:

对于同一张表被多个限界上下文使用的场景,我们应该如何处理?以下是一些处理的步骤和原则 :

一.分清代码中对数据库进行读写的部分

我们需要厘清代码是如何访问数据库的,在什么地方读,在什么地方写?他们分别位于什么样的上下文中。

  二.打破外键关系

对于表与表之间的外键关系,如果这两张表需要被拆分至两个微服务中,我们可能需要放弃外键关系,同时把这个约束关系放到代码中实现,我们可能还需要实现跨服务的一致性检查,或者周期性触发清理数据的任务。

我们可以通过类似于SchemeSpy这样的工具来分析数据库表之间的依赖关系。

三.共享静态数据

比如,国家、部门之类的数据都是各个微服务之间经常使用的,这些数据的特征是不会经常变,而且是通用性高。这些数据在微服务划分之后该如何处理呢?

方法一:我们可以为每个微服务复制一份这样的数据,但是这个会导致数据的一致性问题;

方法二:把共享的数据放入代码之中,比如放在属性文件 中,或者简单地放在一个枚举中,但数据一致性仍然存在。

方法三:把这些静态数据放在一个单独的服务中。

四.共享数据

如果不同的微服务都使用了同一张表,比如仓库和财务都用到了客户信息表,这种情况下该如何分享?其实这种情况很常见:领域概念不是在代码中建模,相反是在数据库中隐式地进行建模。这里缺失的领域概念是客户,因而我们需要提供一个新的服务:客户服务。

五.共享表

与共享数据不同的是:不同的微服务也会使用同一张表,但两者修改的部分不一样,这样的情况下,我们可以把这张表拆分出两张表,分别供两个微服务使用。

      六.实施拆分

通常,我们推荐先分离数据库结构然后对代码进行拆分。表结构分离之后,对于原先的某个动作而言,对数据库的访问次数可能会变多。这也是我们需要考虑的问题,这里涉及到分布式事务的相关问题。

另外,先拆分数据库但不分离代码的好处在于,可以随时选择回退这些修改或是继续,而不影响服务的任何消费者。

分布式事务

一个事务可以帮助系统从一个一致性的状态迁移到另一个一致的状态,要么全部都做,要么什么都不做。

在单块结构中,所有的创建或者更新都可以在一个事务边界内完成,分离数据库之后,这种好处就没有了。在分布式事务中,我们有可能面临一个操作成功,而另一个操作失败的局而,我们该如何处理这些问题?

方法1:补偿机制——最终一致性

对于失败的动作,我们进行重复触发,只要在系统可接受的时间范围内,最终一致性是可以接受的。

       方法2:回滚机制

对于失败的动作,我们可以选择回滚。但是回滚也失败的呢?这个时间,要么我们在某个时间重试回滚操作,或者提供一些自动化的操作或界面操作来清除这些不一致的状态。

      方法3:分布式事务

我们可以使用事务管理器来统一编排横跨多个服务的事务,分布式的事务会保证整个系统处于一致的状态,唯一不同的是,这里的事务会运行在不同系统的不同进程中,通常它们之间使用网络进行通信。

分布式事务的常见算法是两段提交,在这种方式中,首先是投票阶段,在这个阶段,每个参与者都会告诉事务管理器是否应该继续,如果事务管理器收到所有的投票都是成功,则事务管理器会告知各个参与者执行提交操作,只要收到一个否定的投标,事务管理器就会让所有的参与者回退。

但两段提交也有缺点,首先所有的参与者都等待中央协调进程的指令,从而很容易导致系统的中断,如果事务管理器宕机了,处于等待状态的事务就永远无法完成;如果有一个参与者在投票阶段发送消息失败,则所有的其他参与者都会被阻,投票之后的提交也可能会失败;另外中央协调进程也可能使用锁,这样会对系统的扩展带来影响。因而这种算法并不是万无一失的。

如果确实存在保持一致怀的场合,应该尽量避免把它们放在不同的地方。

又一个难点:报表数据库

报表通常需要来自组织内各个部分的数据,在以往的单块结构来说,这是很方便的。但也存在一些缺点:首先是修改表结构的风险增大;再者则是报表系统的优先手段有限,比如关系型数据库对于海量的数据不能呈现很好的支持,而MongoDB则地文档存储有其独特的优越性。

一.通过服务调用来获取数据

报表数据通常需要大量的数据,通过服务提供接口来一条条调用很显示是不太合适的,这样非常低效而且对服务来说负载过重。

我们可以一次性返回分页的多条记录,或者在本地将数据导出到文件文件的地址返回给调用方以供使用。

二.数据导出

我们也可以把报表数据周期性的导出,推送到报表数据库,但这样不同微服务的数据又集成到一起的,这时我们可以使用一些技术来屏蔽这些耦合,比如视图

三.事件数据导出

在每次数据发生变化时,数据提供方也会提供一些事件,数据订阅方可以将这些数据导出到报表数据库中,这样源数据与数据之间的耦合就消除掉了,我们只需要绑定到服务所发送的事件即可。

不同前面的周期性导出数据,这里的事件数据是实时,所以能让数据更快地流入报表系统。

另外,我们只需要对新事件产生的新数据进行处理,即处理增量数据,这样的操作会更加高效。

而缺点在于事件数据必须以事件的形式广播出去,同时在数据量时,不容易进行扩展,而前面的数据导出的方式,可以在数据库级别进行扩展。

四.数据导出的备份

这里是整库备份,因而也会造成不同微服务之间数据的耦合。

参考

《微服务设计》(Sam Newman 著 / 崔力强 张骏 译)

相关文章:

  • 微服务的概念——《微服务设计》读书笔记

  • 微服务架构师的职责——《微服务设计读书笔记》

  • 建模:确定服务的边界——《微服务设计》读书笔记

  • 微服务集成——《微服务设计》读书笔记

  • 服务的协作:服务间的消息传递——《微服务设计》读书笔记

原文地址:http://www.cnblogs.com/gudi/p/6667107.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

拆分:分解单块系统——《微服务设计》读书笔记相关推荐

  1. 微服务架构师的职责——《微服务设计读书笔记》

    如何定义架构师 架构师从英文单词Architect翻译而来,在英文中,Architect原来的意思是"建筑师".作者吐槽英文中架构师与传统的建筑师单词相同,但实际的工作性质并不相同 ...

  2. 微服务设计 读书笔记 一

    1.1 什么是微服务 微服务就是一些协同工作的小而自治的服务. 1.1.1 专注于做好一件事 随着新功能的增加,代码库会越变越大.时间久了代码库会非常庞大,以至于想要知道该在什么地方做修改都很困难.在 ...

  3. 中台架构与实现(基于DDD和微服务)-读书笔记1

    前绪 一.DDD(Domain Driven Design,领域驱动设计).微服务.中台 中台需要将通用的.可复用的业务能力沉淀到中台,实现企业级能力的复用.企业在进行中台建设时首先要从业务领域出发, ...

  4. 规模化微服务——《微服务设计》读书笔记

    改变思维的角度:故障无处不在 当微服务规模化后,故障是无可避免的,以往我们总是想尽力避免故障的发生,而当故障实际发生时,我们往往束手无策.我们花了很多时间在流程设计和应用设计的层面上来阻止故障的发生, ...

  5. 康威定律和系统设计——《微服务设计》读书笔记

    康威定律 任何组织在设计一套系统时,所交付的设计方案在结构上都与该组织的沟通结构保持一致. --梅尔.康威 如何理解这句话在软件工程上的含义?埃里克.S.雷蒙德说:如果你有四个小组开发一个编译器,那你 ...

  6. 安全——《微服务设计》读书笔记

    身份认证和授权       1.单点登录(SSO) 当主体试图访问一个资源,他会被定向到一个身份提供者那里进行身份验证,身份提供者验明正向后会发消息给服务提供者,让服务提供者来决定是否允许它访问资源. ...

  7. 监控——《微服务设计》读书笔记

    在单块应用的世界里,当我们遇到问题时,我们至少清楚从哪里开始调查.网站访问速度?网站访问异常?CPU占用过高?这些都是单块应用程序的问题,单一的故障点会极大地简化对问题的排查. 而现在我们面对了多个微 ...

  8. 测试——《微服务设计》读书笔记

    一.测试象限(Brain Marick) 二.测试金字塔(Mike Cohn)       1.单元测试 通常只测试一个函数或方法调用,通过TDD或者基于属性而写的测试就属于这一类,在UnitTest ...

  9. 部署:持续集成(CI)与持续交付(CD)——《微服务设计》读书笔记

    一.CI(Continuous Integration)简介  CI规则1:尽量频繁地把代码签入到分支中以进行集成 CI规则2:不光要对语法进行验,也要提供一系列的自动化来验证 CI规则3:CI失败后 ...

最新文章

  1. SpringBoot 集成 Elasticsearch
  2. Vim 实用技术,第 2 部分: 常用插件
  3. 2.2.5 调度算法:时间片轮转 优先级调度 多级反馈队列
  4. 春招实习前端面试题汇总
  5. java的equals方法_Java Date equals()方法与示例
  6. 部署mysql MHA集群
  7. FTP判断ftp上是否有文件目录,没有就创建的具体案例
  8. 如何为 Mac 添加新语言?
  9. lottie-动画转代码神器
  10. 如何报考华为网络工程师?
  11. My Twelfth Page - 环形链表Ⅱ - By Nicolas
  12. 给初学者用pycharm轻松导入Python各种包
  13. iphone邮箱收件服务器设置,iphone中使用国内邮箱设置方法
  14. 学会java足够开发app吗_请问如何两个月内在不懂java 的情况下学会开发app?
  15. 显卡,就是一个男人对自己的交待
  16. 目标管理的痛?那是因为你没有找准目标管理工具
  17. MYSQL 因单引号报语法错误
  18. Python利用qrcode生成二维码并解析结果
  19. 学习Qt使用GDI+绘图笔记
  20. 2014一年开发技术资料收藏整理(一)

热门文章

  1. Codeforces Round #323 (Div. 2) C.GCD Table
  2. 17款加速效率的CSS工具
  3. google code for xbmc addons2
  4. Win XP2实用的修复工具
  5. 【贯穿】.NET6结合Docker傻瓜式实现容器编排
  6. WPF 模仿IconPacks库写图标按钮
  7. WPF 读取Docx文件并显示(附下载链接)
  8. BeetleX.Http.Clients V1.5发布
  9. C#9引入的自定义类型record
  10. .NET5在开发平台上远优于Java,如何发挥优势?