系统架构要求规范百度版本.docx
《系统架构要求规范百度版本.docx》由会员分享,可在线阅读,更多相关《系统架构要求规范百度版本.docx(21页珍藏版)》请在冰豆网上搜索。
系统架构要求规范XX版本
系统架构规说明
foquanlin.
2016年9月
文档信息
文档编号:
文档名称:
系统架构规说明
文档类别:
规类
密级:
普通
版本信息:
V0.5
建立日期:
2016-08-29
创建人:
foquanlin.
审核者:
[审核人]
批准人:
[批准人]
批准日期:
[批准日期]
项目/客户:
部用
日期:
存放位置:
编辑软件:
发行软件:
文档状态:
[√]草稿;[]正式发布;[]正在修改
文档修订记录|OutstandingIssues
版本
编号
变化
状态
简要说明
修订日期
变更人
批准日期
批准人
V0.1
A
说明:
版本编号栏中填入版本编号或者更改记录编号。
变化状态分为三种状态:
A——增加;M——修改;D——删除。
在简要说明栏中填写变更的容和变更的围。
表中所有日期格式为:
YYYY-MM-DD。
文档审批信息
序号
审批人
角色
审批日期
签字
说明:
表中所有日期格式为:
YYYY-MM-DD。
[系统架构规—正文]
1前言
本系统架构规仅适用于中型系统和大型系统,对此类项目,一般需要较多人员的参与,如不在开发进行之前定义好一些规、原则,很容易在开发中产生各种各样的问题,如功能切分不合理、服务拆分粒度不足、数据冗余、性能受影响等各式各样的问题。
在构建此类系统前,我们要进行统一的系统层级的设计,来尽量避免文中这些问题的出现。
对于影响不大、重要性不大或存活时间不久的项目,可以采用更为灵活的方式进行自行开发,以免过多人力投入产生浪费。
2技术选型
应以满足系统的需求为出发,考虑选择某个技术对整个系统生命周期的影响:
1.需求层面的影响
是否能够满足当前或未来的业务需求,在整个系统生命周期中,应该优先满足目前业务情况,再考虑未来不确定的业务需求。
2.系统设计层面的影响
系统设计时需要考虑技术特性对整个系统生命周期的适应性,稳定性,可替代性,可维护性,是否可以跨平台,以及开发难度的综合考量,避免系统依赖于某项专用技术,或者和某项技术耦合紧密,降低技术选型变更成本。
3.系统开发层面的影响
应当为开发人员提供技术相关使用文档,以及入门指南等技术资料,应以技术透明为原则做好技术封装工作,和应用规,减轻开发人员使用该技术的难度,降低开发人员学习成本。
4.系统实施层面的影响
应当考虑所采用技术在实施安装部署的技术难度以及硬件的兼容性,稳定性,以及资源消耗问题。
并提供系统所采用技术安装部署操作文档。
5.技术实现难度的评估
评估所选技术实现的难点,算法,技术团队是否能够很好的掌握和使用,开发时间,以及是否会提高系统复杂程度。
6.技术的优缺点评估及同类技术之间差异评估
调研所选技术在行业是否普遍认可和使用,社区维护情况,系统版本是否趋于成熟稳定的状态
7.技术是否开源以及是否成熟稳定
3接口以及协议
3.1原子性
接口原子性,包含三个层面的定义,一个是接口数据的粒度定义,一个是接口在进行写操作的不可打断原则,一个是组合接口的数据拼装的完整。
1.接口粒度:
定义的粒度是否合适,是否充分考虑接口使用者需求。
接口定义是否清晰,通用以及粒度适中原则。
2.不可打断:
接口调用是不可被打断的,如果调用失败则数据不会被修改,要么成功要么失败。
3.组合接口:
是指某个接口的数据来源于其它多个接口的数据进行拼装的结果,这时接口要么返回其它接口都正常返回进行拼装的数据,要么返回接口异常。
原则上,对于服务系统,其接口应该是完成单独的某个功能,应该提供原子级(不可再拆分)的接口,某个复杂的功能,可拆分成几个不同的接口调用来完成。
对于原子级的接口,出错回滚处理也会比较简单。
对于原子级别接口的定义,应当基于对数据操作的不可打断为原则,例如:
用户下单,需要扣减库存生成订单两个数据操作步骤,正确定义:
提供创建订单接口,在创建订单接口里进行库存扣减,错误定义:
创建订单接口+库存扣减接口
3.2可组合性
1.基于接口的原子粒度,根据不同的业务需要,灵活调整接口的拼装调用,完成业务需求的快速实现。
2.定义接口时,要区分服务系统和业务系统或是业务服务组合的系统,服务系统完成服务的提供,业务系统完成业务的封装和转发调用。
3.组合性的接口原则上只用于数据的读取进行组合,当接口存在写操作时,则不建议用组合接口的方式完成事务工作。
具体参考<数据:
原子性>
3.3可读性
1.所有系统提供的接口文档,应该是统一、规的、格式一致的。
2.接口文档的定义,可读,可理解。
在接口中,完整的定义好上传报文和返回报文的相关字段、报文头、报文格式的规。
3.接口字段中的数据字典要明晰,每个字段代表的意义要明确,每个标准数据对应的值,要明确,或标明在哪里可以查询(附录或其他)。
4.不同的服务系统,应有统一的接口命名规则,可根据服务模块直接查找响应接口功能及要求,并可在代码简单查找。
5.接口还应该明示接口是否会对数据进行读或写的操作。
3.4兼容性
1.接口的调用如果产生异常,或接口参数非法等情况时,接口是否做到充分的提示。
2.系统接口设计,要避免依赖于开发语言特性,应考虑兼容于其它开发语言为原则。
3.接口是否充分考虑了各种终端的接入,不同开发语言间的接入等
4.接口应当考虑不同开发语言对于数据类型的定义与区别,应当避免不同语言对数据类型的解析问题,例如:
java的doubble类型,在php里面是有区别的。
3.5独立性
每个接口都应该是独立可被调用的,不因依赖于其它接口被调用为前提才可以正常被调用。
接口的调用不依赖于会话状态的建立,接口调用者只需根据接口参数的定义,满足于接口调用的参数要求后既可正常调用接口返回相应数据。
3.6安全性
1.接口是否公开开放,如果开放是否充分考虑接口调用的合法性问题,如果接口被非法调用怎么处理。
2.接口调用者的合法性校验。
3.接口是否有做入参的合法性检查。
4.接口应当仅限于部系统网络可以访问,并且具有安全性的检测机制防止接口异常调用的发生,非开放式接口不应暴露于公网环境
5.开放接口必须要做好接口鉴权工作,不允许任何一个接口绕过鉴权直接调用,以及做好沙箱隔离。
4数据
数据是系统的产出结果,数据的一致性、原子性、完整性、隔离性直接反映了系统架构设计是否合理以及是否严谨。
维护数据的一致性,原子性,完整性,隔离性需要系统在各个层面(数据库设计,系统架构设计,事务处理机制,编码规)进行系统的设计规划以及对编码有严格的约束和要求,才能够很好的保证数据的四性要求。
在数据操作中,事务对于数据的四性原则起到关键作用,事务操作确保了数据的真实有效。
在系统中事务操作,不仅指数据库的事务还指业务逻辑的事务。
良好的系统架构理应对数据的四性,以及事务的粒度做到统一的平衡保证系统在高负荷情况下也不会崩溃以及数据出错。
4.1一致性
在系统设计时,跨系统之间的调用要考虑事务数据的一致性,要么A系统和B系统成功完成数据操作,要么A系统和B系统都回滚。
系统需要考虑异步处理时保障数据的一致性,不因系统的异步处理导致数据的不一致因而导致数据失真。
系统需要保障数据在系统于系统之间,模块于模块之间,同一时间数据是一致的。
跨系统间的数据要保障数据最终一致性。
数据的一致性也包括在跨系统或模块之间对同一数据的定义也应当是一致的,例如用户名称的数据类型以及长度或格式等在不同系统中对用户名称的数据类型是一致的,长度是一致的,数据格式也是一致的。
4.2原子性
数据的原子性是指,在系统中的业务处理逻辑被执行时导致的数据(创建、修改、删除、文件保存、删除、改名)变更,在整个事务中或许存在多次的数据操作,此时在进入某个数据操作时发生异常应当回滚之前完成的数据操作,以保障本事务要么全部数据修改完成要么全部不做修改。
这里的数据原子性区别于接口的原子性,接口的原子性还包含了接口粒度的原子性,即接口的粒度小到不能再拆分的。
4.3完整性
系统需要保障用户操作的数据是完整的,在数据库设计时应当考虑好表之间的数据约束关系。
代码层面主表与外表的数据操作应当在同一个事务里面完成,不可分割不可打断。
当某个表数据操作失败时,相应的其它表数据的修改也需要同时回滚。
尤其在跨系统间的数据操作,必须保证同一数据A系统存在,B系统对应存在,这设计到分布式事务的处理机制。
数据的完整性,不仅包含于数据库表之间的完整性,还包含于系统的业务逻辑中,假如上传一个商品,其中包含图片信息,商品信息,分别存放于文件服务器,以及多个商品表中,这时应当完整保存商品数据到对应的商品表中以及文件服务器中,如果其中一个表或一个文件保存异常,应当全部回滚保障数据的完整性。
数据的完整性,还包含于单个表的数据完整,假如用户录入信息必须包含时间,如果用户没有填写时间则也不应当保存数据。
这除了数据库式进行约束,在代码层面也应当进行约束,以保障数据的完整性。
4.4持久性
数据修改后,对系统的影响是永久性的,即使系统停机或故障也不会丢失修改后的数据。
数据的持久性不仅限于数据是否正常保存到数据库当中,还包括数据保存介质的可靠,以及保存的数据是否有冗余备份,在数据存储环节出现故障或其它不可遇见的风险时,如何保障数据长久的安全和不丢失。
持久性的另一层意思,是在系统经过持续的更新升级后,老的数据,是否还可以被系统使用的,可读的,可追查的,以及可以被转化再利用的。
当系统出现故障时或硬件出现故障时能保证系统及时恢复故障前的数据。
4.5隔离性
系统与系统间或模块与模块之间对同一数据的操作需要遵循一定原则,避免事务死锁的情况发生,保障系统和模块间的事务操作是隔离的,不会导致A,B,C三个数据之间互相等待对方锁的情况发生。
假如三个事务同时需要对三个数据A,B,C进行操作,这应当遵循优先操作A数据的事务肯定也会优先操作B数据和C数据。
数据的隔离性需要在系统设计和编码阶段尤其需要考虑的工作。
事务的隔离直接影响到系统的稳定性以及系统的可用性。
严重情况会导致整个系统崩溃无法运行和导致数据出错。
以下举例错误的事务隔离和正确的事务隔离例子
错误的事务隔离:
X事务与Y事务需要同时对A,B数据进行操作,此时X事务的操作顺序是BA而Y事务的操作顺序是AB,在极端情况下X事务在锁定B数据后等待A数据的锁释放,而同时Y事务才锁定A数据后等待B数据释放锁,进而X事务与Y事务循环等待对方释放锁导致数据的死锁问题。
正确的事务隔离:
X事务与Y事务需要同时对A,B数据进行操作,此时X事务的操作顺序是AB而Y事务的操作顺序也是AB,在极端情况下X事务在锁定A数据后,此时由于Y事务也优先操作A数据只能等待X事务完成后Y事务再继续操作,进而避免了事务之间循环等待对方事务释放所的可能。
数据的隔离也既事务的隔离,在分布式系统在多个事务对同一数据的操作应当遵循先启动事务者先锁定数据的原则,进行事务操作。
4.6可移植性
在大型的分布式系统中,不可避免的存在不同系统使用不同的数据库以及数据库版本的不一致问题,虽然可移植性不是系统架构的必须要求,但基于数据的可移植性考虑,在数据定义时应当避免使用数据库特性来定义数据属性,数据的定义应当兼容于不同数据库的种类,数据库使用的版本等。
在架构设计时应当优先考虑统一使用统一厂商的数据库品种以及同一版本的数据库为原则,尽可能避免数据库移植产生的转换成本。
4.7标准数据定义
系统中存在的常见数据字典的定义,业务状态数据等的数据要有标准的定义。
标准数据定义一般是指跨系统或模块之间广泛使用的以及频繁被使用的数据,或业务状态数据,对标准数据定义的名字应当人机可读的并遵循固定的命名规则,便于开发人员理解以及使用。
标准数据的定义,应当广泛考虑在各个场景中使用的普遍适用程度,以及在跨系统和跨语言之间的通用性,避免使用特定语言的数据类型或格式。
5系统
设计软件系统的模块层次结构,设计数据库的结构以及设计模块的控制流程,其目的是明确软件系统"如何做"。
这个阶段又分两个步骤:
概要设计和详细设计。
概要设计解决软件系统的模块划分和模块的层次结构以及数据库设计;详细设计解决每个模块的控制流程,部算法和数据结构的设计。
这个阶段结束,要交付概要设计说明书和设计说明,也可以合并在一起,称为设计说明书。
在系统分析的基础上,设计出能满足预定目标的系统的过程。
系统设计容主要包括:
确定设计方针和方法,将系统分解为若干子系统,确定各子系统的目标、功能及其相互关系,决定对子系统的管理体制和控制方式,对各子系统进行技术设计和评价,对全系统进行技术设计和评价等。
系统设计需要考虑的原则,必须遵循并考虑以下问题。
5.1系统可靠性
系统的可靠性与系统的稳定性紧密相关,系统的可靠性往往建立在系统的稳定性基础之上,这里对系统的可靠性仅限于在系统发生不可预测的故障问题时对系统的影响程度的要求,原则上基础设施没有大面积瘫痪的基础上系统应当都能够可靠的运行并提供应有的服务。
系统运行中某个独立模块发生故障,不应当影响其它不相关模块的正常运行,系统故障时能够及时恢复系统或新增机器资源保障系统能够正常继续工作,系统不因硬件的故障问题导致整个系统瘫痪无法运行。
平均无故障时间,系统平均正常运行多长时间才发生一次故障
5.2系统稳定性
系统的稳定性主要考虑下列各项指标因素,系统的稳定性也间接反应系统的架构设计的优劣以及代码质量优劣问题。
1.系统在无外界干预情况下是否能长期稳定运行
2.系统在高负荷情况下是否能正常运行不影响用户使用
3.系统在受到网络攻击时是否能够正常运行
4.系统在受到网络资源限制时是否能够正常运行
5.系统在受到存资源瓶颈时是否能够正常运行
6.系统在受到CPU资源瓶颈时是否能够正常运行
7.系统在受到磁盘资源瓶颈是是否能够正常运行
5.3系统安全性
系统安全性包括系统能够鉴别非法和合法用户的安全性以及用户对数据操作的安全性,隔离非授权用户对数据的访问以及操作,另外对于合法用户也需要做到鉴别非法数据的输入鉴别处理。
授权:
在需要授权的操作中,如果用户未获得授权许可应当决绝用户对数据的操作行为。
注入:
往往非法的入侵伴随着系统存在着可以被注入恶意代码的漏洞,注入方式有web脚本注入,sql注入,可执行命令注入或堆栈溢出漏洞等,系统应当在用户提交的数据中做好数据的合法性检查。
5.4系统扩展性
系统应当具有新的功能模块扩展的能力,不因新需求的增加而造成系统的重大变更甚至重构才能满足需求。
系统的扩展性不仅限于新功能的可扩展,还包括无用功能的移除也不应造成系统重大的变更或重构才能完成。
系统的扩展性还包括计算能力的可扩展性,当系统负荷压力超过单机能够完成的计算量时,系统能够动态的增加机器资源完成负载压力的分布,降低系统的计算压力,当系统压力下降后能够自动的或手动的撤销机器资源。
系统还应支持数据存储层面的扩展,在系统的存储层面已经产生瓶颈时系统能够支持存储的扩展以其能够很好的解决数据存储的瓶颈而不至于整个系统重构或做出很大的变更来满足拓展存储的需求瓶颈。
5.5系统移植性
系统的设计时应当注意避免使用某项技术的特性来构建系统,尽可能使用技术的标准件,或对某项技术做好封装和隔离并考虑后备方案。
例如:
系统在使用tomcat时,不应依赖于tomcat特有的技术特性,如果系统移植到jboss时则会导致系统无常运行。
1.系统环境能够自由切换到不同云平台
系统设计时应当考虑在各种云平台中能够正常运行而不限制于特定的平台技术限制。
同时也应当考虑系统能够运行在不同操作系统以及不同硬件机器资源,而不依赖于特定的硬件或特定的操作系统以及某种技术。
系统应当支持所用操作系统的版本升级,例如操作系统更新升级后不会影响系统的正常运行。
2.系统环境是否可自行部署
系统安装部署应当能够脱离开发人员自行部署,其它人员根据安装部署文件即可完成部署工作,不因为使用某种技术而需要开发人员协助才能安装部署。
3.系统是否依赖于特定硬件
如果没有特殊需求,系统不应依赖于特定的硬件作为系统的必须条件,系统应当支持所用的硬件升级,硬件升级而不影响系统正常运行。
4.系统是否依赖于特定技术
系统所使用技术当发现有一定风险或存在隐患时能够比较容易的迁移到其它技术方案替代,而不会导致系统发生颠覆式的重构或无法迁移。
如果系统确实需要用到某种特定技术,应当在设计层面做好封装解耦系统对某种技术的紧密依赖。
例如系统用到RocketMQ,由于后期发现存在一定风险转用更加可靠稳定的替代技术时,不会因为系统严重依赖RocketMQ而导致无法替代或替代成本高昂。
5.6系统独立性
1.系统应该是独立的,不因其它不相关的系统发生故障而不能运行,不会因为依赖于别的系统才能使用,不会因为其它系统发生故障而导致本系统不能运行或发生连锁反应。
2.系统中的子系统也是相对独立的,除了核心模块外,不会因为不相关模块的故障而不能使用和运行。
3.系统设计时,应当考虑各模块之间互相独立以及各系统接口之间互相独立,互不影响对方的运行与使用,不应该因为某个模块或某个系统发生故障而影响其它系统或全部系统的正常使用和运行。
5.7系统可监控性
在大型的分布式系统中,系统运行时总会出现各种不可预见的异常、资源瓶颈、并发、系统瓶颈等问题,往往这些问题在开发环境中都难以体现或难以模拟。
当系统在运行过程中如果没有有效的监控手段,在系统存在问题或bug时无异于盲人摸象浑水里抓鱼无从下手,系统的可监控性具有重要的意义,系统的可监控性有助于问题的排查和分析并促进问题快速有效的解决的一个手段,同时可监控的系统也有助于提前预警系统未发现的隐患,具有预警问题发现问题排查问题和解决问题的重要作用。
在分布式系统中,系统间的接口调用应具备可监控的手段,及时监听系统的各种运行指标,并输出相应接口调用频率,每次调用时间,平均调用时间,异常次数,接口入参数据,数据库负载情况,缓存使用情况,缓存使用频率等等便于开发人员和运维人员做问题的预警和分析优化,调拨机器资源,改善技术方案或调整系统架构等工作。
监控涉及到系统的重要环节当中,包括不仅限于以下环节
1.运维人员随时可以查看系统运行的事实状况,磁盘IO,CPU,存,网络等
2.技术人员随时可以查看请求的调用链条,系统负荷状况,接口调用频率,接口异常次数,接口调用耗时,数据库数,数据库请求耗时,缓存请求耗时,缓存命中率,存使用状况,PV,UV,并发线程数,消息队列堆积情况,数据库状态等。
系统监控还应当支持系统各种治标值的预警能力,允许运维人员或系统管理人员设置系统的监控报警阀值,以及各种指标的报警开关等,并将系统报警信息通知并发送给相关人员。
5.8系统易维护性
分布式系统的体量庞大,系统与系统间或多或少都存在关联性,系统的变更和改动会对其它系统造成大小不一的影响,这需要对系统的设计以及代码的要求都比较高,同时在系统的架构设计以及开发编码中应当充分考虑系统的可维护性。
系统在设计阶段就要充分考虑好系统的可维护性,系统的可维护性包含代码的可读,可调试,可跟踪,可测试,可还原的基本原则.
可测试原则:
既系统设计的接口,对象,方法,包括但不仅限于接口层服务层以及数据持久层应当可以互相独立进行单元测试。
可读原则:
既开发出来的代码核心对象和重要方法都应当有充分的注释说明描述,代码命名以及定义符合编码规,应做到开发人员能够轻易理解做在对象或方法的意图。
对于比较复杂的方法,应当拆分成多个简单的方法。
可调试原则:
既代码的编写在符合编码规的前提下应注意空指针变量被执行在代码中做好空指针判断对无效或非法入参进行过滤和检查,确保业务被执行时的数据合法有效。
多用临时变量减少堆栈的深度,变量类型明确定义和声明。
错误的例子
Dd=funA().funB().funC().funD();
这个例子的代码是难移调试的。
正确的例子
Aa=funA();
Bb=a.funB();
Cc=b.funC();
Dd=c.funD();
这样写的代码是可调试的
可跟踪原则:
代码的可跟踪与可调试密不可分,这里仅描述在非调试状态下,便于技术人员能够跟踪异常的执行情况。
系统在设计和编码阶段应当充分考虑好测试日志的输出,不同层级的日志输出以及日志输出的可配置化,系统应当支持日志配置的动态生效以及动态禁止而不用重新启动服务器。
做好日志输出的规划工作,对于接口以及重要方法的执行必须做入参数据的日志输出以及返回数据的日志输出,确保在系统出现异常时技术人员能够跟踪日志信息快速定位和排查问题的原因。
6处理机制
处理机制是针对在系统中广泛存在的特定问题进行统一处理的方式,把开发人员解放出来,避免开发人员过多和重复考虑广泛存在的问题。
处理机制应当是有针对性的解决某一领域广泛存在的问题,同时处理方式应当避免或尽可能的降低跟现有的业务代码产生紧密的耦合。
6.1缓存使用机制
在一个高并发的系统中,每一次请求都需要读取响应的数据,在当前磁盘读取效率底下的情况下,为了更好的实现快速响应,而引入缓存机制既在用户请求数据时,第一次访问则读取磁盘数据而后将磁盘数据放如存当中提高下次读取同一数据的效率,缓存的使用大大提高了系统整体的并发效率,这一机制同时也增加了系统的复杂度。
在系统使用缓存后,既同一数据产生了两份一份在存中一份在磁盘中,如何保障缓存数据与磁盘数据的一致性至关重要,在系统架构层面应当统一处理缓存的使用读取,写入等的一些列标准化抽象,避免由开发人员直接管理和使用缓存不当而导致数据的不一致性。
缓存的使用原则,缓存的使用应视具体业务情况,并非所有数据都需要使用缓存,缓存的目的是为了提高数据的多次读取效率,一次读取多次使用,某些数据的操作频率非常低的情况下则可以不用缓存。
缓存命中率,命中率也既缓存被使用的概率,命中率的高低直接反应了系统对缓存使用的合理程度以及缓存带来的效率,命中率高则缓存使用合理,命中率低则使用不合理,甚至可以不用缓存,衡量缓存命中率的关键因素在于数据读和数据写的频率,其方程式可以简单概括为(读次数÷写次数=命中率)如果命中率等于1则完全可以不用缓存。
命中率越高则证明缓存使用越合理和必要。
6.2日志处理机制
在高并发的大型分布式系统中,日志信息输出有助于系统的优化以及问题跟踪处理,同时日志输出也会给系统带来额外的运行开销,滥用日志输出会严重影响系统性能,日志的处理应当遵循一些原则和规,尽可能减少不必要的日志输出。
可配置,日志的输出应当允许运营人员动态的去配置,而不需要重启服务器。
格式化,日志的输出应当遵循一定的约定和规则。
日志输出应当是可配置的,运维可通过配置打开或关闭日志输出。
日志输出不应该影响系统的正常运行。
日志输出不应造成系统性能大幅下降。
日志输出容应该是可读的,既日志容不用经过工具解析开发人员是可以看得懂的没有加密的,日志文件也是可以打开的,同时日志输出容应该是可分析的,既容具有一定的代表性反映了系统真实的当时运营状态。
6.3异常处理机制
异常的处理方式关系到系统的友好性以及容错性和健壮性,系统在运行过程中会抛出各种可预见和不可预见的异常,这是系统架构应当