架构第1章

2019-08-02  本文已影响0人  小螺丝钉cici

本文参考《极客时间》- 从0开始学架构

架构到底是什么?

架构和框架是什么关系?
架构的目的
复杂度来源:高性能,高可用,高扩展

来源一:高性能
软件系统中高性能带来的复杂度主要体现的两方面,
一.单台计算机内部为了高性能带来的复杂度;
二.多台计算机集群为了高性能带来的复杂度

性能优化点思路总结起来还是两步走:先单机后集群,如多线程、协程等编程模型的使用,缓存的使用,最终都是为了更快完成一次请求服务

来源二:高可用
高可用的定义:系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。

现实: 没有任何系统真的能做到“无间断”。不论是内部原因系统设计,还是外部自然灾害,都会导致间断。
在复杂的分布式系统中,每个服务都有99.99%的可能出现故障,YTX有80个应用也就是说有99.99%的80次方,也就是也就是99.2%的高可用,也就是说有0.8%的故障,那么一年有70个小时的故障。如果,阿里巴巴70个小时的故障,那就是损失惨重了。

如何做到高可用?

没有完美的高可用解决方案。而是减少或规避。规避某个问题的时候,一般会引发另一个问题,作出取舍。

***SpringCloud的hystrix的出现就是为了高可用
***高性能和高可用都通过增加更多机器达到目的,但本质上有区别的:高性能增加机器目的在于“扩展”处理性能;高可用增加机器目的在于“冗余”处理单元。

来源三:
可扩展性指系统为了应对将来需求变化而提供的一种扩展能力,当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持,无须整个系统重构或者重建。
面向对象思想、设计模式都是为了解决可扩展性的而出现的方法与技术。

设计具备良好可扩展性的系统两个基本条件:
1.正确预测变化(业务维度,对业务深入理解,对业务的变化进行预测)
2.完美封装变化(技术维度,利用扩展性好的技术,实现对变化的封装)
在实际工作场景中的(实现良好的可扩展性)解决方案 :
(1)使用分布式服务(框架)构建可复用的业务平台。
(2)使用分布式消息队列降低业务模块间的耦合性。
(1)分布式服务框架 (如Dubbo)可以将业务逻辑实现和可复用组件服务分离开,通过接口降低子系统或模块间的耦合性。新增功能时,可以通过调用可复用的组件实现自身的业务逻辑,而对现有系统没有任何影响。可复用组件升级变更的时候,可以提供多版本服务对应用实现透明升级,对现有应用不会造成影响。
(2) 分布式消息队列 基于生产者-消费者编程模式,利用分布式消息队列(如RabbitMQ)将用户请求、业务请求作为消息发布者将事件构造成消息发布到消息队列,消息的订阅者作为消费者从消息队列中获取消息进 行处理。通过这种方式将消息生产和消息处理分离开来,可以透明地增加新的消息生产者任务或者新的消息消费者任务。

其他复杂性来源:
来源四.低成本
How:一般通过“创新”达到低成本的目标。
(1)引入新技术。主要复杂度在于需要去熟悉新技术,并且将新技术与已有技术结合;一般中小型公司基本采用该方式达到目标。
(2)开创一个全新技术领域。主要复杂度在于需要去创造全新的理念和技术,并且与旧技术相比,需要有质的飞跃,复杂度更高;一般大公司拥有更多的资源、技术实力会采用该方式来达到低成本的目标。
来源五.安全
安全是一个庞大而又复杂的技术领域,一旦出问题,对业务和企业形象影响非常大。
从技术的角度来讲
(1)功能安全-“防小偷”,减少系统潜在的缺陷,阻止黑客破坏行为;
(2)架构安全—“防强盗”,保护系统不受恶意访问和攻击,保护系统的重要数据不被窃取。由于是蓄意破坏系统,因此对影响也大得多。架构设计时需要特别关注架构安全。
How:
(1)功能安全。是一个逐步完善的过程,而且往往都是在问题出现后才能有针对性的提出解决方案,与编码实现有关。
(2)架构安全。传统企业主要通过防火墙实现不同区域的访问控
制,功能强大、性能一般,但是成本更高。互联网企业更多地是依靠运营商或者云服务商强大的带宽和流量清洗的能力,较少自己来设计和实现。
来源六.规模
What:规模带来复杂度的主要原因就是“量变引起质变”,当数量超过一定的阈值后,复杂度会发生质的变化。
(1)业务功能越来越多,调用逻辑越来越复杂;
(2)数据容量、类型、关联关系越来越多。
How:规模问题需要与高性能、高可用、高扩展、高伸缩性统一考虑。常采用“分而治之,各个击破”的方法策略。
来源七.可伸缩性
当前大型互联网网站需要面对大量用户高并发访问、存储更多数据、处理更高频次的用户交互。网站系统一般通过多种分布式技术将多台服务器组成集群对外提供服务。伸缩性一般是系统可以
根据需求和成本调整自身处理能力的一种能力。伸缩性常意味着系统可以通过低成本并能够快速改变自身的处理能力以满足更多用户访问、处理更多数据而不会对用户体验造成任何影响。
伸缩性度量指标包括
(1)处理更高并发;
(2)处理更多数据;
(3)处理更高频次的用户交互。
其复杂度体现在
(1)伸——增强系统在上述三个方面的处理能力;
(2)缩——缩减系统处理能力;
(3)上述伸缩过程还必须相对低成本和快速。

