“星光不问赶路人,时光不负有心人”
做过一些项目,也带过一些项目,通过摸索,学习,实践,慢慢对一个高可用,稳定的项目架构有了一些初步的了解,将一些做项目方面的心得简单的总结下来,供自己日后查漏补缺,欢迎探讨。
一,项目的来源
总结工作经历中,项目立项的主要几个思路来源如下:
1. 客户诉求
这类来源最直接,由客户主导项目的需求,客户主动提供项目的目标,项目的诉求,项目组根据客户的述求,进行项目需求的整理,项目方案的落地。
2. 行业趋势
通过了解行业最新的趋势,类比行业内的最佳解决方案,向客户提供采用最新最优技术的解决方案,吸引客户的目光,引起客户的兴趣,要量化的体现出新idea能够带来的效益,或者降低的成本。
3. 客户痛点
客户和方案提供方角色不一样,我们多从技术方面去认知,客户会从市场,会从业务方面去认知项目,所以客户会有很多痛点,我们要主动去和客户沟通,了解客户的痛点问题,然后给出落地的方案,尝尝会达到事半功倍的效果。
4. 运营梳理
在系统或平台的运营的过程中,用户,开发,测试,运维,运营等各个角色都会遇到各种无法解决的痛点和问题,或者随着整体的一个大的系统背景的变更,小的系统和平台也需要去适配和变更,这过程也可以攒出项目的落地内容,进行立项。
二,客户的沟通
对于技术人员来说,沟通其实一直是个难题,因为大多数技术人员包括我自己更愿意埋头搞技术,完成一个功能或者修改一个bug带来的快感让我们如痴如醉。但是随着工作经历的增加,我觉得应该埋头干活,抬头思考,开口沟通,动手实践,其中开口沟通一门很重要的技能,能够让我们更加准确的了解客户的真实诉求,找到更好的解决方案。
客户千人千面,不同的客户有不同性格,也有不同的立场,对于不同的客户我们要有不同的沟通着重点。
客户高级领导:
首先要表明自身和自身团队的技术实例,说明实施这个项目的驱动力,对于长远架构的帮助,列举解决方案和最佳实践,说明自身的优势
客户项目经理:
要进行量化指标,要说明实际的可落地的方案,解决问题的场景,以及对现有流程,现有业务的影响范围,能够带来的收益
客户项目人员:
要说明实际使用的技术,可实施的方案,以及清晰的计划和里程碑
三,项目生命周期管控
①需求调研阶段
这一阶段的主要目标,是走进客户现场,深入运营一线,深入挖掘和采集实际的需求和述求,并如实精确的记录下来,包括但不限于背景,目标和范围,现状,影响范围,项目内容,工作量评估,预算,优先级,外围依赖,软硬件资源,部署方式等等的沟通和明确。
②需求分析阶段
现在在需求分析阶段经常要求提供cosmic的材料,作为工作量评估的依据,一般的,通常项目需求阶段需要完成的任务包括用户需求分析,业务需求分析,功能需求分析,以及一些非功能性需求的分析,最后出具需求分析报告。需求分析作为后续项目设计的基础和依据,是很重要的环节,如果需求分析出现偏差,后续设计开发的功能可能和客户实际需求有出入。
值得注意的是,变化是永远存在的,我们要实时的去更新调整我们的目标,以适应变化,永远要保持和客户和现场的沟通,不要闭门造车
③项目设计阶段
项目设计阶段,通常分为概要设计和详细设计阶段。
概要设计阶段,我们主要目标是要指定一个大概的总体设计,总体规划,比如项目包含哪些功能模块,每个模块做什么内容,数据模型怎么样,容灾怎么做,安全模块怎么设计等等
详细设计阶段,我们就要依据概要设计来进行落地方案的设计,作为开发的依据和指导,这部分我觉得重点在可落地三个字上,要有把想法变为方案的切实可行的方案设计,除了功能架构,逻辑架构,甚至要落实到使用到的表和表中的字段设计,主键外键设计等等
④规划及里程碑设计
作为项目管理人员,要保证项目能够如期的上线交付,要合理的分配每个项目成员的工作,就要根据项目内容制定切实可行的项目规划和里程碑设计,这块儿我常用到的软件是project。当然落实到日常中,我们还可以通过一些看板的方式,来渠道项目推进和问题解决。
对于一些功能复杂和周期长的项目,我们可以制定分批次的上线计划,按照客户需求的紧要程度和依赖资源的具备情况,功能模块间的耦合关系等,合理划分每个批次的上线内容。
需要注意的时,时间安排要尽量合理,根据经验,时间安排上不能踩点最后的deadline,要尽量将开发测试任务排布的更提前一点,留够buffer时间,因为按照经验,在资源申请集成,各系统之间交互依赖以及一些不可控突发事件(封网)上,时间往往不可控。
⑤资源集成阶段
资源集成阶段的主要工作,一般包括硬件资源申请,软件资源申请,容器化资源申请,虚拟机资源申请,网络策略打通等内容。
一般的,资源申请要兼顾到各个环境,例如开发,测试,生产环境,还要考虑到安全问题,例如防火墙等等,当然还有成本问题,效率问题,要尽量的客观的评估项目上线后所需要的最大资源,考虑是否有必要使用物理机,是否使用虚拟机即可,合理的申请资源,避免资源的浪费,降本增效。
⑥项目开发阶段
项目开发阶段,就是根据前期沟通和设计,通过代码实现我们的目标。这一阶段,也要保持项目团队成员间的沟通,要根据需求的调整和变化来变更自己的开发计划或方案,还是那个原因,变化是客观存在的。
每天可以举行几分钟的站立会,每个人讲一讲自己做了什么,正在做什么,将要做什么,其他的问题可以不在站立会上说,提高沟通效率,节约开发时间。可以通过看板工具,日报工具来回报工作进展。每周可以规定一个确定的时间,进行一次codeview,保证开发的质量等等,这都是开发阶段的一些具体措施。
⑦测试验证阶段
测试验证阶段实际上和开发阶段已经部署阶段没有明显的隔离,贯穿始终,一般的,测试环节又分为单元测试,功能测试,性能测试,回归测试等等
⑧上线部署阶段
上线部署阶段的前提是生产资源的具备,这一阶段常见的工作内容包括
○制定上线计划,割接计划
○分析上线影响
○制定上线步骤
○准备验证资源及案例
○应急预案
○保障方案
上线完成后,要出具上线验证报告,告知客户和报障人员
⑨线上试运行(初验)
如果具备灰度环境,可以先上灰度。
一般的,这一阶段可以逐步切换流量到新系统上来,如果未发现明显异常,再根据迁移方案分批次的切换生产现网业务进来,避免由于故障带来过大的损失。
⑩培训推广阶段
编写项目操作手册,对开发,运维等相关人员进行培训,提供操作手册供客户用户使用。
⑪项目终验及后期运营
项目开发阶段结束,进入后期运营运维阶段,一般来说,这一阶段会移交专门的运维团队进行管控,响应运营过程中遇到的零星需求。
四,项目高可用架构演进的探索
系统稳定性和业务连续性,一直是我们孜孜以求的目标,是一个平台和系统想要做大做强的必要条件。我理解的项目高可用,不只是应用和组件的一个高可用,他还应该包括架构高可用(防御式编程,可观察架构)和人员的高可用(提升运维效率,培训,预案)。但在这里,我先聊聊架构层面的高可用演进。
1,应用和组件分离
这应该是最简单的一类项目结构,用户通过浏览器访问应用主机,应用所需的配置数据存放在数据库中。在这里我们将应用app和database进行分开部署,避免其争抢资源,造成性能损耗,这是我们第一步演进思路
2,数据库读写分离
随着访问量的上升,对单节点的数据库会造成压力,频繁的读写场景中,我们发现系统大多数时候是读,写操作会少一些,这样,我们的演进思路就是进行读写的分离,可以添加多个读库,写库和读库之间同步数据,这里可以用到mycat来实现。
3,二级缓存和分布式缓存
好了,随着业务量的继续增加,我们发现直连数据完全扛不住压力了,这时候我们考虑使用缓存,引入了分布式缓存和本地缓存,分布式缓存常采用redis集群来实现,数据从数据库同步到缓存中,应用jvm又从redis同步放到本地缓存中,这样可以避免对数据库造成更大的直连压力。
4,Nginx负载均衡
之前的架构还是太过畸形,因为明显可以看出应用实例太少,为何不扩展下应用的数量呢,所以我们引入了Nginx,来做负载均衡,将流量均匀的分配到多个应用实例上,这样可以承载的请求量就更多了。常见的负载均衡算法包括随机,轮询,最小连接数,加权轮询等等
5,分库分表
前面其实已经达到了一些小规模项目的架构基本要求,随着业务的复杂和请求量的上升,我们可以继续对数据库做文章,进行分库分表,不同的业务放在不同的数据库,同一张表可以按区分到不同的分表中,进一步减轻查询访问的压力
6,硬件负载均衡
当然,我们还可以在nginx上打主意,毕竟增加应用数量来增加平台的能力上限是一个常规思路,所以我们这次演进,在nginx的基础上增加了一层硬件负载F5,将请求均匀的转发到各个nginx节点上
7,DNS实现多机房
现在我们要考虑的问题是机房的承受能力,这可以有几个目的:
A,跨机房容灾
B,多机房负载
C,实现流量的就近访问,提高访问速度
所以演进的这个步骤中,我们构建了多机房
8,去IOE
由于数据的持续增加,常见的关系型数据库不适用一些复杂的查询,对于一些需要频发查询统计大量数据的情况下,我们引入了非关系型数据库比如mongodb,hbase等等,当然在这之前,我们还替换了Oracle,因为mysql免费,开源,可以灵活的做很多定制化的配置和改造
9,应用按业务拆分
我们好久没有从我们业务下手了,按照业务板块来划分应用代码,使单个应用的职责更清晰,相互之间可以做到独立升级迭代,当然这就涉及一些注册中心,配置中心的概念了。
10,微服务化
上次的演进,还可以进一步的进行细化拆分,将一些公共的模块独立出来,形成独立的应用模块,这样的应用模块就是微服务,应用和服务之间通过HTTP、TCP或RPC请求等多种方式来访问公共服务
11,能力开放服务治理
引入能力开放层,也就是通常所说的esb服务总线层,来屏蔽各个应用之间接口的差异,同时将内外部渠道的接口进行有序开放和统一管控,通过ESB统一进行访问协议转换,应用统一通过ESB来访问后端服务,服务与服务之间也通过ESB来相互调用,以此降低系统的耦合程度。
12,流控网关
在软负载层,可以引入一些流控框架,做流控网关,例如基于openresty框架的Nginx+lua实现的网关应用,来进行限流、流量整形、熔断降级、系统负载保护、热点防护等等
13,容器化
容器化能够快速的弹性扩缩容,能够进行方便的版本更新和回退,演进到这一步,一个基本的高可用高并发的架构就已经成型了
14,云化
如果想更进一步,系统可部署到公有云上,利用公有云的海量机器资源,解决动态硬件资源的问题,这也是未来系统演进的方向,所以现在很多公司都在提上云战略。
五,监控告警体系
1,监控指标和目标(指标实例体系)
2,精准告警
3,预案自动处理
4,故障主动探测
六,部署发布体系
如何降低部署发布对现网业务的影响?是保证业务连续性的重要问题。
部署发布前:
应该通过完备的测试流程,功能上线前,需要经历功能测试,性能测试,回归测试,生产验证等一些列测试流程,保证功能对业务不会造成影响以及功能本身的正确性。
部署发布中:
建议采用了滚动式发布,将上线对业务的影响降到最低,而且可以通过这种方式,响应一些需要实时上线的紧急需求。
部署发布后:
应该有完备的回退机制,能够保证在出现问题时,能够迅速的回退。让开发参与能开的on-call轮值工作,有清晰的问题升级流程和应急响应的预案,这也是sre思想的一些具体实践。
本文是自我的一些简单总结,匆匆成文,多有纰漏,生产现网的实际问题其实更为复杂,项目的管控和架构的演进也是一门庞大的学问,需要我慢慢摸索,后续我会不断更新和优化此文,与君共勉!