跳至主要內容

简介

大约 15 分钟

简介

atom是一个以java+react联动的后台系统开发脚手架,以单体巨石架构出发,内置嵌入式中间件,致力于java的产品化软件开发。

适合场景

atom适合的业务为后端业务系统、为解决某种纵向垂直场景的中间件产品。

  • 不适合cms类似的内容系统
  • 不适合oa办公等具备复杂用户层级树、复杂权限模型的系统
  • 不适合要求海量并发的分布式场景
  • 不适合频繁业务变化的大型业务团队

技术选型考量

首先需要说明下,当代软件开发分布式和微服务是主流。然而我们认为微服务仅仅适合在国内那么几家头部互联网公司,对于绝大部分百人以下的中小开发团队来说, 微服务一定是错误的选择。我们在思考软件架构的时候,一定要考虑真实的业务体量、实际的业务复杂度,而不用为了未来大概率不会发生的海量业务规模提前谋划。

就我个人经历而言,在我刚刚工作的前五年,遇到很多次创建一个系统,老板都会说这个系统未来会有多少业务规模,要提前考虑系统架构设计。然而实际上大多数情况系统连上线机会都没有, 就算上线了业务规模也远远没有老板鼓吹的那么高,在被骗了很多次之后痛定思痛。我认识到老板在对未来的美好期待就是泡沫,以及大家都在喊高并发微服务,老板要是不喊几句就没法写ppt, 无法拉到项目,骗不到大老板或者投资人,拉不到项目我们也没有了工作。这是复杂的社会组织结构带来的信息熵增问题,是投资人太久没有接触技术本身,而被周围的信息围城限制带来的认知偏差问题。

从另一个角度,我发现我所使用的大多数被市场接收,被大家熟悉的B端软件工具,均是单体为主。如mysql、confluence、wiki、gitlab,而当一个组织发展到极具规模以后, 会有技术团队重新考量在单体结构上如何扩展到更大规模。比如mysql分片和集群、gitlab重构,不过此时单体性能提升对于整个组织来说,已经是非常小的成本比重了(解释来说, 具备万人规模的研发组织,重构gitlab实现集群版,对于这个万人公司来说,根本不算成本开销。但是对于一个商业模型还没有确定的小公司,一上来就说要搞一个集群版gitlab,那就是脑子有病)。

我们以做软件产品角度出发,考虑软件本身发生应该有的生命变化规律,那么atom的技术选型路径思想应该会比较适合你。同样如果你是为了满足老板写ppt的目的,那么atom的各种行为、代码范式、 方案决策绝对是和ppt项目的目的背道而驰,此时本项目不会适合你。

单体架构

我奉行的理念为,在计算机性能完全过剩的当代,几乎没有什么系统是单台服务器撑不住的。如果真的有,你的产品将会是一个很大的规模的组织团队才能维护的。这个时候技术和你的业务相比一定没有那么重要。 更多的场景是部署一个系统,难度在系统本身的业务流程构建,其运算性能在单体机器完全扛得住。就算扛不住,单机增加配置也比分布式扩容来得简单、便宜。毕竟现在128核、2T内存的服务器也不是不存在。

  • 单体情况下,不需要考虑分布式数据存储,可以随意使用各种文件数据库,缓存性能远高redis。文件一般落地在本地,不需要对象存储成本
  • 单体情况下,加锁和事务是非常容易的,很多业务流程就完全不需要考虑多台节点如何保证事务,不会多节点竞争
  • 单体情况下,数据可以设计为有状态化,绝大部分业务场景,其数据结构都会非常简单。相对应的分布式情况下,要么业务流需要无状态设计,要么各种组装redis数据结构,业务流被搞得非常复杂。
  • 单体情况下,不存在多节点通信成本,很多业务系统多节点通信成本都已经远高于业务本身流程成本。
  • 单体情况下,问题排查非常简单,再也不需要搞一个elk搜索日志,搞得又慢又不好看。查日志还得学es语法,但是好像很多人也没有学明白es的语法(吐槽下,要学的东西太多了,没多少能精通的)。
  • 单体情况下,一样可保证稳定性,稳定的来源就是少发布。所以如果你的系统是一个面向行业稳定10年业务需求的系统,那么没有发布就没有宕机。当然,如果你的系统是老板朝令夕改的、每天都要发布的,那么老老实实用微服务吧

逆中台化

