如何进行系统架构设计及其常用手段总结

原创 码农  2020-01-26 20:14:37  阅读 305 次 评论 0 条

1. 架构定义


软件架构(Software Architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。其实我们把架构当成一个技能、工种、职位、岗位,核心还是为了应对软件设计、构建中的复杂度,降低成本、提升效率。
对我们常见系统做一下分类。如果按照行业分,篇幅不够、积累也少,无法全面分类。这里尝试按照时间线分类,后面阅读会更加顺畅一些。

事中业务

常见的业务系统。如:电商、交易系统等等大多属于这类。实际业务中,对业务反馈需要越实时,实现难度相对越高,比如:共享单车APP、股票交易等,需要实时的提示、预警、交互。除了传统型业务型架构外,对大数据流计算架构要求逐步提高。

事后业务
事后肯定有数据沉淀,有数据肯定可以对未来决策做指导。自然而然查询统计、报表决策、数据挖掘、事后总结等数据应用类系统。

事前业务
事前基本为业务预测、分类、推荐、决策辅助灯业务。随着机器学习、深度学习的火热,这部分应用越来越广泛。例如:量化投资、广告点击率预测、短视频推荐、电商推荐等。

趋势
人类欲望膨胀,业务需求无止境,从而推进IT技术、架构发展。人工智能、流计算、大数据发展,离线/在线、事后/事前/事中、人工决策/机器预测 等界限已经很模糊。也是我个人认为的IT技术方向, 大数据、流计算、推荐系统、广告系统。(机器学习、深度学习等业务系统)。
如何进行系统架构设计及其常用手段总结 如何进行系统架构设计及其常用手段总结 架构

2. 架构目的有哪些?


架构的目的其实每个架构师、程序员都很清楚,或日常工作中自然而然都会面对。但是我们很容易迷失自我。如果你是个架构师,现在闭上眼睛,回想三十秒,想想当天工作内容的解决了什么问题?达成什么目的?晚上加餐学习内容的目的是什么?是在熬时间等工资?是在踢皮球推卸责任?还是为了少干点活?还是学习新的知识为了提升个人价值,升职跳槽?
面试时,面试官通常会从项目经验中考察以下几点:业务复杂引起的复杂度数据量引起的复杂度用户数引起的复杂度。比如,做过什么项目,是否了解电商交易系统?你们用户数有多少,峰值 QPS 多少?你们一天产生多少数据?如何存储处理等?
面临架构设计 Case 时候,无论是架构升级、还是构建架构地基,主要目的肯定只有一到两个。比如:用户规模扩大,原有架构在并发、性能上无法容忍;又如:业务快速发展,7*24 小时运转下,升级迭代新功能太麻烦, 是否可以考虑微服务架构等。
如果从客观来说,架构需求肯定包含在以下需求之列:高并发、高性能、高可用、安全性、规模扩展性、规模成本。书籍、网上都是这样说的,因为这样说都没错。
小节:基本很多书上、文章都有讲解,下面来点很少地方能看到的知识点!就算我们设计的架构,都能满足需求,达到目的,算合格的架构吗?答案是不算!为啥,回到前面 OGSM, 能够明确量测方式、可量化任务的目的、目标,其实都不是难事。我们做很多事情时,尤其是探索性架构师,可量测性其实是很模糊的。 举个例子:当初 MapReduce 框架刚出来时,谁有说它慢呢?是否直到 Spark 在更短时间完成相同任务,才发现 MapReduce 框架如此之慢!
所以是否有个结论,可量测方法、量化指标都是在实践后的结果。当然,不是说目标的评测不重要,对于初学者肯定是重要的, 但是用这些评价架构或评判事物,可能陷入自欺欺人的境地。


3. 如何评测这些目标?


SLA 服务等级协议(Service-Level Agreement),指的是系统服务提供者(Provider)对客户(Customer)的一个服务承诺。这是衡量一个大型分布式系统是否“健康”的常见方法。SLA 设定一些指标,来考核、衡量系统。
    1. 系统可用性:也就是常说的 4 个 9、5 个 9 指标。
    2. 准确性或错误率:可以简单理解为 错误请求数/全部请求数=错误率。
    3. 系统容量/吞吐量/预期负载:也就是常说的 QPS/TPS 等, 每秒可处理的查询数或事务数。
    4. 延迟或 RT 等:系统响应时间。
注:关于这部分概念,上网查询即可,不展开描述。
当系统架构在不停迭代的时候,有了一个明确的 SLA,我们可以知道下一个版本架构的改进目标以及优化好的系统架构是否比上一代的系统 SLA 更加优秀。当然评测系统还有很多其它指标,比如:可扩展性,随着云计算的发展,硬件层面扩展性基本不用考虑,我们通常考虑业务需求的扩展性即可, 但这个需求、业务扩展往往无法衡量,而架构师又容易过渡设计,是个考验架构师火候的指标之一。 还比如分布式系统数据一致性、持久性、数据可靠性能,这里不展开阐述。
当架构搭建基础较好的时候,这些指标其实比较容易提升。从另外一方面说,真正架构难度,不是业务架构,而是支撑核心业务稳定运行的点点滴滴,以微服务为例来看:
  • 冗余部署是提高系统可用性唯一法宝。服务的冗余部署,是为了提升系统可用性。另外使用微服务架构,有个很重要目标,就是要无感知升级系统模块。 汽车的备用轮胎也可以提升汽车可用性,但汽车爆胎后,需要换轮胎的时间,这个可用级别上不去。 而微服务,把功能拆分成小服务,可以通过技术手段,无感知的升级。
  • 服务治理都会包含服务监测、预警功能。当服务错误率达到一定阈值, 很可以报警或开启限流、服务降级、熔断等策略,把影响降低到最小。
  • 微服务架构中,通常会在在 Gateway 层,甚至 Service、Dao 层 设置限流措施。当流量大于预期时,开启防御手段。 也有一些弹性扩容的设定,当流量大于阈值时,自动扩展服务,应对突发流量,这个过程甚至不用人工参与。
  • 系统延迟或相应时间,也会在服务监测平台设置相应指标,超过阈值时,启动相关服务降级、限流、熔断等策略。
注:个人理解,其实微服务、Kubernetes 等,很大一部分功能都是为了应对 SLA 的智能化扩展。


4. 架构设计常用手段


相信大多数人都认同,与其说架构是设计出来的,不如是说抄袭或拼装而成的。所以我们需要熟悉常用的手段或成熟的框架来解决日常工作中的问题。每个架构师工作经历不同、应对过的业务系统不同、兴趣点不同,手头的弹药库也不同。我列举一些自己认为重要的知识点或框架。(前端太久没接触,只列举后端,大多以微服务为例,后续文章有机会展开探讨)

业务处理相关技术点和框架

单机:高性能、高并发手段相关

1. 单机高性能手段:可以上网查询 C10K 问题,获取相关文章。把进程、线程、池、IO 多路复用相关知识点弄清楚。

2. 分清楚 IO 密集型和 CPU 密集型场景:一般互联网应用多为 IO 密集型。但是类似:滴滴出行、股市量化投资、在线游戏之类,属于 IO 密集型和 CPU 密集型并存的场景,甚至对响应时间要求也很高。 幸好大多数 CPU 密集型应用也是多租户、区域独立性架构,容易扩展拆分。

3. 程序访问存储介质或链路快慢: 程序肯定要与存储进行消息交换。一定明白,CPU 高速存储器、内存、SSD 硬盘、机械硬盘、同交换机网络、同机房网络、同城网络、同运营商网络等。细节展开很多内容,包含缓存、CDN、多机房等,从细节编程到部署架构的知识点。

集群:高性能、高并发相关

1. 负载均衡反向代理:其实把 Nginx 了解就可以了。如果是初创小公司,基本使用云上 SLB 负载均衡(Server LoadBalancer)就可以, 如果需要自建机房,有专门运维负责这些工作,到时候补补 LVS、F5 相关技术即可。

2. 服务无状态:以微服务为例来说,服务无状态会带来太多的好处,扩展冗余部署服务会很方便。不谈微服务,就说前后端分离,鉴权这块 token 的实现,其实根本目的也是把用户状态剥离出来,实现服务的无状态化。 (提个小插曲,估计老人才了解 J2EE EJB 规范,当初居然专门设计了一个 sessionBean 有状态的服务规范)。

3. 任务(服务)拆分:可以理解为服务拆解、功能拆解。其实拆分准则很多,可以按照实际需求来权衡。比如:按照人头分、按照功能划分、按照数据库表划分、按照功能重要性划分、按照功能访问频度划分。 不过,水平按照 Gateway、逻辑层、数据层、存储层算基本规范了。

4. 常用的语言及框架:了解语言特性,如 Node 语言的快速开发、前后端语言一致带来的便利、多路复用回调的原生支持等;go 语言“goroutines”特性带来的编程便利;Java 优秀的生态及开源框架;C++性能优势等。当然技术选型,跟团队及业务成熟度很大关系。

5. 缓存:分布式缓存是提升系统性能利器。基本掌握 Redis 即可,需要知晓 Codis 和 Redis 官方集群部署方式。

6. 消息队列:消息队列也是常用提升系统性能利器,如业务逻辑异步化、削峰、解耦等。熟悉 Kafka、RocketMQ即可。

高可用手段(集群):

高可用手段核心解决思路是冗余部署,同样的服务冗余多份,会带来服务出错通知、服务自动切换、容错等一系列问题。高可用的实现更有技术含量,现在微服务框架服务治理组件,很多在高可用上做创新突破。(高性能冗余部署为了扩展节点,带来更高的处理性能)

1. 服务无状态:当某个服务故障时,自动切换到新的服务,不用产生状态丢失等问题。

2. 调用方支持超时、重试配置:由于网络抖动等原因,某个服务可能某次调用不可用,调用方需要重试重新调用。当然超时是调用方通用遇到的故障之一,也会有在其它故障发生,然后发起重试的配置。

3. 被调用方需要幂等支持:显而易见,无论是重试、还是调用方自动切换到的新的服务, 被调用方服务幂等支持的必备的。

4. 服务状态监测:所有服务都可用,那是理想情况。当某个服务发生故障时,整个体系必须知道这个服务有问题了,重试调用多少次也不会成功了。按照微服务框架来说,需要两方知道这个信息:1、服务注册组件。2、服务上游调用方。当然报警让运维技术恢复是常规。

5. 服务状态通知:按照微服务架构,服务的状态 在注册中心都会体现。但是注册中心跟服务之间一般是通过心跳来检测的,有时间延时。 另外,服务调用方会缓存注册中心数据,其中就包含服务状态。  所以说,从注册中心获取服务状态,是有延时,可能会造成很多无效的请求。  高效的服务状态机制,很难组件化框架化,  所以这块需要高性能、较实时的自研通信机制或高性能集中存储机制保证。具体可以留言讨论或后续文章探讨。

6. 调用方智能路由:除了负载均衡以外,当调用方 A1 知晓下游服务 C1 故障后,可以自动切换到 C2 等服务上。 另外,通过服务状态通知机制,最好可以告诉 A2、A3,C1 服务故障了,你们别去尝试了。

7. 服务故障恢复有,状态通知机制:这部分就比较简单了。注册中心状态变化后,调用方会慢慢更新注册中心元数据,来获取最新状态。 当时,如果有更实时的消息机制,时效性会更高。

系统可靠性(牺牲少部分可容忍体验,降低问题到最低)

8. 服务(功能)分类:不管是微服务框架也好,单体框架也好,架构师必须对功能、服务进行分类。分类维度很多,比如:重要程度、QPS 量级、是否可以降级停止等等。

9. 应用限流:对于一般规模的应用,在 Gateway 层做即可,从源头保护整个应用。对于超大应用(个人没经验),我觉得架构会更加复杂,可能 Gateway 会分为很多层或多个,甚至有业务中台,层次会更复杂。

10. 服务降级:服务是在服务分类的基础上的。比如:百度贴吧的发帖功能,信息流广告功能,紧急情况下是可以降级处理的。可以人工或自动执行。其实 限流也是一种特殊的服务降级。(服务可以是个功能、也可以是接口,就看团队内如何达成一致)

11. 接口熔断:熔断一般在接口方法级别,因为调用链路很长,容易引起调用雪崩。让某个接口方法出现问题,我们可以按照预定配置处理业务,快速返回预设结果,防止整个链路的奔溃。

12. 弹性扩容:弹性扩容是理想的智能运维,但是具体操作也做大厂才会做相关工作。例如新年红包业务,双十一电商业务,秒杀业务,明星结婚对新浪微博的影响等,这些可以预知或未知的突发流量,如果系统可以自动扩容,那将很是完美。其实很多当前 Docker + kubernetes 的使用案例,还只是方便运维工作量,对弹性扩容这块实践感觉不是很好。

存储相关:

1. 关系型数据库:传统的 MySQL 数据需要掌握。如果做互联网业务,对分库分表肯定有需求,关注 NewSQL,如 TiDB,可以避免分库分表的麻烦。

2. NoSQL 存储:Elasticsearch、MongoDB至少掌握一个。笔者对 Elasticsearch 还是比较看好,综合性 文档数据、列式存储、反向索引 都支持,社区生态也很不错。

3. 大数据数据库:强烈建议熟悉 HDFS + HBase + openTSDB。如果熟悉时序数据库 openTSDB 设计以后,对了解各个监控系统如 OpenFalcon 有很大的帮助。基本自研监控系统也难度不是特别大了。

4. 内存数据库:有些特殊应用使用内存数据会事半功倍。Redis 提供丰富的数据结构及良好特性,并且有很多插件,巧妙使用可以降低业务代码复杂度。

5. 消息队列:消息队列也有存储机制,使用得当,也可以当成存储介质使用。例如:kappa 架构、RocketMQ 事务消息支持等。

注:存储相关其实只是中间件的学习,自研或改造几率机会还是比较少。

最佳实践:

笔者强烈建议架构师研究商业化广告系统的架构,有心得也可以与我交流。广告系统涵盖知识点很多,如:高并发、高性能的广告引擎;倒排索引的广告定向召回;流计算计费系统;批处理反作弊大数据处理系统;大数据DMP用户设备画像系统;点击率预测机器学习、深度学习方向;adx + ssp + dsp 之间跨公司、跨系统间通信调用;频次控制等需要的缓存系统设计;交易相关资金方面的处理等等。


5. 提升认知


每个架构师都梦想架构世界,设计未来。可惜当你真正有能力或有义务为社会做点贡献时候,往往忘了初心或体力有限。所以年轻时候,精力充沛时候,往往经验能力有限,年轻时候过度设计都会经历,为了可扩展性、可重用、预防需求变更做这样那样的设计。前文互联网思维-迭代思维中也讲到,世事万物都是在变化的。无论我们如何封装变化、兼容变化,都有个刻度。变化始终要面对,一劳永逸是不可能的, 好的设计模式本身就是封装变化、应对变化的最佳实践。

笔者在多元视角看问题章节也提到过,学会用时间线眼光看待问题。这里很是适用,刻意练习自己多元视角思维,可能会找到事物发展的趋势或固有轨迹。如果你能够把我企业内部、业内流行架构趋势,或推动架构演进的企业内部业务发展趋势, 做架构方面取舍时,可能会有更加全面的考虑,从而设计出扩展性更好的架构

注:当然,做任何事情也是如此,顺势而为。

本文地址:https://www.itcodeit.com/post/63.html
版权声明:本文为原创文章,版权归 码农 所有,欢迎分享本文,转载请保留出处!

发表评论


表情

还没有留言,还不快点抢沙发?