李智慧《大型网站技术架构》读书笔记

第一章《大型网站架构演化》

最初的网站架构可以说没有架构,具体表现为应用程序、文件、数据库部署在同一台服务器中。常见如LAMP(linux+Apache+MySQL+PHP)

演化历程有:

  1. 应用服务和数据服务分离(应用服务器、文件服务器、数据库服务器三分天下,各自选用性能更为适合的硬件服务器)
  2. 使用缓存改善网站性能(80%的数据访问集中在20%的数据上,缓存这少部分数据可以大幅度提升网站响应速度,缓存分本地缓存和远程缓存,本地缓存即应用服务器缓存,远程缓存就是缓存在专门的分布式缓存服务器上的缓存,远程缓存可以部署集群,理论上不受容量限制)
  3. 使用应用服务器集群改善网站的并发处理能力(应用服务器集群设计提升网站伸缩性,可以通过增加集群服务器数量来提升网站性能)
  4. 数据库读写分离(利用数据库热备功能,配置主从服务器,主服务器执行写操作,然后数据同步至从服务器,从服务器执行读操作)
  5. 使用反向代理和CDN加速网站响应(反向代理和CDN的基本原理都是缓存,区别在于CDN是部署在网络提供商的机房,用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据,这个参考京东分布在全国各地的货仓就近发货是一个道理,而反向代理部署在网站的中心机房,当访问请求到达中心机房后,首先访问的服务器是反向代理服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户)
  6. 使用分布式文件系统和分布式数据库系统(分布式数据库是网站拆分的最后手段,分表、业务分库)
  7. 使用NoSQL和搜索引擎
  8. 业务拆分(将一个网站拆分成不同的应用,比如首页、商铺、订单等每个应用独立部署维护,可以通过超链接、消息队列进行据分发)
  9. 分布式服务(拆分出公用业务服务,比如用户管理、商品管理等部署公共服务服务器,应用服务器只需要管理用户界面,通过分布式服务调用公共服务完成具体业务操作,这点类似于曾经的CTAIS系统在weblogic上做的双层部署,web集群与app集群分离,经常说到的2个web连接4个app应该就是这种情况)

历经上述演化之后,目前服务器架构如下:(按照访问顺序进行编号)

  1. CDN服务器
  2. 反向代理服务器
  3. 负载均衡服务器
  4. 应用服务器A
  5. 消息队列服务器(连接不同的应用服务器传递消息)
  6. 应用服务器B
  7. 分布式服务服务器(1应用程序、2本地缓存、3统一数据访问模块)
  8. 由7.3统一数据访问模块控制访问如下5种数据渠道
  9. 分布式缓存服务器
  10. 分布式文件服务器
  11. 分布式数据库服务器
  12. NoSQL服务器
  13. 搜索引擎服务器

第二章《大型网站架构模式》

  1. 分层(将系统在横向维度上切分成几个部分,每个部分负责一部分相对比较单一的职责:应用层——负责具体业务和视图展示、服务层——为应用层提供服务支持、数据层——提供数据存储访问服务)
  2. 分割(分割是在纵向方面对软件进行切分,将不同的功能和服务分割开来,包装成高内聚低耦合的模块单元)
  3. 分布式(分层和分割的一个主要目的就是为了切分后的模块便于分布式部署,即将不同的模块部署在不同的服务器上,通过远程调用协同工作。分布式应用和服务——应用拆分和服务拆分、分布式静态资源——JS、CSS独立分布式部署动静分离、分布式数据和存储——数据库分布式部署和NoSQL、分布式计算——Hadoop等)
  4. 集群(提高性能、伸缩性、可用性)
  5. 缓存(CDN、反向代理、本地缓存、分布式缓存,缓存可以提高数据访问速度还可以减轻后端应用和数据存储的负载压力,缓存的两个提前条件是:1数据访问热点不均衡即某些热点数据会被更频繁的访问2数据在某个时间段内有效不会太快过期)
  6. 异步(异步架构是典型的生产消费者模式,多个服务器可以通过分布式消息队列实现异步,生产者提交访问请求后将消息放入消息队列中即返回用户界面,请求存储在消息队列中等待被消费者即被调用者读取并处理,减少了应用之间调用的依赖性)
  7. 冗余(访问量和负载很小的服务器也要至少部署两台做集群,通过冗余实现高可用,避免宕机)
  8. 自动化
  9. 安全

