近年来,我们发布了很多文章介绍企业向微服务迁移的成败经验。最近,Segment的Alexandra Noonan写了一篇文章,讲述了他们从单体架构迁移到微服务,之后又退回单体应用的经历。文中Alexandra具体介绍了他们从原来的简单架构迁移到微服务的过程:

\\

\

我们原来有个API负责拦截事件并将它们转发到一个分布式的消息队列中。这里的一个事件指的是由网页或移动应用生成的,包含用户与用户动作信息的JSON对象。当队列中的事件被消费后,系统会检查用户设置来决定接收事件的目标。(……)之后事件被逐个发送到每个目标的API。这样的流程很合理,因为开发者只需要将事件发送到Segment的API这一个目标即可,无需创建几十个集成。

\

\\

如果事件交付失败,就会被系统重新加入队列,也就是说有时工作者进程要一边发送新的事件,一边尝试重新发送之前失败的事件。这样会导致所有目标都出现延迟,Alexandra解释说:

\\

\

为解决最紧迫的阻塞问题,团队为每个目标各创建了一个独立的服务和队列。这一新架构包括一个新的路由进程,它会接收入站事件并向每个选定的目标分发一份该事件的拷贝。现在如果某个目标出现问题,只有它自己的队列会回溯,不会影响其它目标。这一微服务化的架构将各个目标独立开来,这样当某个目标又出现常遇到的问题时就会非常有用。

\

\\

文章之后写到,Segment的开发团队一开始将所有代码存放在一起,但这引发了许多问题:

\\

\

最大的麻烦在于,只要一个测试崩溃,那么所有目标的测试都会失败。当我们试图部署一项改动时,我们必须先费劲修复崩溃的测试,就算改动与一开始的变动毫无关联也得这样做。为了解决这个问题,我们决定将代码拆分到每个目标各自的存储库里。

\

\\

这样一来开发团队的灵活性的确改善了许多。然而随着目标数量的增加,存储库的数量也在同步增长。为了让开发者免受维护这么多代码库的麻烦,Segment团队创建了许多共享库,存放所有目标通用的变换和功能。这组共享库大大减轻了他们维护工作的压力。但这个措施也有不太容易发现的负面影响:向共享库更新并测试改动会花费大量时间,还会增加破坏无关目标的风险。最后这些库开始分裂为不同的版本,各自不统一,引发了之前没有想到的一个问题:每个目标的代码库都会依赖不同版本的共享库。Alexandra承认,他们当时可以开发工具来自动将改动更新到这些库中,但那时他们又遇到了这个微服务架构产生的一些新问题。

\\

\

新出现的问题是,每个服务都有自己的负载模式。有些服务一天处理几个事件,有的服务每秒就能处理几千个。如果目标只处理很少的事件,工作者线程就得在出现负载问题时手动扩展服务以满足需求。

\

\\

他们的系统集成了自动扩展能力,但因为每个服务都需要指定CPU和内存资源分配,调整自动扩展的设置“更像玄学而非科学”。如前所述,每次存储库的数量增长时他们都要增加目标,最后团队平均每月要增加三个目标,当然还要加上更多的队列和服务。

\\

\

2017年初,Segment的一个产品的核心部分使我们达到了峰值负载。当时的情况下我们好像在从微服务的大树上摔下来,一路撞上了所有的树枝。我们这个小团队非但没有提升效率,反而陷入了愈加复杂的泥潭。这个架构的核心优势都成了负担。我们的速度暴降,故障率却在暴增。(……)于是,我们决定回退一步,重新考虑整个流程。

\

\\

文章最后Noonan回顾了他们如何摆脱这个微服务架构,其中他们还开发了Centrifuge来替换所有独立的队列,将所有事件都发送到一个单体服务上。他们还将所有目标的代码都迁移到一个存储库里,不过这一次新增了一些代码管理的规则:所有目标都要使用同一个版本,每次更新时同步更替到新版本。他们再也不用操心各个独立版本之间的差异了,因为所有的目标都在使用一个版本,以后也是如此。对于开发者来说,管理越来越多的目标所花费的时间减少了,风险也降低了。

\\

Noonan的文章还写了很多内容,都是关于他们退回单体服务的经历。感兴趣的读者应该去仔细读一下,文章里面有很多架构细节、关于存储库架构的思考和建立弹性测试集的方法。最后,团队将回退的好处总结如下:

\\

\