对于技术人来说,中台的确是一个好东西,中台能力让技术人裹挟业务,技术人具备了极高的话语权和公司地位。从技术的角度对业务进行顶层抽象,让中间件适配千万业务场景,这也让我们满足了系统架构设计的瘾。 我们怡然自得的欣赏我们的作品,感叹我们的技术水平如此牛逼,我们深陷这种外界的恭维无法自拔。

然而在业务团队走一走你会发现,哪些被中台裹挟的业务小开发,就是个if-else工程师、CRUD工程师,他们的业务团队使用了集团的各种中台平台串联,业务本身使用中台产品搭积木的方式构建的, 所以他们没有自己的系统,他们所有需求必须求着中台团队排期、他们排查一个问题必须串联很多中台系统、他们的实际工作就是每天改中台给他的配置、他们无法接触到中台系统的代码导致没有技术成长、 他们想做一些事情结果被告知和中台系统的设计理念违背所以无能为力 、他们使用大量中台模块堆叠导致数据散布在各种地方,数据到处都是、权限到处都是,所以又要使用中台的存储中心、配置中心、权限中心、监控中心、日志中心, ,无限的各种X中心。当然这些中心都是收费的,这种x中心的费用远高于他这个团队应该有的成本,大家纳闷为啥中台均摊了大量的同质化成本之后为啥业务团队还这么贵。

凡事有度、中台理应服务于业务,作为服务者不应该有权力裹挟业务,我们的业务系统应该只是根据自己需要调用中台能力,而不可以在中台给我们提供上的平台搞配置来驱动我们的业务。 所以中间件应该只是服务者,而不是系统的主人。这个思想也被深深刻在atom系统设计理念当中。

atom内置了大公司常见的一些中台功能,不过这些中台功能都是嵌入式的,无外部依赖的。atom中台能力使用10%的代码量解决90%的需求场景,剩余10%的场景期待用户自己修改代码按需适配。 对比中台思维,则是为了应对各行业扩展,使用了90%的代码量,开发剩余的10%的能力。导致中台系统非常复杂,但是中台90%的功能用户用不上。

  • 用户体系:基础的多账户系统,但是只支持管理员和普通用户两种角色
  • 权限体系:简单的,可以前端配置的权限管理模块
  • 配置中心:可以在前端页面实时配置的模块,对标大公司的配置中心
  • 监控:支持绝大部监控指标功能,内嵌不需要外部服务,无任何外部依赖
  • 告警(todo):一种内置的告警模型,告警事件触发、外部通知webhook、事件消息消重、从监控产生告警事件
  • 分布式广播:简单的分布式协调服务,用以多节点状态同步(只支持无状态的,简单的分布式管理。并且永远不会把这里做的复杂)
  • 数据库实体配置映射:提供一种将数据库的配置项映射为内存对象的功能,达到数据变更多节点实时通知同步
  • 版本号和升级:作为可以外部发布的产品,atom支持在不同版本上定制升级代码
  • 脚手架:文档、前端、doc,启动脚本、构建脚本、docker、测试环境。基础的错误拦截、接口监控、登录拦截、数据结构定义等

用户为先

这是atom的另一个理念,其意义是表达系统使用的扩展性和用户使用难度的一个均衡思考。同样作为技术架构师,我们关注性能、扩展能力、分布式能力等等,但是对于用户使用难度本身的思考并不多。 这本身没有问题,大多数情况下技术底层到用户还非常远,技术也是一个专业的工种,所以本来就会需要专业的同行人来学习和消化。

当技术发展到一定程度,可能会想着扩大技术影响范围,比如技术商业化、技术开源。这个时候就需要考虑广大人民群众的上手难度了。

我想到我公司曾经的一个被公司广泛使用的IM软件,在公司内部的使用体验超过了钉钉、飞书。后来有一天公司决定将它开源商业化,因为我觉得他做的挺好的,就想去研究研究他的开源软件。也期待能加入开源, 但是对照开源文档,我花了好几天时间硬是不知道如何把这套系统部署起来,不考虑文档完善程度,单从软件架构来说,就复杂得不能再复杂。很多模块和组件相互通信,很多端口和配置需要关心。最后是我放弃了研究,这个项目也在开源一段时间消失历史中。

