架构本质
一个软件系统随着功能越来越多,调用量急剧增长,整个系统逐渐碎片化,越来越无序,最 终无法维护和扩展,所以系统在一段时间的野蛮生长后,也需要及时干预,避免越来越无序。 架构的本质就是对系统进行有序化重构,使系统不断进化 那架构是如何实现无序到有序的呢? 基本的手段就是分和合,先把系统打散,然后重新组合。 分的过程是把系统拆分为各个子系统 / 模块 / 组件,拆的时候,首先要解决每个组件的定 位问题,然后才能划分彼此的边界,实现合理的拆分。合就是根据最终要求,把各个分离的 组件有机整合在一起,相对来说,第一步的拆分更难。 拆分的结果使开发人员能够做到业务聚焦、技能聚焦,实现开发敏捷,合的结果是系统变得 柔性,可以因需而变,实现业务敏捷
架构的分类
架构一般可分业务架构、应用架构、技术架构
1. 业务架构从概念层面帮助开发人员更好的理解系统,比如业务流程、业务模块、输入输出、 业务域
2. 应用架构从逻辑层面帮助开发落地系统,如数据交互关系、应用形式、交互方式,是的整 个系统逻辑上更容易理解,步入大家熟知的 SOA 就属于应用架构的范畴
3. 技术架构主要解决技术平台选型、如操作系统、中间件、设备、多机房、水平扩展、高可 用等问题 需要注意的是,系统或者架构首先都是为人服务的,系统的有序度高,用用逻辑合理,业务 概念清晰是第一位。现在大家讨论更多的是技术架构,如高并发设计,分布式事务处理等, 只是因为这个不需要业务上下文背景,比较好相互沟通。具体架构设计时,首先要关注业务 架构和应用架构,这个架构新手要特别注意。
网站演进
为什么这么分呢?
从计算机本身的角度来考虑的话,一个请求的访问到处理最终到返回,性 能瓶颈只会是:CPU、文件 IO、网络 IO、内存、等因素。而一台计算机中这些纬度是有性 能瓶颈的,如果某个资源消耗过多,通常会造成系统的响应速度较慢,所以增加一台机器, 使得数据库的 IO 和 CPU 资源独占一台机器从而增加性能。 这个地方插入一点题外话,就是简单说一下各个资源的消耗原因。 CPU/IO/内存:
1. 主要是上下文的切换,因为每个 CPU 核心在同一时刻只能执行一个线程,而 CPU 的调 度有几种方式,比如抢占式和轮询等,以抢占式为例,每个线程会分配一定的执行时间, 当达到执行时间、线程中有 IO 阻塞或者有高优先级的线程要执行时。CPU 会切换执行其 他线程。而在切换的过程中,需要存储当前线程的执行状态并恢复要执行的线程状态,这 个过程就是上下文切换。比如 IO、锁等待等场景下也会触发上下文切换,当上下文切换 过多时会造成内核占用比较多的 CPU。
2. 文件 IO,比如频繁的日志写入,磁盘本身的处理速度较慢、都会造成 IO 性能问题
3. 网络 IO,带宽不够
4. 内存,包括内存溢出、内存泄漏、内存不足 实际上不管是应用层的调优也好,还是硬件的升级也好。其实无非就是这几个因素的调整。
引入负载均衡
负载均衡算法
轮询(Round Robin)法 将请求按顺序轮流分配到后台服务器上,均衡的对待每一台服务器,而不关心服务器实际的 连接数和当前的系统负载
缺点:当集群中服务器硬件配置不同、性能差别大时,无法区别对待
随机法 通过系统随机函数,根据后台服务器列表的大小值来随机选取其中一台进行访问。随着调用 量的增大,其实际效果越来越接近于平均分配流量到后台的每一台服务器,也就是轮询法的 效果
优点:简单使用,不需要额外的配置和算法。
缺点:随机数的特点是在数据量大到一定量时才能保证均衡,所以如果请求量有限的话,可 能会达不到均衡负载的要求。
源地址哈希法 根据服务消费者请求客户端的 IP 地址,通过哈希函数计算得到一个哈希值,将这个哈希值和 服务器列表的大小进行取模运算,得到的结果便是要访问的服务器地址的序号。采用源地址 哈希法进行负载均衡,相同的 IP 客户端,如果服务器列表不变,将映射到同一个后台服务器 进行访问。
加权轮询(Weight Round Robin)法 不同的后台服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不一 样。跟配置高、负载低的机器分配更高的权重,使其能处理更多的请求,而配置低、负载高 的机器,则给其分配较低的权重,降低其系统负载,加权轮询很好的处理了这一问题,并将 请求按照顺序且根据权重分配给后端
最小连接数法 前面几种方式都是通过对请求次数的合理分配最大可能提高服务器的利用率,但是实际上, 请求次数的均衡并不能代表负载的均衡。所以,引入了最小连接数法。它正是根据后端服务 器当前的连接情况,动态的选取其中当前积压连接数最少的一台服务器来处理当前请求,尽 可能的提高后台服务器利用率,将负载合理的分流到每一台服务器。
session问题
解决:
1.server数据同步
缺点:网络带宽增加,很多session的话会占用内存,集群数多不适合
2.session集中存储,可以是数据库,redis,gemfire
缺:引入网络操作,有时延和不稳定。集中存储机器有问题会影响
3.session维护在客户端,cookie
缺:安全性,虽然可以加密
读写分离
搜索引擎
缓存和分布式存储(redis,mongoDB等)
- 文件系统:对于图片、大文本采用分布式文件系统实现文件存储。比如淘宝的 TFS、google 的 GFS。还有开源的 HDFS
- nosql
- 数据缓存
- 页面缓存
数据库的垂直和水平拆分
垂直:专库专用,数据垂直拆分 垂直拆分的意思是把数据库中不同的业务数据拆分到不同的数据库中,那么根据我们推演的例子, 把用户、交易、商品的数据分开
水平:数据水平拆分就是把同一个表的数据拆分到两个数据 库中,产生数据水平拆分的原因是某个业务的数据表的数据量或者更新量达到了单个数据库 的瓶颈,这个时候就可以把表拆到两个或者多个数据库中。
数据水平拆分与读写分离的区别是,读写分离解决的是读压力大的问题,对于数据量大或者 更新量大的情况并不起作用。
数据水平拆分与数据垂直拆分的区别是,垂直拆分是把不同的表拆分到不同的数据库,而水 平拆分是把同一个表拆分到不同的数据库中。
我们可以进一步把用户表拆分到两个数据库中,它们拥有结构一模一样的用户表,而且每个 库中的用户表都只涵盖了一部分的用户,两个数据库的用户和在一起就相当于没有拆分之前 的用户表
影响:
- sql路由,根据一个条件去哪个数据库
- 主键不能自增,需要全局id
问题:
查询需要跨2个数据库获取,如果数据量需要分页,很难处理
解决:
服务化
而服务中心不仅把一些可以共用的代码集中管理,而且还使得这些代码变得更好维护。 服务化的方式会带来很多好处,首先,从结构上来看,系统架构更加清晰了,比原本的架构 更加立体。从稳定性上来看,一些散落在多个应用系统中的代码变成了服务并且由专门的团 队进行统一维护,一方面可以提高代码的质量,另一方面由于基础核心模块相对稳定,修改 和发布的频次相对于业务系统来说会少很多,这也会提高整个架构的稳定性。最后,更加底 层的资源由服务层统一管理,结构更加清晰,对于团队开发效率来说有比较大的提高 服务化的方式,对于研发也会有很大的影响,以前的开发模式是几个大团队负责几个大应用, 随着服务化的落地,我们的应用数量会飞速增长,系统内部的依赖关系也会变的错综复杂, 同时团队也进行了拆分,每个小团队专注于某个具体的服务或者应用上,迭代效率也会更高
小总