2016年时我们还在使用微服务架构,我们为共享库带来了32项改进。而仅仅今年到现在我们就做出了46项改进。过去半年来我们为库带来的改进比2016年全年都多。因为所有的目标都处于同一服务内,我们可以很好地搭配CPU密集型服务和内存密集型服务,所以扩展服务以满足性能需求变得非常容易。更大的工作者池能负载更多内容,所以我们不再需要将处理少量负载的目标挂起到页面了。

\

\\

不过这个架构回退过程也有一些负面影响,包括:隔离错误变得更困难(一个目标的错误导致目标崩溃,结果会传染到所有目标);升级一个目标的版本可能会破坏其它一些目标,于是后者也需要升级。Noonan在文章最后写下了诚恳的总结:

\\

\

在微服务和单体架构之间做选择时,要注意它们各自都有自己需要考虑的因素。我们的架构中有些部分是微服务表现更出色,但服务端的目标迁移到微服务后的一系列麻烦是一个很好的教训,证明这一流行趋势在某些情况下能对生产力和性能有多大负面影响。结果对于我们来说,单体架构才是最终解决方案。

\

\\

其实他们关于微服务的某些看法是很眼熟的。今年早些时候我们报道说,ThoughtWorks根据观察认为微服务尚未进入普及周期。当时的报道写到:“主要原因之一是很多组织并没有为微服务做好准备,他们缺少一些关于运营和自动化的基础实践”。此外,Jan在另一篇文章中总结了多年来微服务迁移的失败案例。Berico科技的首席软件工程师Richard Clayton提到了他们当时遇到的一个问题:

\\

\

在不同服务之间共享通用功能代码,以消灭各个服务中的重复功能的努力却带来了巨大的负面影响,最终导致了大规模回退。

\

\\

回到原文,有很多关于这个话题的讨论,比如Hacker News和Reddit上的这些;有些讨论者认为与微服务无关的一些因素可能导致了这些问题。比如,有些评论指出Noonan的文章并没有引用CI,只有CD,起码这是一个奇怪的组合。还有评论认为不止微服务会引发这些问题,所有的分布式系统都是一个样。关于这一点我们之前也提到过,有人使用SOA时有过类似的经验:

\\

\

我曾在一个类似的代码库中工作过,那时他们管它叫SOA,云还没开始流行。对服务的每次调用都会启动一个完整的服务实例。我想我们应该强制将网络延迟规定为架构设计的要素之一。

\

\\

有趣的是很多讨论串谈到了微服务中数据上下文的问题。这个话题我们探讨过很多次,这也是微服务反对者的主要论据之一。HackerNews的一条评论举例说:

\\

\

比这还糟呢。据我观察多数微服务架构根本就没考虑一致性(“我们才不要乱七八糟的事务!”),盲目地随大流还乐在其中。我搞不懂为啥子人们会觉得,把软件模块拆分开来然后用缓慢不可靠的网络和弱爆的手动连接REST处理串起来,就能神奇地让架构面目一新哩?我觉得人们产生这种生产力幻觉的原因是:”我把这些都搞定啦,现在我也有一套’管它是什么即服务‘的先进玩意儿喽!看看那酷毙的数据面板上闪烁的小绿灯吧,我们可是为了它干了好几个月呢!“

\

\\

另外,为微服务定义域是多年来我们一直强调的微服务部署关键环节。有一篇PPT介绍了如何使用DDD解构单体应用,Reddit的一个讨论串也谈到了这一点:

\\

\

建立一个出色的微服务架构是很难的。我现在觉得关键在于恰当地分隔你的域,当系统进化时持续关注这一层面。微服务并不像它的名字那样,它不必非得那么小,但是要搭配适合这个架构的元素。很多人的失败正是因为忽视了这一点。

\

\\

其他人怎么看?比如说,Segment的微服务架构出现的问题能否用其它方式解决,无需退回单体应用?或者一开始的单体架构是否有办法进化得更好,解决原来的问题,而无需切换到微服务?

\\

查看英文原文:Why Segment Returned to a Monolith from Microservices

\\

感谢冬雨对本文的审校。

