1.5、谈谈架构那些事儿

11/11/2022

#

本篇文章比较长,主讲架构,因为我们认为架构不是个技术问题,他牵扯面很多,比较复杂,所以会长;
本文会结合我们实验室这十年的项目经验,以及开源这三年的百余家企业经验,还有身边一二线大厂、中型企业、小企业、国央企、政府科研院所等相关技术朋友的项目经验,还有“商业”、“成本”、“人员”、“团队”等其他方面的因素,来讲述架构;
我们希望,希望我们能以最普通、最简单的文字讲清楚“架构”,也希望无论你是初出茅庐的青涩少年、还是炉火纯青技术大佬,也都能看得懂。 若直接想看结论总结建议

# 一、背景与问题

为什么写这篇文章,是发现我们开源这几年来,很多人问 “1024创新实验室” 如下几个问题:

  • “是否有微服务版本?”
  • “为什么SmartAdmin不用微服务?”
  • “你们是不是没用过微服务?”

先回答下问题:我们有微服务版本smart-cloud,但未开源,精力不够;我们很多中大型项目用过微服务;


故事: 这几年使用SmartAdmin的企业已经超过了百余家,被问过很多关于架构、微服务等相关的问题,甚至身边的企业,朋友还出现过盲目上微服务,为了微服务而微服务、还有一个项目出现过 两个开发维护一个大型微服务项目最后把老板逼着跑路的故事等等,发生过很多有意思的故事。
经验: 我们实验室本身这些年做过很多项目, 其中有大型产业电商项目、供应链项目、大型在线教育项目、大型企业ERP项目、CRM项目、大型国企项目、三线城市公交项目、大型物联网项目、中型仓储、物流项目、中型互联网体育项目、科研院所项目、部队军工项目、银行项目、学校智慧校园等等各行各业都接触过。 有些项目用了微服务架构,有些项目是多模块多体架构,有些是单体项目等等,不同的业务用了不同的架构。

# 二、关于架构的认知

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

  • 技术能力:无论什么架构,在这种架构上的技术你是否精通?是否有系统且全面的架构解决技术能力?我们实验室对于架构技术的理解是,一定要系统且完整、全面的把这个技术从头到尾的学习一遍,且从外到内,再从内到外理解深刻后,并从小到大在真实的项目中使用过,才是真正的掌握某个技术。
  • 团队组织:首先团队每个人要对这种架构熟悉,且团队必须有个拥有此架构落地经验的架构师,围绕架构师周边还需要有高级开发负责核心模块,与此同时还需要有一些负责业务开发中后端。
  • 商业价值:无论哪种架构,只要脱离业务和商业,都属于空谈架构,但结合业务需求来看,不合理的架构会给商业带来风险。比如你利用架构支撑那些现在不需要的业务需求,导致许多努力、人力、财力白白浪费,这叫做架构努力错位。比如用一个单体架构开发一套大型电商平台,异或使用微服务架构开发了一个简单的后台管理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 的一句话:

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

我们《1024创新实验室》最终关于 本质问题的看法:
只要你没有行业项目经验,所有的拆分,几乎都是凭感觉、凭其他行业经验的拆分,这极有可能拆分错误,那么就等价于极有可能会让自己的团队陷入架构泥潭,不如一步一步来,从单体、多模块架构、再到微服务

# 7.3、我们建议

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

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

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

最后,你能找准你所在业务中的领域模型吗? 或者说有没有其他不一样的观点呢?来联系我们吧,聊聊你的观点!

# 联系我们

1024创新实验室-主任:卓大 (opens new window),混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室(河南·洛阳) (opens new window) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目。

加 主任 “卓大” 微信
拉你入群,一起学习
关注 “小镇程序员”
分享代码与生活、技术与赚钱
请 “1024创新实验室” 喝咖啡
支持我们的开源与分享

告白气球 (钢琴版)
JESSE T