微服务与单体那些事儿

本篇文章比较长,主讲架构,因为架构不是个技术问题,他牵扯面很多,比较复杂,所以会长;
本文会结合实验室这多年来的项目经验,以及开源这几年来认识的其他企业相关经验,还有身边一二线大厂、中型企业、小企业、国央企、政府科研院所等相关技术朋友的项目经验,还有"商业"、"成本"、"人员"、"团队"等其他方面的因素,来讲述架构;

希望能以最普通、最简单的文字讲清楚"架构",也希望无论你是初出茅庐的青涩少年、还是炉火纯青技术大佬,也都能看得懂。

一、背景与问题

为什么写这篇文章,是发现这几年来,很多人问 如下几个问题:

  • "是否有微服务经验?"
  • "为什么不用微服务?"
  • "你是不是没用过微服务?"

二、关于架构的认知

很多人认为架构是一个技术问题,但笔者认为,架构是一个 "复杂科学"的技术问题,他需要考虑"技术能力"、"团队组织"、"基础设施"、"商业价值"、"业务形态"、"时间周期"、"边际成本"等等多个方面。如果只是从技术方面考虑,容易误入歧途。

  • 技术能力:无论什么架构,在这种架构上的技术你是否精通?是否有系统且全面的架构解决技术能力?实验室对于架构技术的理解是,一定要系统且完整、全面的把这个技术从头到尾的学习一遍,且从外到内,再从内到外理解深刻后,并从小到大在真实的项目中使用过,才是真正的掌握某个技术。
  • 团队组织:首先团队每个人要对这种架构熟悉,且团队必须有个拥有此架构落地经验的架构师,围绕架构师周边还需要有高级开发负责核心模块,与此同时还需要有一些负责业务开发中后端。
  • 商业价值:无论哪种架构,只要脱离业务和商业,都属于空谈架构,但结合业务需求来看,不合理的架构会给商业带来风险。比如你利用架构支撑那些现在不需要的业务需求,导致许多努力、人力、财力白白浪费,这叫做架构努力错位。比如用一个单体架构开发一套大型电商平台,异或使用微服务架构开发了一个简单的后台管理CMS系统等等
  • 业务形态:要关注业务的属性,比如是传统行业ERP、CRM、MES系统关注的是单据的流转,互联网行业的电商、在线教育等关注的是用户体验,物联网项目关注的是数据采集和报警等等,这些系统的业务形态,比所以用到的架构是不一样的。
  • 时间周期:比如需要很短时间内做一个试验性的产品、或者长时间内做一个电商项目、再或者很明确要长期做一个大型企业的内部ERP系统等等;对于实验性项目突出的就是快,那么相对单体更适合,比如长期的复杂电商项目,相对微服务会比较好一些,但是这些都是相对而言,具体还是需要按照实际的周期来看。再比如融资了100万,做一个细分小领域的B2C平台,你该怎么选择呢?
  • 边际成本:要考虑人工成本、维护成本、质量成本、性能成本,所有权成本、软硬件成本等等
  • 其他方面:基础设置是否成熟、扩展、市场时间等等

架构设计的三大原则:简单、适度、演化

三、单体架构

单体架构最种常见,也是这几十年来最主要的架构。使用经典的 3 层模型,即表示层、业务逻辑层和数据访问层即所有功能都在一个工程里,打成一个jar包、war包进行部署。

案例:

1)早期开源中国(oschina)是个经典的案例,以一台4核8g撑起来一个十几万人的社区,且jfinal就是模仿的oschina的架构。

2)github,GitHub 是基于 Ruby on Rails 的单体架构,直到 2021 年,为了让超过一半的开发人员在单体代码库之外富有成效地开展工作,GitHub 以赋能为出发点开始了向微服务架构的迁移。

3)互联网大厂后台管理系统,央国企的后台管理系统,ERP、OA、CRM等等传统应用

3.1、优缺点

优点:
1、单体架构开发简单,容易上手,开发人员只要集中精力开发当前工程
2、容易修改,只需要修改对应功能模块的代码,且容易找到相关联的其他业务代码
3、部署简单,由于是完整的结构体,编译打包成jar包或者war包,直接部署在一个服务器上即可
4、容易扩展,可以将某些业务抽出一个新的单体架构,用于独立分担压力,也可以方便部署集群
5、性能最高,对于单台服务器而言,单体架构独享内存和cpu,不需要api远程调用,性能损耗最小
缺点:
1、灵活度不高,随着代码量增加,代码整体编译效率下降
2、规模化,无法满足团队规模化开发,因为共同修改一个项目
3、应用扩展性比较差,只能横向扩展,不能深度扩展,扩容只能只对这个应用进行扩容,不能做到对某个功能点进行扩容,关键性的代码改动一处多处会受影响
4、健壮性不高,任何一个模块的错误均可能造成整个系统的宕机
5、技术升级,如果想对技术更新换代,代价很大