架构设计三原则
合适原则:“合适优于业界领先”。
简单原则:“简单优于复杂”。
演化原则:“演化优于一步到位”。

软件架构设计的过程:

架构设计流程

架构设计第1步:识别复杂度

将主要的复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序,优先解决当前面临的最主要的复杂度问题。
“亿级用户平台”这个案例,团队就优先选择将 子系统的数量降下来,后来发现子系统数量降下来后,不但开发效率提升了,原来经常发生的小问题也基本消失了,于是团队再在这个基础上做了异地多活方案,也取得了非常好的 效果。

架构设计第2步:设计备用方案

最好是“三方案”,又叫“第三选择”,可以防止思维狭隘,目光短浅,思维盲区等决策陷阱

  1. 几种常见的架构设计误区
    (1)设计最优秀的方案。不要面向“简历”进行架构设计,而是要根据“合适”、“简单”、“演进”的架构设计原则,决策出与需求、团队、技术能力相匹配的合适方案。
    (2)只做一个方案。一个方案容易陷入思考问题片面、自我坚持的认知陷阱。

  2. 备选方案设计的注意事项
    (1)备选方案不要过于详细。备选阶段解决的是技术选型问题,而不是技术细节。例如,评审的时候针对某个定时器应该是1分钟还是30秒,争论得不可开交。
    (2)备选方案的数量以 3~5个为最佳。
    (3)备选方案的技术差异要明显。例如,采用ZooKeeper和Keepalived两种不同的技术来实现主备,差异就很大
    (4)备选方案不要只局限于已经熟悉的技术。

3.“微博”设计方案
(1)采用开源的Kafka,高性能
(2) 集群 + MySQL存储
“高可用写入”和“高性能读取”一样,可采用集群。因为消息只要写入集群中一台服务器就算成功写入,因此“高可用写入”的集群分配算法和“高性能读取”也一 样采用轮询,即正常情况下,客户端将消息依次写入不同的服务器;某台服务器异常的情况下,客户端直接将消息写入下一台正常的服务器即可。
整个系统中最复杂的是“高可用存储”和“高可用读取”,“高可用存储”要求已经写入的消息在单台服务器宕机的情况下不丢失;“高可用读取”要求已经写入的消息在单台服务器宕机的 情况下可以继续读取。架构师第一时间想到的就是可以利用MySQL的主备复制功能来达到“高可用存储“的目的,通过服务器的主备方案来达到“高可用读取”的目的。

image.png

(3)备选方案3:集群 + 自研存储系统
(4)高可用消息存储和读取可以采用mongo和redis
这么高的gps很难保证消息不丢 那么可以采用有消息确认机制和消息回溯的MQ 或者自研rpc的时候考虑消息发送失败的时候重新选择节点然后落盘

架构设计流程的第3步:评估和选择备选方案。

列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。

常见的方案质量属性点有:性能、可用性、硬件成本、项目投入、复杂度、安全性、可扩展性等。在评估这些质量属性时,需要遵循架构设计原则1“合适原则”和原则2“简单原则”, 避免贪大求全,基本上某个质量属性能够满足一定时期内业务发展就可以了。

image.png

列出表格后,一时无法判断。最终架构师选择了备选方案2
针对备选方案2的缺点,架构师解释是:
第一缺点是性能,业务目前需要的性能并不是非常高,方案2能够满足,即使后面性能需求增加,方案2的数据分组方案也能够平行扩展进行支撑(参考架构设计原 则3:演化原则)。
第二缺点是成本,一个分组就需要4台机器,支撑目前的业务需求可能需要12台服务器,但实际上备机(包括服务器和数据库)主要用作备份,可以和其他系统并 行部署在同一台机器上。
第三缺点是技术上看起来并不很优越,但我们的设计目的不是为了证明自己(参考架构设计原则1:合适原则),而是更快更好地满足业务需求。