第三章《大型网站核心架构要素》

  1. 性能
  2. 可用性(主要手段——冗余,应用部署在多台服务器上同时提供服务,数据存储在多台服务器上互相备份)
  3. 伸缩性
  4. 扩展性
  5. 安全性

性能优化:

  • 浏览器端可以通过浏览器缓存、使用页面压缩、合理布局页面、减少Cookie传输等手段改善性能
  • 使用CDN将网站静态内容分发至离用户最近的网络服务商机房,是用户可以通过最短访问路径获取数据
  • 在网站机房部署反向代理服务器,缓存热点文件,加快请求响应速度,减轻应用服务器负载压力
  • 在应用服务器,可以使用服务器本地缓存和分布式缓存,通过缓存在内存中的热点数据处理用户请求,加快请求处理过程,减轻数据库负载压力
  • 也可以通过异步操作将用户请求发送至消息队列等待后续任务处理,而当前请求直接返回相应给用户
  • 在网站有很多用户高并发请求的情况下,可以将多台应用服务器组成一个集群共同对外服务,提高整体处理能力,改善性能
  • 代码层面,也可以通过使用多线程、改善内存管理等手段优化性能
  • 数据库服务器端,索引、缓存、SQL优化等性能优化手段都已经比较成熟。而方兴未艾的NoSQL数据库通过优化数据模型、存储结构、伸缩特性等手段在性能方面的优势也日趋明显

伸缩性:

衡量架构伸缩性的主要标准就是

  1. 是否可以使用多台服务器集群
  2. 是否容易向集群中添加新的服务器
  3. 加入新的服务器后是否可以提供和原来的服务器无差别的服务
  4. 集群中可容纳的总的服务器数量是否有限制

集群添加服务器数量对不同集群的影响:

应用服务器集群:只要服务器上不保存数据,所有服务器都是对等的,通过使用合适的负载均衡设备就可以像集群中不断加入服务器。

缓存服务器集群:新加入的服务器可能会导致缓存路由失效,进而导致集群中大部分缓存数据都无法访问。虽然缓存的数据可以通过数据库重新加载,但是如果应用已经严重依赖缓存,可能会导致整个网站崩溃。需要改进缓存路由算法保证还承诺数据的可访问性。

数据库服务器集群:

        关系型数据库很难做到大规模集群的可伸缩性,因此关系数据库的集群伸缩性方案必须在数据库之外实现,通过路由分区等手段将部署有多个数据库的服务器组成一个集群。

        NoSQL产品为海量数据而生,集群伸缩性实现起来非常方便。

扩展性:

网站可扩展架构的主要手段是事件驱动架构和分布式服务。

  • 事件驱动架构:事件驱动架构在网站通常利用消息队列实现,将用户请求和同其他业务事件构造成消息发布至消息队列,消息的处理者作为消费者从消息队列中获取消息进行处理。通过这种方式将消息产生和消息处理分离开来,可以透明地增加新的消息生产者或者新的消息消费者任务。
  • 分布式服务:分布式服务则是将业务和可复用服务分离开来,可通过分布式服务框架调用。新增产品可以通过调用可复用的服务实现自身的业务逻辑,而对现有产品没有任何影响。

第四章《瞬时响应:网站的高性能架构》

性能测试方法:

  1. 性能测试:以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能预期。
  2. 负载测试:对系统不断地增加并发请求以增加系统压力,直到系统的某项或多项性能指标达到安全临界值,如某种资源已经呈现饱和状态,这时继续对系统施加压力,系统的处理能力不但不能提高,反而会下降。
  3. 压力测试:超过安全负载的情况下,对系统继续市价压力,直到系统崩溃或不能再处理任何请求,以此获得系统最大压力承受能力。
  4. 稳定性测试:被测试系统在特定硬件、软件、网络环境条件下,给系统加载一定业务压力,使系统运行一段较长时间,以此检测系统是否稳定。