3.2、建议

  • 如果之前没做过这个行业,人力和财力不足或者一般,那么直接单体就可以了,随着业务发展一步一步看。倘若人力和财力充沛,在不会加班的前提下,必须秀一把微服务,哈哈~
  • 如果之前做过,依据之前经验,结合当前业务和未来规划,优化架构,做到更好。

四、多模块(SOA)

随着业务发展,重构,单体架构中,业务、代码越来越多,出现了上面3.2相关的问题,于是将系统按照模块业务拆分成多个单体小系统,系统和系统之间通过明确的接口或者消息串联起来;每个系统内部结构和逻辑发生改变,并不影响对外提供的服务,只要保持接口不变,服务内部对外是透明的;

典型案例

早期淘宝,dubbo最初的版本,目的就是多模块这种,只不过支持了集群而已,但是已经向微服务架构迈出了很大的国产化一步

4.1、优缺点

优点:
1、项目制:一个业务单元对应一个系统,由不同的团队开发,好组织和管理
2、扩展性:可以根据不同的需求,进行重新的组合和构造。
3、耦合性:把模块拆分,使用接口或者消息通信,降低了模块之间的耦合度
4、复用性:可以重复利用,相对业务属性独立
5、敏捷性:方便更新,迭代,可以只更新单个服务(系统)而不需要重写整个项目
缺点:
1、灵活度不高,随着代码量增加,某些系统还是会变得复杂和臃肿
2、开发难度大,业务抽取、接口或者消息设计等问题,考验着团队的技术能力
3、数据一致性问题
4、业务拆分,你确定拆分的准确吗?

4.2、建议

  • 如果之前没做过这个行业,感觉哪块代码量已经很多,逻辑复杂,又相对独立,然后拆吧,试一下,有问题再改。
  • 如果之前做过类似项目,依据之前经验,该拆的果断一点,拆他瞄的。

五、微服务

终于到微服务了,但是随着用户和数据量的进一步增长,多模块系统(SOA),服务管理不完善,再扩展也很难,所以这个时候出现了微服务。

这里在明确几个微服务的属性:

  • 1)代码库是分开,每个服务单独人维护,独立迭代
  • 2)集成和部署分开,独立且自由的发布
  • 3)数据库分开
  • 4)必须容器管理,网关,、服务治理,服务监控,服务跟踪等基础设施
  • 5)必须有专人来维护服务,而不是就2,3个java共同维护多个微服务就搞笑了
  • 6)技术栈也可以不相同,只要遵守 api json 接口协议即可

以上5点是必须有的,如果没有,可能你的并不是微服务。

5.1、优缺点

优点:
1、独立性:每个服务都是独立灵活,且独立迭代和独立部署
2、扩展性强:微服务之间是松耦合的,内部是高内聚,容易按需扩展,产品迭代周期更短
3、隔离性好:每个微服务都是独立的运行,有服务挂掉不会大面积地波及整个服务运行体系
4、技术选型灵活:对于独立的某个服务,用什么技术栈都可以,比如作者希望用nodejs,完全没问题
缺点:
1、复杂度很高:一个业务流程需要多个微服务通过网络交互来完成,开发、调试都很复杂
2、维护成本大:需要有人维护容器管理,网关,、服务治理,服务监控,服务跟踪等基础设施
3、确定哪些业务是一个服务很难,因为微服务要拆的更细,什么拆什么不拆,其实很难决策

5.2、建议

  • 如果之前没做过这个行业,人力和财力充沛,在不会加班的前提下,大胆的搞吧,有的是时间和金钱
  • 如果之前做过类似项目,依据之前经验,再来一遍喽

六、微服务病态

当前了解了千余家企业、还有身边认识的大、中、小企业,都陷入了一个怪圈,"我们后端微服务架构,很屌的,网关、服务治理、跟踪、监控、docker全都上了,架构很漂亮的"。我们也以人员外包的形式协助过一些企业一起开发过他们所谓的"微服务"项目,最终结论就是 "写代码好累,沟通好累,交流好累,改bug改的好累,心累,想骂娘";我们依次举几个真实案例:

6.1、某中型文具电商项目

背景:

地点:北方前5的城市

有crm系统、erp进销存系统、面向C端电商系统、B端代理电商系统、有app端应用、也要对接淘宝拼多多下单

