大型网站架构学习笔记
前言
最近一直在拜读两本书:
1、李智慧老师的《大型网站技术架构 核心原理与案例分析》
2、曾宪杰老师的《大型网站系统与Java中间件实践》
看了并结合自己目前的工作进行了思考,感觉获益匪浅、受益良多,自己对大型网站的理解又有了不少的加深,下面分享一下自己的学习笔记。
学习笔记
1、大型网站架构的发展史(红字就是每一步发展历程的关键)
(1)从一个小网站发展起来,一台服务器,应用程序、数据库、文件等所有资源都在一台服务器上
(2)网站业务的发展,一台服务器逐渐不能满足需求,因此要将应用和数据分离,应用和数据分离后使用三台服务器:应用服务器、文件服务器和数据库服务器
(3)网站进一步发展,数据库压力太大导致访问延迟,因此使用缓存该改善网站性能(记住,使用缓存是改善网站性能的第一步),网站使用的缓存分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存
(4)使用缓存,数据库访问压力得到有效缓解,但是在网站访问高峰期应用服务器还是成为了整个网站的瓶颈。这种时候要理解,不要企图去更换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求,因此可以通过增加服务器的方式改善负载压力,再通过负载均衡调度服务器,将来自用户浏览器的访问请求分发到应用服务器集群中的某台服务器上
(5)虽然使用缓存可以使大部分数据不走数据库,但是缓存没有命中、缓存过期的数据还是会走数据库,网站达到一定规模之后,数据库读写压力还是会很大,成为网站的瓶颈。此时可以使用数据库读写分离来改善数据库负载压力,应用服务器写数据走写库,应用服务器读数据走读库,目前大部分主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上
(6)随着网站业务继续发展,用户规模不断增大,由于中国复杂的网络环境,不同地区用户访问网站时,速度差别也极大。因此可以使用反向代理和CDN,一方面加快用户访问速度,另一方面减轻后端服务器的负载压力,因为反向代理和CDN的基本原理都是缓存
(7)数据库经过读写分离后,由一台服务器拆分为两台服务器,但还是不能满足网站业务量的需求,因此可以使用分布式数据库,主要拆分手段是业务分库,将不同的业务数据部署在不同的物理服务器上
(8)大型网站为了应对日益复杂的业务场景,可以使用分而治之的手段将整个网站的业务拆分成不同的应用,每个应用独立部署,可以通过超级链建立关系,也可以通过消息队列进行数据分发
大型网站发展到这里,基本上大多数的技术问题都得以解决
2、高性能网站的关键:控制住并发的量。只要能做到这点,很多棘手的数据问题也就不是什么问题了
3、不要企图通过技术解决所有问题,业务的问题也可以通过业务手段去解决
比如12306建立之初,0点售票,网站一下子要承受几千万的访问量,直接导致12306这个网站崩溃,各路专业人士和分专业人士众说纷纭、出谋划策。但这仅仅通过技术能解决问题吗?所以,针对这个需求,12306不仅要改善它的技术架构,也要调整它的业务架构,不要0点售票,在售票方式上引入排队机制、整点售票改为分时段售票,并发量控制住了,整个网站的性能就改善了
4、计算机软件发展的 一个重要目标和驱动力是降低软件的耦合性,事物之间关系越少,就越少彼此影响,越可以独立发展
5、异步架构是典型的生产者消费者模式
6、使用异步队列有几个好处
(1)提高系统的可用性
(2)加快网站的访问速度
(3)消除并发访问高峰
7、网站伸缩性就是指通过不断向集群中加入服务器的手段来缓解不断上升的用户并发访问压力和不断增长的数据存储需求
8、衡量架构伸缩性的指标
(1)是否可用多台服务器架构集群
(2)是否容易向服务器中添加新的服务器
(3)加入的服务器是否可以提供和原服务器无差别的服务
(4)集群中容纳的总服务器是否有限制
9、反应系统忙闲的重要指标Load
System Load也称为Load,即系统负载,指当前正在被CPU执行和等待被CPU执行的线程数之和,,是反映系统忙闲程度的重要指标。多核CPU下,完美情况应该是所有CPU都在用,没有线程等待处理。Load值低于CPU数目,表示CPU有空闲,资源存在浪费;Load值高于CPU数目,表示进程在等待CPU调度,资源存在不足
10、浏览器访问优化手段
(1)减少http请求,合并CSS、JS、图片,不要发起多次http请求去拿这些数据
(2)使用浏览器缓存,存储静态资源,Cache-Control、Expires、Pragma、Last_Modified都是和缓存的HTTP HEADER
(3)启用压缩,有效减低通信传输的数据量
(4)CSS放在上面、JS放在下面,因为JS下载会立即执行,可能阻塞页面加载速度
(5)减少Cookie传输
11、缓存使用的几点细节
(1)频繁修改的数据不要写缓存,一般读写比例至少2:1以上才会做缓存,即一次写入至少有两次以上的读取,像新浪微博这种,热门微博,一次写入可能会被读取数百万次,那是大大地合算
(2)如果访问没有热点,大部分数据的访问没有集中在小部分数据上,那么做缓存就没有意义,因为缓存有失效机制,大部分数据还没有被再次访问就被挤出缓存了
(3)容忍一定时间的数据不一致,除非数据更新时立刻通知缓存,不过这也会带来开销与事物一致性的问题
(4)使用分布式缓存集群以提高缓存可用性
(5)新启动的缓存没有任何数据,在重建缓存的过程中,系统性能与数据库负载都不太好,因此要根据项目、根据业务,将一部分数据在启动时就加载好,这就是缓存预热
(6)对缓存做无效参数并设置失效时间,避免不恰当的业务或恶意攻击频繁调用接口查询数据库,一旦某一个Key值数据库里面查不到数据就进入无效缓存,一段时间内再次访问这个Key值无数据返回
12、消息队列具有很好的削峰作用(前面提过),不过注意需要适当修改业务流程进行配合
通过异步处理,将短时间高并发产生的事物消息存储在消息队列中,从而可以削平高峰期的并发事物。不过要注意点,由于数据写入消息队列后立即返回给用户,数据在后续的业务校验、写数据库等操作可能失败,因此在使用消息队列进行业务异步处理后,,需要适当修改业务流程进行配合,如订单提交之后,订单数据写入消息队列,不能立即返回给用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单的,甚至商品出库后,再通过电子邮件或者SMS消息通知用户订单成功,避免交易纠纷
13、CDN和反向代理的基本原理都是缓存,区别在于CDN部署在网络提供商的机房,使用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据;反向代理则部署在网站的中心机房,当用户请求到达中心机房时,首先访问的是反向代理服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户。使用CDN和反向代理的目的是一样的:
(1)尽早返回速度给用户,加快用户访问网站的速度
(2)减轻后端服务器的负载压力
14、应用服务器集群的Session管理
单机环境下,Session可由部署在服务器上的Web容器管理,在使用负载均衡的集群环境中,由于负载均衡服务器可能会将请求分发到集群任何一台应用服务器上,所以保证每次请求依然能够获得正确的Session比单机时要复杂得多。集群环境下,Session管理有以下手段:
1、Session复制
在集群中的几台服务器之间同步Session对象,使得每台服务器上都保存着所有用户的Session信息,这样任何一台机器宕机都不会导致Session数据的丢失,而服务器使用Session时,也只需要从本机获取即可。
这种方案虽然简单,从本机读取Session信息也很快,但只能使用在集群规模比较小的情况下。当集群规模较大时,集群服务器之间需要大量的通信进行Session复制,占用服务器和网络的大量资源,系统不堪负担。而且由于所有用户的Session在每台服务器都有备份,在大量用户访问的情况下,甚至会出现服务器内存不够Session使用的情况。
大型网站的核心应用集群就是数千台服务器,同时在线用户达到数千万,并不适用这种方案。
2、Session绑定
Session绑定可以利用负载均衡的原地址Hash算法,负载均衡服务器总是将来源于同一IP的请求分发到同一台服务器。这样在整个会话期间,用户所有请求都在同一台服务器上处理,即Session绑定在某台特定服务器上,保证Session总能在这台服务器上获取,这种方法又被称为会话粘滞。
但是Session绑定的方案不符合对系统高可用的需求,因为一旦某台服务器宕机,那么该机器上的Session也就不复存在了,用户请求切换到其他机器后因为没有Session而无法完成业务处理。因此虽然大部分负载均衡服务器都提供原地址负载均衡算法,但很少有网站利用这个算法进行Session管理
3、利用Cookie记录Session
早期的企业应用使用C/S架构,一种管理Session的方式是将Session记录在客户端,每次请求服务器的时候,将Session放在请求中发送给服务器,服务器处理完请求后再将修改过的Session响应给客户端。网站没有客户端,但是可以利用浏览器支持的Cookie记录Session。
利用Cookie记录Session也有一些缺点:
(1)受到Cookie大小限制,能记录的信息有限
(2)每次请求和响应都携带Cookie,影响性能
(3)如果用户关闭Cookie,访问就会不正常
不过因为Cookie简单易用且可用性高,支持应用服务器的线性伸缩,而大部分应用需要记录的Session信息有比较小,因此事实上,许多网站或多 或少都会使用Cookie记录Session
4、Session服务器
利用独立部署的Session服务器(集群)统一管理Session,应用服务器每次读写Session时,都访问Session服务器。
这种解决方案事实上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的Session服务器,然后针对这两种服务器的不同特性分别设计其架构。
对于有状态的Session服务器,一种比较简单的方法是利用分布式缓存、数据库等,在这些产品的基础上进行包装,使其符合Session的存储和访问要求;如果业务场景对Session管理有比较高的要求,那么就要利用Session服务集成单点登录(SSO)、用户服务等功能,则需要开发专门的Session服务管理平台。
我不能保证写的每个地方都是对的,但是至少能保证不复制、不黏贴,保证每一句话、每一行代码都经过了认真的推敲、仔细的斟酌。每一篇文章的背后,希望都能看到自己对于技术、对于生活的态度。
我相信乔布斯说的,只有那些疯狂到认为自己可以改变世界的人才能真正地改变世界。面对压力,我可以挑灯夜战、不眠不休;面对困难,我愿意迎难而上、永不退缩。
其实我想说的是,我只是一个程序员,这就是我现在纯粹人生的全部。
==================================================================================