总结:性能测试(满足性能目标即可),负载测试(测出最大处理能力),压力测试(压力过大性能下降直至系统崩溃)三种测试方案压力逐渐增大。

Web前端性能优化

浏览器访问优化

1.减少http请求

        HTTP协议是无状态的应用层协议,意味着每次HTTP请求都需要建立通信链路、进行数据传输,而在服务器端,每个HTTP都需要启动独立的线程去处理。这些通信和服务的开销都很昂贵,减少HTTP请求的数目可有效提高访问性能。

        减少HTTP的主要手段是合并CSS、合并javascript、合并图片,将浏览器一次访问需要的javascript、CSS合并成一个文件,这样浏览器就只需要一次请求。图片也可以合并,多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS偏移响应鼠标点击操作,构造不同的URL。

2.使用浏览器缓存

        对一个网站而言,CSS、javascript、Logo、图标这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次HTTP请求都需要的,如果将这些文件还存在浏览器中,可以极好地改善性能。通过设置HTTP头中Cache-Control和Expires的属性,可设定浏览器缓存,缓存时间可以是数天、甚至是几个月。

        在某些时候静态资源文件变化需要及时应用到客户端浏览器,这种情况,可通过改变文件名实现,即更新javascript文件并不是更新javascript文件内容,而是生产一个新的JS文件并更新HTML文件中的引用。

        更新较多静态资源时应该一个一个逐渐更新并有一定的时间间隔,以免用户浏览器突然大量缓存失效,集中更新缓存造成服务器负载剧增、网络堵塞的情况。

3.启用压缩

        在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。但是压缩会对服务器和浏览器产生一定压力,需要权衡通信宽带压力和服务器资源压力。

4.CSS放在页面最上面、javascript放在页面最下面

        浏览器会下载完全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS。javascript则相反,浏览器在加载javascript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此javascript最好放在页面最下面。但如果页面解析时就需要javascript,这时放到底部就不合适了。

5.减少Cookie传输

        一方面,cookie包含在每次请求和响应中,太大的cookie会严重影响数据传输,因此哪些数据需要写入cookie需要慎重考虑,尽量减少cookie中传输的数据量。另一方面,对于某些静态资源的访问,如CSS、javascript等,发送cookie没有意义,可以考虑静态iziyuanshiyong独立域名访问,避免请求静态资源时发送cookie,减少cookie传输的次数。

CDN加速

        此处不再赘述

反向代理

        传统代理服务器位于浏览器一侧,代理浏览器将HTTP请求发送至互联网上,而反向代理服务器位于网站机房一侧,代理网站Web服务器接收HTTP请求。

        和传统代理服务器可以保护浏览器安全一样,反向代理服务器也具有保护网站的作用,来自互联网的访问请求必须经过代理服务器,相当于在Web服务器和可能的网络攻击之间建立了一个屏障。

        除了安全功能,代理服务器也可以通过配置缓存功能加速Web请求。当用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上,这样当其他用户访问该静态内容的时候,就可以直接从反向代理服务器返回,加速Web请求响应速度,减轻Web服务器负载压力。事实上,有些网站会把动态内容也缓存在代理服务器上,当这些动态内容有变化时,通过内部通知机制通知反向代理缓存失效,反向代理会重新加载最新的动态内容再次缓存起来

应用服务器性能优化

分布式缓存

        网站性能优化第一定律:优先考虑使用缓存优化性能。

1.缓存的基本原理

        缓存指将数据存储在相对较高访问速度的存储介质中,以供系统处理。一方面缓存访问速度快,可以减少数据访问时间,另一方面如果缓存的数据是经过计算机处理得到的,那么被缓存的数据无需重复计算即可直接使用,因此缓存还起到减少计算时间的作用。
        缓存的本质是一个内存Hash表,网站应用中,数据缓存以一对key、value的形式存储在内存hash表中。hash表数据读写的时间复杂度为O(1)。