早起的我们也是面临这种苦恼,熟悉我们团队的同学可能会知道我们早起开发了一个开源项目echo-当前已删除open in new window,这个项目是我们的majoraopen in new window的前身, 在实现echo的时候,我也是从技术角度出发,为了考虑系统的扩展能力,覆盖更多的功能场景。我将echo内部组件拆分为5个子服务(上游、下游、连接器、配置中心、客户端),每个服务都是单独服务器, 我们当时喊的口号是这个项目可以对软件网络进行无限想象的扩展。然而实际上,这个系统虽然是开源了有同学来star,却没有同学能真正的搭建起来这套软件。同时我们的本质工作就是做代理集群搭建。 同样的,不考虑服务器多节点成本,单纯说多服务器的业务流跳转问题,中间都有好多bug。从echo到majora的演变过程,我发现很多在echo的分布式环境下很难解决的状态问题,在majora就是一个内存引用就可以搞定了。

到现在我们的多个软件成熟以后,我认为用户为先需要是成熟软件必修课,所有的扩展点必须首要考虑是否会带来用户心智负担,绕过或者减轻对用户的理解压力。这包括

  • 一键部署:产品需要考虑软件bootstrap过程是否简单
    • 软件部署少配置:约定大于配置思想,所有配置考虑是否默认值满足需求,以及考虑最终配置可以根据已有配置联动计算而来
    • 少端口:尽量多模块单端口,不要告诉用户我有多少端口,什么功能需要配置什么端口
    • 少依赖:除开mysql,其他所有中间件尽量不用就不用。比如redis、mongo、nacos之类的。因为多一个依赖就多一个服务,多一个节点。会增加部署难度,以及增加运维风险
    • docker和云原生不是银弹,虽然说服务编排可以进化软件部署流程。一旦发生了问题排查需求,用户更加难以理解内部机制
  • 高内聚低耦合
    • 不要为了所谓的扩展,胡乱开放扩展点。所有外放API一定要少且简单
    • 不要为了所谓的稳定,抽离独立的服务器。
    • 考虑不常用功能的内部隐藏:如果必须开放额外逻辑开关,需要考虑将此功能隐藏在正常功能下面,保证正常用户几乎不会触达到他。
  • 统一的代码范式:这也是atom开源的原因,目前我们所有产品均使用相同的骨架。

墒增对抗

熵增指的是,系统随着时间的推移,会出现各种异常问题,这些问题会阻碍系统发展。

  • 随着业务发展,代码跟随发展,系统和业务的贴合度会逐步降低
    • 存在废弃/降频业务,这些业务代码在生产运行,不被删除也不被使用。长久之后变成无人能懂的逻辑
    • 存在新业务加入,业务上线前不确定业务形态,导致架构不合理。但上线业务不敢修改,反而增加越来越多的逻辑分支。导致代码不易阅读,代码结构不稳定,bug高发
    • 系统使用了过期的技术,业界早已废弃,但系统不变修改。逐渐变成大家都不懂的技术无人维护
  • 软件系统为公司资产,然而公司领导多半不是技术,或者精力不在技术本身。
    • 有外行领导提出不合理技术路径,导致代码结构出现破坏
    • 有技术不强的同事开发了不合理代码
    • 一般情况,领导只在乎业务价值,不会在乎系统发展。所以不可接受无业务收益的系统重构(目前中国最多允许借着业务需求搭车上线的部分重构)
    • 系统owner经常更换,没有人最终是为系统负责,并且伴随业务系统全部生命周期。中国很多大公司的开源项目都是KPI项目,作者晋升完成即离职
  • 没有绝对完美的架构师:任何一个真实的系统,在早期规划时都不能绝对的设计合理。所以没有发生重构的系统,就是屎山了

在业务公司中开发的代码,其最终归宿都是代码屎山,这是多人开发、多业务变动、无技术主人导致代码墒增问题。一份屎山代码无法让程序员实现改变世界的梦想,也无法网研发同学 得到价值感。这可能是国内研发35岁被裁员的原因之一吧。

我们考虑对抗墒增,始终保持代码质量和架构良好,期待我们写得代码可以存活几十年、几百年,这是我作为一个工程师的长期远景。毫无疑问墒增对抗需要我们自己来完成, 公司领导不会给我们资源进行代码质量保证、实现代码重构、进行长达几十年的技术规划。为了实现这个目标,我自身保证对系统全部生命周期负责。

  • 负责人规模收敛:按个人能力,系统负责人收敛到2-3人,避免多人协同开发带来多风格问题。且存在绝对的一个主要领导人。对系统具有绝对决策
  • 责任终身制:因为个人兴趣而创建了软件系统,并以个人身份运作,不把他交给公司或者组织。避免在公司运作时,被要求以业务为先破坏系统设计
  • 技术为先:一方面保持业务需求支撑,同时具有魄力进行代码重构和升级。
上次编辑于:
贡献者: iinti_cn