什么是软件架构?IT行业内并没有一个准确的、一致认可的定义,不同的组织有不同的定义。

实践是最好的老师,讲讲最近完成的一个项目——这里不会提及任何技术方案细节。

历时1年多,从一穷二白连容器云平台都没有,到逢山开路、遇水搭桥,不断解决各种技术、非技术问题,费尽九牛二虎之力,终于完成了这个项目。这次是真·全栈,除了开发工作因为精力顾不上只接手了一小部分核心及算法设计实现外,其他角色——产品经理、架构师、项目经理、QA,甚至平台采购,都兼了一遍,从这个坑爬出来,真不容易。

一个项目做完了,尤其是自己第一个从无到有的项目,体会比较深刻,分享一些思考。

1、关于架构

公司内部历年积累下来的系统,不管是自建还是外购,只要是在非云时代构建的系统,基本都是单体架构。单体架构到底好不好,关键看好不好使,糊弄一句见仁见智肯定是不行的。我们可以从非技术和技术两方面来分析一下。

1)非技术方面

a. 组织结构

康威定律(有向烂梗转化的趋势😂),业务部门的小单元是怎么划分的,技术部门的小单元是怎么划分的,在技术小单元内部的各人分工又是怎么划分的,各种不同层次的单元是如何互动的,这些都会相互交织,并映射到技术架构上。想象一个有很多处于不同地理位置的机构,其产品形态也必将向多地联合结构的形态演化。组织里不同单元的话语权变化有时也会影响到架构的最终形态,因为不同单元的关注点不同。

b. 组织偏好

组织的整体风格是风险厌恶型、激进型,还是技术前瞻型,这一切都可以更加具体地着落到行业特性、组织自身定性、组织所处发展阶段、管理层的知识储备和行事风格上。当然组织内的偏好是可以和自身行业或更外围的整个技术大环境相抵触的,这取决于组织所处领域市场竞争的充分程度。市场竞争程度不充分,改变的压力会很小,也没有进步的参照物,就容易造成眼界的狭窄和封闭,而【山中方一日,世上已千年】会在未来带来系统性风险。

c. 监管规范

不同行业有不同的监管要求,不同类型的组织也有不同的监管要求。金融领域就是强监管的领域,有各种审计、反洗钱之类的监管规范。证监会监管证券业,银保监会监管银行和保险业。具体到对技术架构的需求上,就看组织内的相关部门是如何解读监管规范的,架构层负责对架构及业务领域的监管要求提供支持。

d. 行业特性:互联网行业要求7×24,会追求零停机时间。证券业周末停市,无法进行场内交易。

小结:技术不是真空,满足特定的需要是它诞生和存在的理由,如何更好地满足则是它演进的方向。

2)技术方面

a. 必须要可用

不可用就不存在。可用指可以在承诺的时间提供承诺的服务。整体可用整体不可用是它的两个极端,在这两者之间,还有一个辗转腾挪空间。如果想更具体一点,可以定义为对谁提供什么功能。假设我提供了10个功能,而只向A用户公开了1个功能,那么只要这个功能是可用的,在A用户看来,系统就是可用的。一般系统都会向不只一类用户提供可用承诺,比如以界面功能的形式提供给业务用户、以界面功能的形式提供给管理用户、以api接口的形式提供给其他系统。停机维护时的可用性怎么保障、外部不可抗力发生时的可用性怎么保障,这就涉及到高可用性,从物理机到虚拟机到容器,主备、冷备、热备、双活、多活、热加载、滚动发布,都是减少停机时间,增加高可用性的手段。

另一个方面是可用也存在质量的差别,同样是苹果,红富士和野苹果的口感就完全不一样(虽然我更喜欢野苹果),在不同的延迟下,可用的体验也不同,比如电信的网络有时候卡得不行,但10分钟后还是能加载出网页。

b. 必须要满足性能要求

一年中每天各个时间点的处理活动大部分都是温和的,符合历史统计情况,但某些特殊的业务时点或业务人员的特殊操作会造成处理活动在短时间内暴涨。服务实例的伸缩性、弹性就对架构有很大的影响。如果是一台大机器,运行的单实例,就加内存、加cpu、加存储;如果是基于虚拟机的多活,就加虚拟机,改nginx分发配置;如果是像现在我们用的容器云,就根据预先的设计指标自动扩缩。基于组织能提供的基础设施的不同,应对性能变化的架构设计也不同。

c. 必须要能支持扩展

外部环境不是静止的,业务也不会静止(否则一做完你就失业了),所以系统一定要能支持扩展。一个系统肯定能扩展,只是代价不一样。可以通过修改影响的范围、改动量的大小来衡量付出的代价。最极端的情况是一个大泥球,扩展它需要重写整个系统;如果模块化了,即使各个模块都是大泥球,也只需要重写某个模块。在同一个模块里,可以通过运用设计模式,来最优化当调整发生时所影响的范围和需要做的改动量。比如OOP中,通过抽象类/接口粘合具体,就可以在修改发生时尽量减少混乱和痛苦。

d. 运行维护

系统必须能很好地支持运行维护工作。IT的C位多年来被开发工作所占据,但从软件生命周期来看,开发完毕上线仅仅是千里之行的第一步,后续还有很长的精力投入周期。现代的软件开发已经转变为了不断迭代上线的过程。运行发现问题,需要修改;有新业务需求,需要修改;有业务需求调整,需要修改;基础设施发生变动,需要修改;数据库许可到期需要修改;技术栈调整,需要修改;误操作导致脏数据,需要修改;有安全漏洞,需要修改;调整监控指标,需要修改…… 如果更好地进行运行维护,减少痛苦,是一个重要方面。保障可测试性,能够提高对修改的信心,提高迭代的效率;保障可观测性,能够随时看到系统的运行状态,而不是等到出现问题收到病危通知书了才手忙脚乱处理;保障可部署性,可以提高部署效率,减少人工操作引入失误的概率。

e. 演进

系统最好是演进式的架构。软件的演进可以是架构的转变,比如从单体到微内核或者事件驱动或者微服务;可以是编程语言的演进,从c#到java,或者从java到go或者python;可以是部署方式的演进,从虚拟机部署到容器部署。微服务俨然是目前最炙手可热的新星。

f. 安全

要保障软件的安全性。开发时往往更注重业务逻辑和业务数据的正确性,以及性能,而容易忽略安全考量。以前研究网络协议时,就发现某些协议在设计上就存在固有漏洞,最近频繁爆出来云厂商因为一条ospf配置错误而导致整个网络域下线的情况也是某些协议在机制设计上就存在脆弱性。sql注入漏洞、xss漏洞、csrf、(java)反序列化漏洞。现代软件是一个高度依赖的生态,催生了供应链攻击,jar依赖的漏洞、npm依赖的漏洞。前段时间的log4j2漏洞,也着实让IT界狼狈了一把。除了漏洞,还有访问控制,谁在什么时间能如何操作什么资源,都需要进行控制,并经受审计。

ps:今天不想聊了,其他内容放下次写

分类: CODE

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注