75% 新项目都可以“无脑”选择单体架构


75% 新项目都可以“无脑”选择单体架构

文章插图
 
以微服务的方式构建新项目并不困难,新架构带来的新承诺也着实令人充满期待 。然而,现实与想象往往相去甚远 。本文是该作者 Arnold Galovics 关于微服务系列文章中的第二篇 。感兴趣的朋友可以点击此处阅读第一篇《新项目别一上来就用微服务》,在第一篇文章中,Arnold 介绍了微服务架构对于基础设施的要求、更快的部署特性、给组织文化提出的挑战以及天然的故障隔离优势 。
 
Arnold 提示道:“本系列文章中提到的所有观点都是个人心得,毕竟不同环境、组织和项目都会给开发工作带来变数 。没准我踩过的坑反而是你开发流程中最顺畅的部分,我的考虑方式也未必符合各位的实际情况 。总之,内容仅供参考,请大家轻拍 。”
 
本系列目的在于提醒大家,只有对新项目建立起深入的评估与理解,才能真正找到最适合的架构选项 。当然,也期待大家在留言中分享自己的真知灼见 。以下是正文:
易于理解很多朋友都觉得微服务架构的理解难度更低……但事实真是这样吗?
 
当然了,我们只需要具体管控各个肩负明确职责的微服务项目,所以每种元素在干嘛、需要干嘛、系统整体状况如何不就更清晰了吗?毕竟我们面对的是一个个服务,而非彼此交织的架构整体 。
 
但我要给大家泼点冷水:这完全就是骗人的 。没错,确实有一些微服务架构做出了优秀的边界定义,任何半路介入的参与者都能快速理解某项微服务的实际作用 。但也有很多项目做得不好,导致某项服务要么做得太多、要么做得太少;甚至部分单一功能也被过度拆分成了多项服务,因此系统的混乱度大幅提升,任何单一服务的故障都可能将整体应用拖入崩溃的深渊 。
75% 新项目都可以“无脑”选择单体架构

文章插图
 
大家可能会说,“对,这种情况是有,但那是你的问题、不是微服务的问题”,或者“你笨啊,笨还能怪架构?”有道理,但问题是项目绝对不可能百分之百受控,真的不可能 。团队、组织、项目,各个层面都有出错的可能,所以边界定义不清的几率会远远高于边界定义良好的几率 。
 
但我也承认,这种情况在单体式架构中也可能带来麻烦 。我也见过那些搞不清在干什么的单体式应用,所有功能就像飘香拌面一样混杂成大坨,代码库硕大无朋、缺少必要的测试、说明文档含糊不清、不同功能的编程风格格格不入等等 。
 
不过单体式架构修改起来还是更轻松一点,它相较于微服务的优越性也正在于此——模块化 。我们同样像为微服务定义边界那样进行代码构建,只是不再将这些“服务”或者说模块视为其他应用的元素,而是同一整体中的各个组成部分 。
 
所以对我来说,这种杂乱的毛病主要还是出在微服务架构身上 。只是我也承认,如果要想搞砸,那在单体式架构中也一样可以搞砸 。
可扩展性提到微服务,网上总在强调“你可以横向扩展各项服务——也就是为同一服务启动多个实例,从而轻松应用负载增长 。”
 
说得倒是轻巧,但具体实现起来有那么简单吗?我们用以下架构为例(沿用系列第一篇文章的用例):
75% 新项目都可以“无脑”选择单体架构

文章插图
 
假定你的应用中有大量活跃用户,所以系统需要处理众多用户会话 。那很明显,我们就得启动多个会话服务 。
 
如果会话服务可以通过 HTTP 协议访问,那用多实例实现就会比较困难 。如果是通过 API 网关或者登录服务来接入会话服务,那就得调用会话的 HTTP API 。但使用 HTTP API 时,我们得调用表达特定会话服务实例位置的特定 URL(主机+端口) 。所以如果同时启动多个会话服务,消费方就得调用多个主机+端口组合 。
 
这个问题倒不至于无解,常见的办法就是使用服务注册表或者负载均衡器 。如果是使用服务注册表,那么当实例启动时,它们会将自身注册到某种类型的存储当中,再通过存储检索实例的相应位置 。这时候当消费方服务打算跟特定服务对话时,它就会先到服务注册表去检索实例位置,之后再使用该位置实现与特定实例的对话 。
75% 新项目都可以“无脑”选择单体架构

文章插图


推荐阅读