架构设计的原则

时间:2022-09-19 10:28:10

本文是对《架构即未来》一书第12章的总结;
1. 书中总结了一个好的架构应该具备的特点,但是有些特点个人感觉是重复的,总结起来应该有以下3个特点:
(1) 具体的、可执行的;好的架构不应有太多虚的东西,它应该能够切实可执行起来用于指导开发;
(2) 可度量的;平时最关注的是一个架构所能承载的性能,它应该是可以测试出来;
(3) 可达到的;架构设计不应脱离实际,一个很美好但是无法实现的架构是没有任何意义的;

  1. 确定架构设计原则
    在大型公司中,架构师们往往都是一个团队甚至一个部门,每个架构师的设计思路都不一样,因此要确定一些原则用于指导架构师们的设计;
    可以按照如下步骤制定一个架构师团队的架构设计原则:
    (1) 确保所有参与方都去应用这些原则,否则原则的定义就没有任何意义;
    (2) 通过将这些原则与公司的愿景、任务和目标关联,创建一个成功的因果图;
    (3) 为原则拟定主题,韦恩图对显示重叠的原则很有用;
    (4) 把大团队分成小团队,然后有每个小团队分别提出他们的原则,虽然每个团队所提出的原则描述不同,但是一般都能发现这些团队共同关注的那些原则条款;
    (5) 把团队集合起来做个小展示,然后再让各小团队来修改他们的原则;
    (6) 让每个团队阐述他们的原则,然后选择那些重叠度较高(例如超过半数的团队都赞成的原则)的原则;
    (7) 把不重叠,或者重叠度较低的条款单独列出来,再让大家投票选择;
    (8) 把总的原则条款列出来,包括第(6)步选择出的重叠度高的条款和第(7)重叠度低的投票结果;
    (9) 大家最后讨论决定选择哪些条款作为大家日后架构设计的原则;
  2. 架构设计原则不是一成不变的,而是会随着大家的工作经验、业务发展等等各种因素而成长的。
  3. 一些公认的架构设计原则
    (1) N+1原则,即任何服务在部署时都要多部署一个冗余服务,这即能防止服务出现单点部署(由于N>1,所以部署总数至少为2),也能防止故障发生时系统还能有一定的承载的能力;
    (2) 回滚设计,确保每个升级的版本都要向后兼容,即要兼容以前的旧版本,这样可以防止新版本故障时可以立即回滚;
    (3) 禁用设计,当一个系统要另一个高风险模块或服务对接时,要能够通过开关来禁用它,而且尽量减少对原有功能的影响,这样一旦生成环境中高风险模块发生故障时,我们可以快速关闭它;
    (4) 监控设计,尤其是针对分布式的微服务架构中,一个复杂的系统往往有多个功能独立的服务来组合完成,这种分散的设计增加了故障发生的概率,而且一旦故障发生分析起来就相对困难,因此我们需要完善的监控设计,才能实施监控系统中各个服务的运行情况,一旦服务出现异常,系统应能提醒相关的运维、研发人员,如果可以它还可以自动恢复;监控设计时,要充分考虑通用监控系统、详细监控功能、日志分析系统等等,例如我们常用的nagios、zabbix等都是常用的通用监控系统,可以用于监控某个主机上的某个服务进程是否还存在;详细监控功能可以监控到服务进程是否存在假死现象;日志收集和分析系统不仅能协助相关人员事后分析、定位问题,而且通过对历史日志信息的分析也能挖掘出一些潜在的风险点;
    (5) 设计多活数据中心,这个对于大多数中小公司来说都用不上;
    (6) 使用成熟的技术;在系统的关键位置一定使用成熟稳定的技术;在团队开发过程中,大家经常热衷于追求新技术,新框架,例如,我们在选用rpc框架时,就有采用thrift还是grpc的大讨论,我们当时的原则选择thrift,就是因为rpc框架是后台业务的关键部分,thrift相对成熟、稳定,并且我们详细分析、学习过它的源码,对它的掌握更充分,虽然grpc宣称效率很高,而且采用新的go语言,但是我们还是不愿意在生产环境上的主要服务中去做尝试。对于新技术,可以先在对系统的可用性不高的新功能上,经过一段时间的验证,等稳定了,大家对新技术的掌握程度足够了,再将之推广重点领域;
    (7) 异步设计,这一点也是大家在做分布式设计时经常采用的原则,一般情况下,同步实现简单,异步实现复杂;但是异步会让系统的耦合性降低,也会让整个系统更加弹性、健壮;其实,也没有多少更详细的原则来说明什么情况下应该用异步,异步应该如何设计?我们只能根据自己的业务来判断,哪里适合去做异步;常见的异步结构方式就是采用消息队列,例如RabbitMQ、Kafka等等;
    (8) 无状态系统,这个是后台服务开发的基本原则之一,一般情况下,我们都要求所设计的服务无状态,所有服务处理过程中需要保存的数据都要存入到Redis、memched等第三方独立缓存中。
    (9) 优先选择水平扩展,无状态是水平扩展的前提,只要能做到无状态的服务基本都具备一定的水平扩展能力;一般情况下,服务的水平扩展比较容易,垂直扩展则涉及到分割业务、数据,实现起来相对复杂;
    (10) 设计架构要有两个步骤的前瞻性,这个比较难以把控,其实每个人在做架构设计时都会尽量考虑后续扩展性,个人认为除非很了解业务,否则不要做太远的考虑,考虑的越远,所考虑的事情被实现的可能性就越低;
    (11) 非核心则购买;个人理解,国内大多数公司纠结的是自研还是开源,而非自研和购买,其实每个团队的精力、能力都是有限的,把团队的力量尽可能的放在核心业务上,非核心业务的地方则能采用开源就采用开源,能购买就购买,千万不能为了一个小的非重点业务而投入团队太多的人力;
    (12) 小构建、小发布、快速试错,这时开发过程中经常采用的快速迭代原则,这一点是大家公认的;因为改动越多,风险越大,出了问题就越难分析定位;
    (13) 故障隔离,防止一个服务出现故障时对整个系统产生影响,就像电路设计里面的短路保护,一旦一个电器发生短路,则系统马上断电,从而防止系统中其他电器被烧坏。不同的是一般家里电路短路时;整个家里的电就全短路,而我们设计系统时不能因为一个模块出现故障而让整个系统出现停止服务的问题,因此就要对各个服务模块做好故障隔离,一旦本模块出现问题了不要将问题波及到其的服务;
    (14) 自动化,这一点是所有团队努力的目标,包括自动构建、自动化测试、自动化发布、自动化监控等等各个系统,所有这些自动化的东西构建起来所需的东西非常多,好找各个部分的自动化中都有相应的开源软件,我们只需要把这些开源软件应用好,也能满足一定的自动化要求。