之前系统是php研发,老板要大干一场,技术团队换成了java(java这批人也不懂文具行业)

最终技术团队(写代码)大概20个人(1个前端架构,5个前端、1个后端架构,8个后端、4个移动端、1个运维)

B端客户2000人,C端累计用户几十万(注意累计)

开始了:

  • 了解业务,拆分服务,拆分服务,最终20个java服务 ,具体服务为:C端用户、B端用户、商品、B端订单、B端账户、C端订单、交易、仓储、物流、电商对接、CRM电销、文件、合同、资讯、PC、电商App、网站数据、运营活动、财务软件对接、公司员工 等,10个公共模块,10个数据库
  • 容器管理,网关,服务治理,服务监控,服务跟踪等项目,最终java30个,要部署的docker,约40个(含前端)
  • 服务器部署:2台阿里云服务器,64G内存, 每台部署了20多个docker(redis、nginx等等其他)

看到这里,想必你已经知道了里面的弊端,以这样的人员规模弄了一套这么大的系统,很"牛"!运行过一段时间后,发现数据:

  • B端用户,累计3000个,日活不到1千
  • C端用户,累计50万,日活不到2万
  • 平台交易量:B端日均不到1000单,C端,日均不到3000单
  • 员工:不超过300人

出现的问题:

  • 服务的拆分,按照模块还算独立而且合理(哈哈哈)
  • 8个后端,30个java项目,维护起来,头大,每天要开好几个idea窗口,来回切换
  • 10个数据库,(按理说应该20个数据库,因为20个服务)执行脚本,晕头转向,查询个数据来回切
  • 调试起来及其麻烦,从下单、签合同、付款、发货、物流 等要经过十几个微服务
  • 运营要做个活动,改完上线,某些服务犹如定时炸弹,总有bug
  • 团队人员身心疲惫,记不住哪些服务哪些表
  • 运维人员,淦他大爷的,累死老子了

高潮:

  • 某订单服务开发人员,查询订单频繁被别人调用,直接服务降级,保护自己,不然别人开发就搞死自己,就是自己的bug了,再狠点,调用超过多少次,直接return
  • 老板一脸懵逼,投入那么多人,还每天出bug,进度还慢,一问就是人手不够,再问就是技术架构很屌,问非所答
  • 业务口问技术,技术反馈这实现不了,那实现不了,因为在不同的服务里
  • 20个技术,加上社保公积金、房租水电等,一年至少300万到400万,这么复杂的架构,测试至少6个,再加上产品,算下来一年需要550万到650万

最终:

  • 老板两三年投入了两千万左右被技术玩死了
  • 技术也因企业而被裁员了,新来的一个技术,这些架构简直是一坨屎,哈哈

6.2、某200万学校项目

主要做某个专科院校的智慧党建平台,200万;地点:武汉。在校生2万人,拆分业务服务10个,一套微服务架构下来总计20个;15个开发个4月干完;

  • 技术因架构问题,与产品沟通这不好做那不好做,不然开发时间不够,人手不够,在老板面前又说技术很先进,最终舍弃了很多功能
  • 开发人员天天加班赶功能,调试累,心累,还加班
  • 交付学校的时候,学校说不好用,要改,技术与学校方吵了一架,说架构是这样的,无法实现你的想法,于是离职了
  • 最终,老板和团队成员猝....

6.3、某设计院项目

主要为某个南方一线城市设计院做一个内部项目管理系统;预算200万;微服务10个(8个库),10个java,中途也调来了一些其他项目人,5个月干完;最终加班少,也有项目奖金,原因是:之前给某北方一线城市做过一个类似的项目,也是微服务架构的,只不过这次拆分了更少的服务,更少的数据库,拆分的更清晰;

6.4、问题分析

以上是所接触到的真实的案例,出现问题的原因是"拆分的不合理",导致一个完整的流程无论从开发、调试、测试 都很麻烦,也很容易出现bug,最终导致开发人员压力很大,然后会认为微服务架构就是个噩梦,每天来回切换项目等等一系列的抱怨。但是微服务这么先进的技术难道不好吗 ?

七、总结与建议

7.1、业内大佬建议

前Ebay架构师-杨波

"企业一开始不推荐直接使用微服务,因为微服务需要前期基础设施的投资,复杂性很高,如果对问题领域并不是很理解,一开始用微服务,你很难去划分服务的边界,你的生产力反而会比较低,而且你花了很大精力进行开发,你的产品并没有被市场验证过,有可能会失败,所以这个选项风险会比较高。所以推荐的是单块优先,先从单块运用做起,这样成本低,团队成员也比较少,无须太多研发投入,就可以交付一些基本的功能给客户使用。随着应用越来越成功,客户增加,你的系统复杂度会越来越高,就会出现单块应用和团队规模之间的矛盾,生产力会随着业务复杂度逐渐降低。所以在一些初创型公司,你更多看到的是单块应用,只有一些中大型的公司会看到微服务架构。"

