论软件系统架构风格

本贴最后更新于 416 天前,其中的信息可能已经东海扬尘

摘要

2021 年 9 月,我参加了我们公司一款新款多人在线网络游戏服务端的开发。该项目需要支持游戏业务逻辑的高效迭代开发,对于架构的修改性有要求,并具备高低负载时的服务可伸缩能力。我在该项目中担任技术负责人的职位,主要负责系统架构的开发和组件的选型。项目历时 7 个月,在 2022 年 4 月部署上线,并长期维护。本文结合作者自身实践,以该游戏项目为例,对软件系统架构风格进行具体论述。项目内的系统架构采用了多种软件系统架构风格。有属于独立构件架构风格的事件驱动架构风格,虚拟机架构风格的基于规则的架构风格,以及分层架构风格等。使用这些架构风格,使系统的扩展性、可修改下、可伸缩性都得到了明显的保证。实践证明,使用正确的软件系统架构风格,可以有效的帮助项目的开发维护,并提升关键质量属性要求。

正文

随着游戏行业不断发展,游戏业务种类不断的推进,需要开发更多类型的游戏项目。公司内游戏项目开发原有的都是小服游戏为主,一个服只需要容纳几百人在线就够了,但是为着新类型的游戏模式,比如全球通服的游戏越来越流行,我们需要有新的服务端架构来支持几万人甚至百万人同时在线。原有的架构只是单服架构,不具备水平伸缩能力,单服能承受的能力在 4 核 16G 的机器下,最多只能承受 2000 人的同时在线,并且因为单服架构代码模块间代码的耦合度很高,所以每一次对架构代码的调整,都会影响客户端配合修改,导致在修改成本很高。因此我们需要开发新的服务端架构,来应付的业务拓展需求,而这个新架构必须要满足高扩展性,高伸缩性,高可修改性等质量属性。

2021 年 9 月,我们公司准备开发一款新类型的通服大型在线网络策略游戏,我在该项目中担任服务端技术负责人的职位,我主要负责新软件系统架构的开发、组件的选型和后期的架构维护。在架构设计之初,我们意识到选择正确的系统架构风格,可以帮助我们实现业务和质量属性需求,因此,选择合适的系统架构风格至关重要。

系统架构风格主要有虚拟机架构风格、数据流架构风格、仓库架构风格、分层架构风格和独立构件架构风格等。虚拟机架构风格主要包含解释器架构风格和基于规则的架构风格,在复杂的环境里可以做到面对不同的环境提供对应的抽象接口,有非常好的扩展性和可修改性,但是复杂度高。数据流架构风格主要包含批处理架构风格和管道过滤器架构风格等,该类架构风格的松耦合,良好的可维护性,可扩展性好,良好的隐蔽性,但是交互性不好,复杂度较高,适合通信交互等场景。仓库架构风格主要包含数据库架构风格、黑板架构风格和超文本架构风格等,该类风格是围绕着共享数据进行操作。调用/返回风格主要包含分层架构风格、面向对象架构风格、主程序/子程序调用风格等,该类架构良好的重用性、可维护性好、可扩展性好,多层协助工作并且透明。独立构件架构风格主要包含隐式调用架构风格和事件触发架构风格等,松耦合且具有良好的重用性、可修改性,构件与构件之间没有直接调用,一般通过触发器触发且异步调用另一个构件接口。

我们项目主要使用了分层架构风格、基于规则的架构风格、事件触发的架构风格、数据中心的架构风格,下面将对四个架构风格在系统中的使用进行具体论述。

我们使用了分层架构风格将架构分成了 3 个层次,有与客户端直接交互的网关表现层,内部业务提供者们的业务逻辑层,以及存储持久化数据和缓存数据的数据存储层。网关作为表现层,主要负责与客户端直接的交互,隐藏后面所有服务的接口,加强了可修改性,一定程度的加强了可扩展性和安全性。业务逻辑层有所有的业务逻辑服务,因为有高负载的压力,它们可以根据需求做垂直拆分或者水平拆分,因为有表现层,对于客户端来说这种内部架构修改是透明的。存储层有缓存存储的 redis 和持久化存储的 mysql,因为游戏服务的性能质量属性要求高,所以对于高度频繁读取的数据我们存入了 redis 做缓存,而持久化数据因为数量过大,有性能要求,因此我们做了分库,业务逻辑层通过应用代码实现选择对应的数据库进行存储。分层架构风格使得整个开发逻辑更加清晰,不同层的协助工作透明,可维护性好。