2.合理使用缓存

        频繁修改的数据(失效太快,频繁更新,徒增负担)

        没有热点的访问(定律,只缓存热点数据,容量有限)

        数据不一致与脏读(一般会给缓存设置失效期,超过失效期重新加载,因此数据库修改后,要容忍缓存数据到等待失效期后重新加载,这个期间内会出现数据不一致,如果数据更新后实时通知缓存进行更新会带来系统开销)

        缓存可用性(避免缓存服务崩溃时数据库压力剧增导致宕机)
缓存预热(缓存中存放热点数据,热点数据通过最就久未用LRU算法淘汰出来的,这个过程需要较长时间,因此在缓存系统启动时就应该把热点数据加载好)

        缓存穿透(如果因为不恰当的业务、或恶意攻击持续高并发地请求某个不存在的数据,由于缓存没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大压力,甚至崩溃。一个简单的对策室将不存在的数据也缓存起来(其value值为null))

3.分布式缓存架构

        以JBossCache为代表的需要更新同步的分布式缓存,所有服务器中保存相同的缓存数据,当某太服务器缓存有数据更新时,会通知集群中其他机器更新缓存数据或清除缓存数据,会将缓存部署在应用服务器上,使应用程序可以快速的获取缓存数据,但是受限于单一服务器的内存空间。

        memcached为代表的不互相通信的分布式缓存,采用一种集中式的缓存集群管理,缓存与应用分离部署,缓存系统部署在一组专门的服务器上,应用程序通过一致性hash算法等路由算法选择缓存服务器远程访问缓存数据,缓存服务器之间不通信,缓存集群的规模可以很容易地实现扩容,具有良好的伸缩性。

4.memcached

        不详细记录了

异步操作

        1.使用消息队列异步化,可改善网站的扩展性

        2.改善网站系统的性能(将请求放入消息队列后可直接响应用户操作,无需等待消息被处理)

        3.削峰作用(高峰期业务请求进入消息队列排队处理,将压力高峰削弱,减少高并发对系统的冲击)

使用集群

代码优化

1.多线程

        web应用服务器都采用多线程的方式响应并发用户请求,因此网站开发天然的就是多线程编程。

        从资源利用角度看,使用多线程的原因主要有两个:IO阻塞与多CPU。当前线程在进行IO处理的时候,会被阻塞释放CPU以等待IO操作完成,这是CPU可以调度其他的线程进行处理。另一个原因是服务器有多CPU、CPU有多核,想最大限度的利用这些CPU,必须启动多线程。

        解决线程安全的主要手段有如下几点:

        将对象设计成无状态对象:所谓无状态对象是指对象本身不存储信息(对象无成员变量,或者成员变量也是无状态对象),这样多线程并发访问的时候就不会出现状态不一致,java web开发中常用的servlet对象就被设计为无状态对象,可以被应用服务器多线程并发调用处理用户请求。而web开发中常见的贫血模型对象都是些无状态对象。

        使用局部对象:即在方法内部创建对象,这些对象会被每个进入该方法的线程创建,除非有意识地将这些对象传递给其他线程,否则不会出现对象呗多线程并发访问的情形。

        并发访问资源时使用锁:即多线程访问资源的时候,通过锁的方式使多线程并发操作转化为顺序操作,从而避免资源被并发修改。随着操作系统和编程语言的进步,出现各种轻量级锁,使得运行期线程获取锁和释放锁的代价都变得更小,但是锁导致线程同步顺序执行,可能会对系统性能产生影响。

2.资源复用

        系统运行时尽量减少开销很大的系统资源的创建和销毁,比如数据库连接等,从编程角度,资源复用主要有两种模式:单例和对象池。

        目前web开发中主要使用贫血模式,从service到dao都是无状态对象,所以无需重复创建,使用单例就可以,另外,spring默认构造bean也是单例。

3.数据结构

        程序就是数据结构+算法,灵活组合各种数据结构有助于提升读写性能。

4.垃圾回收

        理解垃圾回收机制有助于程序优化和参数调优。

存储性能优化

        

 

 

 

 

转载于:https://my.oschina.net/qussa/blog/780098

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值