"交叉点表明,业务已经到达了一定的复杂性,单块应用已经无法满足业务增长的需要,研发效率开始下降了,而微服务可以提升研发和交付的效率。这个点需要架构师去综合,权衡。个人经验,一般团队需要达到百人规模,才去考虑微服务。""

胡忠想(微博微服务技术专家)

"一般情况下,这个时候就需要大规模地扩张开发人员,以支撑多个功能的开发。如果这个时候继续采用单体应用架构,多个功能模块混杂在一起开发、测试和部署的话,就会导致不同功能之间相互影响,一次打包部署需要所有的功能都测试 OK 才能上线。

不仅如此,多个功能模块混部在一起,对线上服务的稳定性也是个巨大的挑战。比如 A 开发的一个功能由于代码编写考虑不够全面,上线后产生了内存泄漏,运行一段时间后进程异常退出,那么部署在这个服务池中的所有功能都不可访问。

根据实际项目经验,一旦单体应用同时进行开发的人员超过 10 人,就会遇到上面的问题,这个时候就该考虑进行服务化拆分了。"

Uber 支付体验平台的工程经理 Gergely Oros

"Uber 最早通过构建微服务来完成很小的需求或功能,以至于出现了很多由一个人构建维护的微服务。这些微服务的存在带来了新的复杂性和挑战,例如监控、测试、持续集成 / 持续交付(CI/CD)、服务级别协议(SLA)、跨所有微服务的库版本(安全和时区问题)等等。

Uber 放弃了微服务,转而使用宏服务,不再只是完成一件事,而是使其服务于一项业务功能,由 5-10 个工程师负责维护。"

GitHub CTO Jason Warner

"任何构建过大型分布式系统的人都知道他们并不真的那样工作,但还必须适应它。""公司所处的阶段很重要。如果是一家 5-50 人的公司,只需坚持使用单体。" "Warner 鼓励企业根据自己的情况来选择,而不是盲目跟随大厂的做法,他给出的建议是:

1)尽可能地延长单体应用的使用时间。

2)服务从基础设施开始,而非应用程序。

3)如果要打破单体架构,打破大型应用程序,而不是小型服务。

4)认为每个新应用程序是贵公司的虚拟墙。

5)尽可能选择库而不是微服务。

7.2、探寻架构本质

架构的本质问题就是拆分业务太难 ,无论你是 单体架构、多模块(SOA)架构、微服务架构 都需要
那么试问,有多少的技术人员对这个行业熟悉,比如之前你在京东是干电商的,但当前的项目为钢铁电商,这是两个完全不同的电商。
引自《微服务设计》中的一句话:

"你越不了解一个领域,为服务找到合适的界限上下文就越难,服务的界限划分错误,可能会导致不得不频繁地更改服务间的协作,而这种更改成本更高"

再引自 GitHub CTO Warner 的一句话:

当涉及几十个微服务或更大规模时,企业遇到通常并非技术问题,而是组织上的挑战。

最终关于 本质问题的看法:

只要你没有行业项目经验,所有的拆分,几乎都是凭感觉、凭其他行业经验的拆分,这极有可能拆分错误,那么就等价于极有可能会让自己的团队陷入架构泥潭,不如一步一步来,从单体、多模块架构、再到微服务

7.3、建议

如果满足如下两点,可以直接上微服务。

  • 对这个行业有经验、对行业未来有预判,且能将领域划分清楚;(有行业经验)
  • 有财力和人力,基础设施完善;(有人有钱)

若不满足,则建议 不要盲目拆分给团队造成很大的微服务压力,先单体,以满足业务为前提,把代码写的漂亮一些,等熟悉业务了解行业后,找准业务领域,再去拆成微服务。

相关推荐
AI人工智能+电脑小能手10 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
红尘散仙10 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
来杯@Java11 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记11 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥11 小时前
匿名函数 lambda + 高阶函数
java·python·算法
_codemonster12 小时前
30分钟快速搭建 Spring Cloud Alibaba 微服务实战(一)
微服务·架构·毕业设计·课程设计
会编程的土豆12 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木12 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
Cosolar12 小时前
从零写一个 Attention Is All You Need
人工智能·面试·架构
adrninistrat0r12 小时前
Java调用链MCP分析工具
java·python·ai编程