为了加强整体系统的弹性伸缩,可用性,可扩展性,我们设计一个服务注册中心的组件,即注册中心组件,根据这个需求我们用上了数据库架构风格。拥有了注册表组件后,当服务提供者在服务启动时可以发送服务给注册中心时,服务消费者可以及时知道,根据这个需求我们采用了事件触发架构风格。我们的游戏项目的服务大部分的交互都是要求实时延迟低的服务,所以我们在业务开发上本身就会使用 redis 这个 nosql 数据库,所以为了节省业务开发人员的学习成本,在此使用 redis 做轻量级的服务注册表,对于游戏项目来说,redis 做注册表的承载能力,足够应付大多数的场景。在设计使用过程中,服务提供者会启动一个定时任务,每 10 秒都会将自己的服务描述以及自己的当前的状态描述写入到 redis,并且根据 key 值设置 20 秒的过期时间,若是服务异常断开,redis 也会自动删除服务的信息,而服务若是正常关闭,在关闭之前会自己发送请求到 redis 删除自己的服务信息。redis 内集成订阅服务的功能,服务消费者们需要先订阅服务类型的通道,当服务提供者启动服务时,会将自己的服务描述和自己的状态发送到 redis 的订阅通道,这个消息就作为事件,所有订阅者们都会自动接受到这个消息事件,而对这个事件进行实时的处理。自主设计的这个服务注册/发现服务,降低了服务提供者和消费者之间的耦合度,极大的增强了系统的扩展性,服务的弹性伸缩有了基础性的建设。

另外我们要设计一个网关服务,隐藏内部的服务接口,使得移动客户端不可以直接连内部服务,通过网关服务来访问内部服务。为了实现这个业务需求,我们使用了基于规则的架构风格。当客户端请求的请求消息传到网关服务时,网关内部拆解消息内容,根据算法得出需要的服务名称,根据服务类型获取这一整个服务提供组,再根据内存中存储的服务提供者的当前负载情况,用加权百分比的算法,得到对应的服务提供者,最后将整个客户端的请求发送到该服务提供服务器执行。整个过程需要有静态的规则算法得出消息内容内要请求的服务,通过本地内存,得出对应服务组,通过本地内存存储各个类型服务组的动态负载状态,将服务组的动态负载状态当作参数以加权百分比的算法得出最后的服务提供者。因为服务提供者当时估计同时部署的话至少有几十个,并且因为要根据服务提供者的事实负载状态来选择,普通的方法实现非常困难,基于规则的架构风格解决这种高复杂度下的问题,并且使后面的服务具备了扩展性。

架构搭建工作花费 2 个月,整个项目共耗时了 7 个月,2022 年 4 月测试验收完成,成功部署上线,目前还在长期维护,且该受到了公司高层领导和运维等多方一致赞赏。项目在大量负载时(游戏开服,活动高峰期),配合云服务的弹性伸缩服务,可以将服务提供者动态增加,当降低负载时(凌晨),会自动回收多余的机器,在这个过程里,运维只需要打包组件到容器中,结合 Paas 就可以托管运营。也因为服务的拆分,线上在一台服务提供者出现设备故障时,不影响其他服务的运行,展现了系统一定的可靠性,但是因为系统中还是有一些单点服务,我们后期将单点服务改成集群服务,这时服务注册中心和网关的作用体现的非常明显,服务注册中心可以对服务的单点和集群部署可以完全的兼容,而在我们修改内部服务结构时,只需要简单的在网关上做简单的修改,服务消费者对此毫无感知,内部服务可修改性良好。

实践证明,选择正确的架构风格,提升实现质量属性要求需求的关键。在架构设计之初,选型架构风格要更加重视。

题目要求

系统架构风格(System Architecture Style)是描述某一特定应用领域中系统组织方式的惯用模式。架构风格定义了一个词汇表和一组约束,词汇表中包含一些构件和连接件类型,而这组约束指出系统是如何将这些构件和连接件组合起来的。软件系统架构风格反映了领域中众多软件系统所共有的结构和语义特性,并指导如何将各个模块和子系统有效地组织成一个完整的系统。软件系统架构风格的共有部分可以使得不同系统共享同一个实现代码,系统能够按照常用的、规范化的方式来组织,便于不同设计者很容易地理解系统架构。

请以“软件系统架构风格”论题,依次从以下三个方面进行论述:

1.概要叙述你参与分析和开发的软件系统开发项目以及你所担任的主要工作。
2.分析软件系统开发中常用的软件系统架构风格有哪些?详细阐述每种风格的具体含义。
3.详细说明在你所参与的软件系统开发项目中,采用了哪种软件系统架构风格,具体实施效果如何。

  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...