2 RocketMQ 和 Kafka 有什么区别?
(1) 适用场景 Kafka适合日志处理;RocketMQ适合业务处理。
(2) 性能 Kafka单机写入TPS号称在百万条/秒;RocketMQ大约在10万条/秒。Kafka单机性能更高。
(3) 可靠性 RocketMQ支持异步/同步刷盘;异步/同步Replication;Kafka使用异步刷盘方式,异步Replication。RocketMQ所支持的同步方式提升了数据的可靠性。
(4) 实时性 均支持pull长轮询,RocketMQ消息实时性更好
(5) 支持的队列数 Kafka单机超过64个队列/分区,消息发送性能降低严重;RocketMQ单机支持最高5万个队列,性能稳定(这也是适合业务处理的原因之一)
3 为什么阿里会自研RocketMQ?
(1) Kafka的业务应用场景主要定位于日志传输;对于复杂业务支持不够
kafka针对海量数据,但是对数据的正确度要求不是十分严格。 而阿里巴巴中用于交易相关的事情较多,对数据的正确性要求极高,Kafka不合适,然后就自研了RocketMQ。
(2) 阿里很多业务场景对数据可靠性、数据实时性、消息队列的个数等方面的要求很高
(3)当业务成长到一定规模,采用开源方案的技术成本会变高(开源方案无法满足业务的需要;旧版本、自开发代码与新版本的兼容等)
(4) 阿里在团队、成本、资源投入等方面约束性条件几乎没有

上网看了相关对比,认为阿里选择自己开发RocketMQ更多是业务的驱动,当业务更多的需要以下功能的支持时,kafka不能满足或者ActiveMQ等其他消息中间件不能满 足,所以选择自己开发(RocketMQ设计的真的很牛)
1、数据可靠性
kafka使用异步刷盘方式,异步Replication
RocketMQ支持异步刷盘,同步刷盘,同步Replication,异步Replication
2、严格的消息顺序
Kafka支持消息顺序,但是一台Broker宕机后,就会产生消息乱序 RocketMQ支持严格的消息顺序,在顺序消息场景下,一台Broker宕机后,发送消息会失败,但是不会乱序 3、消费失败重试机制
Kafka消费失败不支持重试
RocketMQ消费失败支持定时重试,每次重试间隔时间顺延
4、定时消息
Kafka不支持定时消息
RocketMQ支持定时消息
5、分布式事务消息
Kafka不支持分布式事务消息
阿里云ONS支持分布式定时消息,未来开源版本的RocketMQ也有计划支持分布式事务消息
6、消息查询机制
Kafka不支持消息查询
RocketMQ支持根据Message Id查询消息,也支持根据消息内容查询消息(发送消息时指定一个Message Key,任意字符串,例如指定为订单Id) 7、消息回溯
Kafka理论上可以按照Ofset来回溯消息
RocketMQ支持按照时间来回溯消息,精度毫秒,例如从一天之前的某时某分某秒开始重新消费消息
.........

架构设计流程第4步:详细方案设计

详细方案设计就是将方案涉及的关键技术细节给确定下来。

详细设计方案阶段可能遇到的一种极端情况就是在详细设计阶段发现备选方案不可行,一般情况下主要的原因是备选方案设计时遗漏了某个关键技术点或者关键的质量属性。例如,我曾经参与 过一个项目,在备选方案阶段确定是可行的,但在详细方案设计阶段,发现由于细节点太多,方案非常庞大,整个项目可能要开发长达1年时间,最后只得废弃原来的备选方案,重新调整项目目标、计划和方案。
这个项目的主要失误就是在备选方案评估时忽略了开发周期这个质量属性。
幸运的是,这种情况可以通过下面方式有效地避免: 架构师不但要进行备选方案设计和选型,还需要对备选方案的关键细节有较深入的理解。例如,架构师选择了Elasticsearch作为全文搜索解决方案,前提必须是架构师自己
对Elasticsearch的设计原理有深入的理解,比如索引、副本、集群等技术点;而不能道听途说Elasticsearch很牛,所以选择它,更不能成为把“细节我们不讨论”这句话挂在嘴边 的“PPT架构师”。
通过分步骤、分阶段、分系统等方式,尽量降低方案复杂度,方案本身的复杂度越高,某个细节推翻整个方案的可能性就越高,适当降低复杂性,可以减少这种风险。

如果方案本身就很复杂,那就采取设计团队的方式来进行设计,博采众长,汇集大家的智慧和经验,防止只有1~2个架构师可能出现的思维盲点或者经验盲区。

详细方案设计实战

虽然我们上期在“前浪微博”消息队列的架构设计挑选了备选方案2作为最终方案,但备选方案设计阶段的方案粒度还比较粗,无法真正指导开发人员进行后续的设计和开发,因此需要 在备选方案的基础上进一步细化。

下面我列出一些备选方案2典型的需要细化的点供参考,有兴趣的同学可以自己尝试细化更多的设计点。

上一篇 下一篇

猜你喜欢

热点阅读