为什么Segment会从微服务退回单体架构?相关推荐

  1. 8 场 5 胜,微服务 VS 单体架构

    来源:thenewstack.io/ microservices-vs-monoliths-an-operational-comparison/ 对比1:网络延迟 对比2:复杂性 对比3:可靠性 对比 ...

  2. 微服务与单体架构:IT变革中企业及个体如何自处?

    戳蓝字"CSDN云计算"关注我们哦! 作者:DAN KUSNETZKY 转自:RancherLabs 当下,企业越来越多地受到竞争对手和他们自己的客户的压力,既需要让应用程序更快地 ...

  3. nodejs微服务:单体架构与微服务架构

    单体架构 单体架构在中小企业内部用的是非常多的,就是完整独立的web服务 当业务不复杂,团队规模不大的时候,单体架构比微服务架构具有更高的生产率 1 ) 单体架构的程序部署在单台服务器 这种架构是目前 ...

  4. 架构之:微服务和单体服务之争

    文章目录 简介 先单体再微服务 直接从微服务开始 总结 简介 微服务和单体服务的各自好处之前的文章中已经讲的很明白了.本篇文章不是探讨到底应该用哪种服务架构.而是假设项目最终会采用微服务架构,那么就会 ...

  5. Jeecg Boot 2.3 里程碑版本发布,支持微服务和单体自由切换、提供新行编辑表格JVXETable

    项目介绍 JeecgBoot是一款基于代码生成器的低代码平台,开源界"小普元"超越传统商业级平台!采用前后端分离架构:SpringBoot 2.x,Ant Design&V ...

  6. 应对海量并发请求,首席布道师谈微服务的应用架构设计

    何李石 七牛云首席布道师 <Go语言程序设计>译者,Go语言/容器虚拟化技术布道师.实践者. 5年以上互联网创业经验和企业级产品研发.运营经验,同时也是互联网产品基础架构解决方案专家. 随 ...

  7. 如何删除网关的session_微服务安全认证架构是如何演进而来的?坐好小板凳一起来听一听...

    之前有同事问为何要用基于JWT令牌的认证架构,然后近期又有童鞋在后台留言问微服务安全认证架构的实践,因此我决定花两篇推文来解答一下.为了答好这个话题,我们先来看看微服务的安全认证架构是如何演进而来的, ...

  8. 微服务浅述---架构演进

    微服务浅述---架构演进 提到架构演进,我们很容易想到'单体应用---分布式/SOA---微服务'的演进过程,那么为什么会有这个必然演进?演进的过程中遇到了哪些坑?是怎么解决这些坑的? 为什么会有这个 ...

  9. 又一神作,Alibaba“M8级”大老总结微服务与事件驱动架构启蒙手册

    首先什么是事件驱动型微服务?(书中摘要) 微服务和微服务类型的架构已经存在很多年了,它们有许多不同的形式和名字.面向服务的架构(service-oriented architecture,SOA)通常 ...

最新文章

  1. 从实例入手学习Shiro的会话机制
  2. linux ppc64 是什么,docker - 在(模拟)PPC64 Linux上的backtrace()segfaults - 堆栈内存溢出...
  3. Android—简单路由框架实践
  4. iPhone 5的发布日期估计为9月21日挂
  5. 指定的颜色信息显示方法
  6. C/C++ 变量的初始化
  7. WPF事件中的sender就是事件源
  8. 查看已安装java插件_记录下eclipse下的插件安装,查看及删除方式
  9. android bionic memcpy 汇编源码解析
  10. 数学建模教程:CBA-基于关联规则的分类算法
  11. u盘启动盘恢复计算机,怎么还原u盘启动盘为普通u盘?
  12. windows图片和传真查看器打不开的解决办法
  13. 课程回顾丨基于FPGA的OFDM可见光通信系统实现
  14. android socket 长连接_java-socket长连接demo体验
  15. 脖子黑色素沉淀怎么去除,有效方法
  16. 【短链接】——新浪、百度、搜狐等官方长链接转短链接
  17. Jetson NX Ubuntu 18.04下谷歌输入法候选框不显示解决办法
  18. python excel写入日期变数字_解决python 读取excel时 日期变成数字并加.0的问题
  19. (转)对话架构师:短视频社区“美拍”的架构实战
  20. 帕斯卡三角形,二项式定理

热门文章

  1. 解决问题:心态 原则 方法
  2. HelloWorld实例(springmvc版)
  3. jquery可编辑表格(版本二)
  4. java数组的api_java程序员常用的11个API,赶紧收藏
  5. 修改表字段类型长度_PG修改字段
  6. 初识Docker-Docker的安装
  7. Nginx中添加gzip_static支持
  8. Network Namespace
  9. 如何确定coordinator
  10. aop简介-基于jdk的动态代理