人人都可以做产品经理,但是却没有人随随便便成为系统架构师,系统架构师为什么这么稀缺,因为系统架构师要求的能力是十分全面的,首先技术基本功要非常扎实,其次是你的统筹能力,一个项目交到你手上,你具不具备从事先需求分析,系统设计,人员安排;事中进度把控,跨团队沟通,事后推动项目最终如期高质量上线的能力。还有一个能力非常重要,就是在项目复盘的时候能不能将项目的复杂度,所创造的业务价值充分的展现出来,也就是我们所说的PPT能力,别瞧不起这项能力,如果一个层级很高的领导,他根本不清楚你所做的具体事情,他只能通过你的汇报来了解你的项目,如果此时讲不清楚复杂度和业务价值,那必然拿不到好的技术结果。
今天我们就从一个具体的例子来讲述系统架构师是如何完成一个分布式高可用系统的设计。
名词解释
集群:即同一个系统部署多个节点,任意一个节点都可以提供同样的服务。
分布式:是一种部署方式,就是将一个完整的系统拆解成多个子系统,并部署在不同的物理机上,通过固定的通信方式,例如http或者rpc从而形成一个完整的系统,这是分布式。
微服务:是一种架构方式,就是将一个完整的系统拆解成多个子系统,通过固定的通信方式,例如http或者rpc从而形成一个完整的系统,微服务既可以部署在同一个物理机上,也可以部署在不同的物理机上,所以微服务包含分布式。
高可用:没有任何系统敢说百分百可用,系统只能做到高可用,高可用也就是在各种极端情况下,例如机房起火,施工将网线挖断,系统依然能够正常的对外提供服务,这是高可用。
分布式是实现高可用的一种手段,分布式不一定能够实现高可用,例如我们虽然把子系统部署在不同的物理机上,但是如果这些物理机全部在同一个机房内,机房起火后就无法实现高可用。
充分理解需求
任何脱离业务的架构都是耍流氓,架构必须贴近需求,并且在当前业务的基础之上留好拓展性。
我们以图文共享系统为例,它最基本的需求如下:
插播一则通告:本人在代码一线工作近八年时间,有非常丰富的面试经验,有需要优化简历,模拟面试的同学可以联系V:xiaolang1530368931。将简历优化成大厂面试官想看的,提前回答大厂面试官可能会问的问题,为进大厂做最后的冲刺。
分析需求一般三步走:
- 梳理业务整体脉络
一般产品会输出一篇需求文档,文档里面会包含特别多的内容,特别是大型项目。不管是大型项目还是迭代需求,首先做的第一件事就是搞清楚这个需求大致是需要做一个什么东西,做到心中有数。
- 梳理技术整体脉络
产品文档的流程图一般只是业务流程,不涉及技术实现,所以为了加深对需求的理解,第二步就是基于需求文档中的流程图,输出一版技术流程图,里面不但会包含需求流程,还会包含技术上的具体实现,包括不限于交互方式,是http/rpc,重试机制,补偿处理等信息。
- 结合自己的思考给出合理建议
因为产品在输出文档时,一般是考虑业务的需求,并且大多数产品是不懂技术的,也没有技术思维,所以在梳理完需求之后,如果哪些说的不合理,或者技术上无法实现,例如要实现五彩斑斓的黑,因为他们从用户角度,这样可能会比较炫酷,这种我们就应该打回去,不受理这样的需求点。还有一些点就是产品遗漏的内容,当局者迷,旁观者清,产品和技术相辅相成,才可以成就伟大的产品。
架构设计
现在的主流架构设计都是采用微服务,我也推崇使用微服务,单体架构和微服务架构优劣势对比如下:
优势 | 劣势 | |
单体 |
|
|
微服务 |
|
|
微服务依然存在很多问题,但是相对单体依然还是有很大的优势,架构设计不存在最适合,只有更适合。
所以我们的图文共享系统语句拆分为用户服务、图文服务、风控服务、推荐服务、结算服务。
数据库设计
数据库设计三泛式:
- 每个表必须存在主键
- 一个表的外键必须是一个表的主键
- 表里的每个字段必须是原子的(也就是没有办法再细拆,例如收获地址,我们应该设计为四个字段,省市区,详细地址,而不是一个字段保存)
三泛式很重要,但是实际工作中一般是改良的三泛式,第一点和第三点保持不变;第二点实际应用中一般不会使用物理外键,而是使用逻辑外键替代,这样既达到了外键的效果,又保证了拓展性,在此基础之上还会给所有物理表加一个通用字段,例如用户ID,这是方便后续的查询。
代码框架设计
- 代码分层设计
代码分层设计
我们以使用Spring Cloud全家桶实现微服务架构为例,一般代码分层设计会分为这四块,Controller作为我们向外暴露服务的入口,Service作为我们具体的功能实现,一个接口如果有多个实现我们会在Controller层对这个Service进行编排(即组装)成一个功能,在Dao层我们会提供一些数据库相关操作供Service层使用,事物我们也会在这一层完成,Mapper层则提供数据操作的原子能力供Dao层使用。
- 定义全局切面
我们为什么需要走分层契约呢,就是为全局切面铺垫,我们自定义一个切面,切点为Controller层,切面将完成以下事情:
- 全局异常处理,分业务异常与系统异常,向上游返回。
- 入参、出参报文打印。
- JSR参数校验
将重复的事情交给切面统一去做,解放生产力,让我们编码时只需要关注业务代码本身。
当然定义契约我们还可以做其他更多的事情,例如我们可以在切面内实现分布式锁,请求频次限制等多种复用功能。
或者可以采用模版模式参考我之前的文章:顶级抽象思维
- 设计模式进行抽象
有些接口需要进行一定的权限校验,那我们可以定义一个模版,将校验的逻辑抽象出来,不用每个接口都去处理一遍权限校验,极大的提高工作效率。
监控设计
系统上线之后,异常全靠人工反馈吗?
人工反馈的链路基本上是:客户 -> 运营 -> 业务 -> 产品 -> 技术主管 -> 开发
这个链路,少则几天,多则半个月,一般我们的系统日志会在有限期内清除,那么在清除之后,我们就很难再还原现场,给排查问题造成极大的困难。
所以监控显的尤为重要,在系统上线初期,我们至少要完成以下监控:
- 错误日志采集,大于多少行之后主动告警。
- 重大风险处,例如阻塞主流程,添加额外告警,只要出现,需要立即人工介入排查。
容灾设计
作为一个高可用系统,在系统上线初期,用户量较小的场景下,我们至少要保证基本的高可用,即集群+多机房部署,这样可以避免单点以及机房起火等灾难场景。
输出设计文档
虽然说技术的主要工作是将业务需求通过代码的方式实现,但是前期准备工作少不了,磨刀不误砍柴工,项目负责人会输出如下设计文档,包含不限于以下内容:
- 资源投入
前端、后端、测试、产品、设计到底是哪些人投入,具体分工,各职能线给出预估工作量,依据工作量与上线时间要求,看是否需要投入更多的人力。
- 里程碑
根据工作量,预估联调时间节点、提测时间节点、上线时间节点。
- 系统详细设计
- 技术基于对业务流程的理解,给出技术上实现流程图。
- 数据库设计。
- 代码流程设计
项目中期
随着项目的推进,负责人会遇到各种各样的问题,例如核心成员离职,突然休假,前期预估工作量有偏差,导致项目无法按照计划推进,这都是非常常见的,所以我们应该让产品牵头,或者技术负责人牵头,至少每两天对一下进度,去提前暴露风险。
上线
大项目期间一定会遇到各种各样的问题,如果我们顺利处理了所有问题,项目如期上线,这个时候我们的监控设计就变的非常重要了,上线后我们会遇到很多在线下环境无法复现的问题,例如主从切换,线下环境只有一个环境,主从链接都是配置的同一个,就不会存在我们写入数据后立马查询却出现了查询不到的问题,因为主从集群一般是主写从读,如果存在主从延迟,那写入主数据库之后立马去查询,大概率就会查不到,从而问题就暴露了。
所以除了线上验证,监控尤为重要,主动发现远好过于被动排查。
以上就是关于系统架构设计的分享,篇幅限制,详细内容看各位同学对哪块比较感兴趣,我们单独出一篇文章细聊,如果大家觉得有一点点受益的话,希望点赞、评论、转发来支持我做更加优质的分享。
分享一句非常喜欢的话:把根牢牢扎深,再等春风一来,便会春暖花开。
PS:以上引用信息以及图片均来自网络公开信息,如有侵权,请留言或联系
504401503@qq.com,立马删除。