北哥在前文陆续总结了程序员成长所具有的核心能力,以及Java程序员成长过程当中应学习的基础知识。在一个Java程序员工做三、5年以后,已经能够承担起大部分的核心开发工做,成长为团队中的高级开发人员。大部分工做中遇到的问题都已经能够自行解决。这个阶段不少同窗会面临着新的成长困惑,到底接下来本身还须要在哪些方面继续提高?如何可以成长为团队里面的架构师呢?前端
市面上有不少分析和拆解架构师能力的书籍,例如《聊聊架构》《亿级流量网站架构核心技术》《大型网站技术架构:核心原理与案例分析》等,书中有一些相关的实战和理论知识分享。这些书籍若是有时间推荐你们去读一读。nginx
今天北哥结合本身工做中的经验,也来浅谈一下如何作应用系统架构设计。程序员
须要说明的是,架构师自己要求的是综合能力,架构也分为业务架构、应用系统架构、技术架构、数据架构等多个维度多个细分领域,但今天分享的关于架构的相关内容,更多仍是侧重在服务端的应用系统架构。sql
做为一个架构师,在作应用系统架构时,最好逐步沉淀本身的一套指导思想,指导思想用于在作架构设计过程当中遇到困惑或遇事不决时的一个指引。我我的总结下来的经验有如下三点数据库
架构是一个复杂的工做,既要考虑当下的需求,还要关注将来可能的变化;既要考虑的足够全面,还要简单容易实现;既要衡量实现成本,还要关注落地的效率。这些无不意味着在作架构时需作好平衡,学会取舍。后端
一个好的架构,必定是通过长期迭代演进而来的。在作架构设计时,受限于当前已经明确的需求,每每没法对将来考虑的那么全面。即便在作架构设计时已经考虑到了方方面面,系统上线后也会遇到一些新的未知问题,而且随着需求的不断迭代,又会引入新的变化和挑战,所以持续的对架构作优化和迭代演进,是必需要重视的。设计模式
没有毫无瑕疵完美的架构,也没有一成不变适合全部业务的架构,只有适合当前业务和产品需求的架构。咱们能够借鉴、吸取别人的经验和实践总结,但最合适的架构必定是结合业务的实际需求设计和演变出来的。脱离业务需求设计的架构必定会在开发中遇到新的问题。浏览器
在作应用系统架构设计时,应遵循一些普适的架构设计目标。这些目标包括缓存
接下来从业务需求分析开始,到最终系统上线运营,按照不一样阶段须要关注的知识和内容,来讲明整个应用系统架构设计过程须要考虑的问题。服务器
正如前文所述,系统架构应该是聚焦业务需求的,业务需求分析,是作系统架构设计的必要前置。这里简述下我在需求分析阶段工做的大体思路。正常状况下,进入到架构师层面的需求,都通过了业务人员和产品人员至少一轮的讨论沟通,或已经有基本的业务和产品需求雏形,或已经产出业务的MRD(业务需求说明书)或产品的PRD(产品需求说明书)。这时架构师进入后须要再和业务及产品同窗进行充分的讨论沟通,明确和产出如下几点信息:
在需求分析阶段完成后,就进入到系统架构设计阶段。
在系统架构设计阶段,我通常会首先作数据建模。根据业务模型和功能列表,已经能够分清楚大概的系统、模块和功能,由此数据库的概念模型基本可以肯定下来。经过数据库的概念模型设计,结合需求分析阶段产出的功能需求列表,整个系统的详细需求基本能够被印在大脑中了。同时通过概念模型的设计,不一样数据实体之间的关系已经相对清晰,服务或领域的划分也具有初步的雏形了。完成数据库的概念模型后,开始进行详细的系统架构设计和技术选型阶段。
在系统架构设计阶段,我会按照分层架构设计的思想,逐步作细化展开。在目前的主流技术方案中,先后端分离基本上是默认的标准,核心缘由一方面是先后端技术演进快速发展,技术专业人员分工更明确;另外一方面当前的产品开始移动化,先后端一体的架构没法支撑当前移动端特别是App类应用的开发,先后端分离也成为不得不为之的举措。
按照分层架构设计的思想,将整个架构分为前端接入层、服务层、数据访问层、数据存储层。在部分高并发的系统中,还会有缓存相关技术贯穿在整个架构层级之间。
前端接入层
首先,在前端接入层,主要解决用户流量从终端发起请求到被应用服务器接收以前这一段的问题。
在前端接入层,核心须要解决终端展示时的响应速度和稳定性。
在传统的PC互联网场景下,大部分产品和应用以浏览器为终端,经过网页的方式展示在用户面前,如京东、淘宝等电商类的网页版。在终端层面,由于用户请求量巨大,会借助页面静态化、CDN等方式,提高页面加载速度。在请求层面,为了提高稳定性和应对更大的流量挑战,在流量进入到应用服务器前,会经过使用DNS、软硬件负载的方式进行流量分流,将请求打到不一样的应用服务器上。这里会使用到的硬件负载有F5等,而软件负载主要经过nginx实现,早期还有LVS、Haproxy的方案等。
服务层
说完接入层,再来看服务层。服务是应用系统的核心,承担着业务和产品核心需求和逻辑的实现。
在服务层,须要解决的重点问题问题是,服务是否能够灵活快速的水平扩展,以应对将来系统可能的访问量剧增。
为解决这个问题,须要对是否进行分布式架构设计进行权衡。分布式架构设计的核心是经过对服务的解耦,来解决应用的水平扩展问题,下降单服务单机器的压力。若是系统所须要承担的流量在可预期的将来会有较大的增加,分布式架构设计就是有必要的。而若是系统流量在很长一段时间内都相对有限且平稳,则分布式架构就显得没那么必要。这里即须要作好平衡和取舍。
分布式架构虽然可以带来服务水平扩展的便捷性,以应对将来可能的系统流量大幅增加,但须要付出较大的系统维护成本。若是选择暂时不采用分布式架构,服务层也一样能够在工程层面,按照服务的接口层、服务的逻辑层和服务的数据层进行划分模块和子模块,而后在代码构建打包时集成到一个单体应用做为一个jar或war包一块儿发布。根据我以前的经验,在一个业务和产品的早期阶段,采用模块化划分的单体应用方式的架构,能够快速完成产品MVP版本的上线试错,当业务发展到必定规模后再启动分布式架构的服务化改造,也不失为一个较好的选择。
不管在一开始就选定分布式架构方案,仍是在后期作分布式架构的服务化改造时,都会面临着另一个选型问题:究竟是采用分布式服务仍是微服务方式来构建应用。
分布式服务和微服务是在分布式架构演进过程当中产生的不一样概念,按照个人理解,分布式服务关注的重点是分布式,重点解决服务的压力负载分担,而微服务重点关注的是服务的单元颗粒度大小,更关注服务的原子性、独立性。两者都是为了解耦合,但在解耦合的颗粒度上稍有不一样。具体的选择也须要根据应用系统的规模、领域划分等综合考量。
落地到分布式服务的架构技术选型上,有以传统的RPC框架为主导的技术体系,和以Spring Boot微服务框架为基础的Spring Cloud全家桶。
传统的RPC框架以早期阿里开源的Dubbo框架为表明,核心的实现是基于动态代理+反射的方式来实现服务之间的接口通讯,服务和服务之间的底层调用是基于socket来实现数据传输交互的。而Spring Cloud全家桶,核心是基于Http协议实现的一套微服务框架,服务和服务之间的调用是经过Http接口实现交互的的。相比Spring Cloud,RPC框架通常具备可自定义数据结构、网络传输速度快、效率高等特色,而Spring Cloud由于是基于Http协议进行网络传输,消息的包体大小受Http协议限制作了封装显得相对臃肿,在网络传输时效率相对低一些,但Spring Cloud因有一整套组件和生态的支撑,所以在不作过多性能苛求的状况下,也是目前能够快速采用的方案之一。另一种将两者结合的方案,利用Spring Cloud设计和实现接口的接入网关,再经过网关将请求转发到RPC服务中,则是目前一些大型应用广泛采用的方案。
在使用Spring Cloud或RPC框架的过程当中,另一个须要关注的问题是服务之间的耦合问题。虽然分布式服务或微服务自己就是为了解决耦合问题,但应用和应用、服务与服务之间的依赖关系并不由于使用Spring Cloud或RPC框架就消失了,在一些场景下,适度的服务之间的依赖是容许且必要的,但过分的服务之间依赖,甚至发展成服务与服务之间相互依赖,就是须要避免的一种状况了。经过消息中间件,将本来有上下游关系的依赖,经过消息解耦,从而让服务和服务之间避免强依赖,是其中的一个解决方案。经常使用的消息中间件有RabbitMQ、RocketMQ、Kafka等。
数据访问层
说完服务层,再来看数据访问层。全部的应用都离不开数据,数据是一个系统的灵魂所在。数据访问层主要用于完成服务层和数据存储层之间数据的交互。由于数据存储方式的多样性,数据访问层一个重要功能是实现对不一样数据存储方式的封装,尽可能作到对服务层屏蔽具体的数据存储细节。另外一个数据访问层的重要做用,是解决数据存储场景下的资源管理问题,包括链接池资源、分库分表、读写分离等。具体是否须要作分库分表、读写分离等,须要根据应用的实际数据量大小、选择的数据存储方式等作综合考量。
数据存储层
最后,再来考虑数据存储层的搭建和选型。
数据存储层是用于将具体应用产生的数据持久化。不一样的数据存储方式适用的业务场景也有很大不一样。如对事务要比较高,通常采用关系型数据库如Mysql、Oracle等;对数据结构和表结构扩展性要求较灵活的能够采用NoSQL数据库如MongoDB、CouchDB等;若是须要存储的数据量很是庞大,能够选择目前基于hdfs的存储方案如Hbase、Hive等;还会有对文件、图片等有存储需求的,能够采用分布式文件存储或云存储的方式等。数据存储的方案自己没有好坏之分,具体仍是要分析业务的实际需求来作平衡和选择。
关于缓存
除了以上所述的几个层级,在大部分互联网应用中,当系统访问用户量达到必定量级,或QPS较高的场景下,还会经过增长缓存来下降系统和接口的响应时间,提高系统的性能。经常使用的缓存框架有Redis、Memcache等。在架构设计阶段,咱们把整个系统按照分层的思想作拆解说明,根据业务的实际需求,对各层中采用的技术和方案作平衡和取舍。架构设计阶段完成并不意味着整个应用系统架构的完成。接下来须要将架构设计落地到代码中。
在架构设计方案完成后,对于开发工程师来讲,已经能够根据架构设计方案来指导进行详细需求设计和编码。对于架构师来讲,在这个阶段须要重点关注的有如下几点:
工程结构:良好的工程结构,能够大幅下降后续代码的维护成本和大团队的协做成本。每一层的工程结构也会有所侧重和不一样,咱们能够在平时沉淀适合本身企业的工程结构脚手架,在须要时一键建立,既能提高效率,还能够统一工程模板。
设计模式:针对复杂的需求,架构师须要重点关注,将不一样设计模式组合、扩展应用到代码设计中,提高代码的可扩展性和可维护性。
代码模板:代码模板能够统一代码风格,提高代码的可读性和可维护性。
代码检查:经过对代码的检查,发现不合理的代码组织和设计、潜在的代码隐患等等。也能够借助一些第三方插件或工具如PMD、Findbugs等辅助作检查。
一个好的架构,必定是须要经历线上系统的检验的。在测试人员完成质量测试后,须要对应用系统作上线发布,进入到上线运营阶段。
在上线运营阶段,架构师核心职责是作好各项监控和告警指标的设定。
在监控层面,首选须要对应用系统相关的各项性能指标作监控。经过一些开源或企业自研的监控工具,须要对应用系统所采用的物理资源如磁盘、内存、CPU、网络等进行监控;须要对数据存储组件如数据库的慢查询、I/O、库大小等进行监控;对中间件如RabbitMQ、Redis等读写、容量等进行监控;对应用系统性能如接口响应时长、95线、99线的监控等等。
另一个重要的监控对象是业务指标的监控,如一段时间内的登录用户量、短信发送量、订单下单量、订单支付量等等。业务指标的监控每每能反映出一些系统层面的异常,引导去追究引发业务指标异常的根本缘由,从而提高系统的可靠性和稳定性。
具体创建哪些监控指标须要根据不一样的监控对象进行合理的设定。
创建完监控指标后,还须要创建告警体系,将异常的指标及时告警通知出来。通常的监控系统都会有提供相似短信、钉钉等告警方式的接入。
最后,在上线运营阶段还须要收集和关注系统的日志,及时排查修复异常,保障系统的稳健运行。
以上是从一个业务的需求阶段开始,到整个业务的应用系统上线运营,做为一个架构师须要关注的方方面面。
固然,其中的每个架构点和技术方案,展开来看都是一个很大的课题。当你具有架构的全局思惟以后,接下来就能够深刻到不一样领域专研,并在工做中不断实践和试错,最终完成自身技能的进阶。
自计算机诞生以来,各项软硬件技术即在不断迭代更新,催生着软件架构的不断升级换代。而随着大数据云计算5G时代的带领,新的业务场景如音视频、直播、物联网等等业务挑战也会随之而来,咱们对架构的追求也永无止境。
但愿你我均可以在持续的架构演进中,不断学习,持续进步。
相关阅读
·END·