《大型网站技术架构》学习笔记
第一章: 大型网站的演化
1.1 大型网站软件系统的特点
高并发, 大流量:PV量巨大
高可用:7*24小时不间断服务
海量数据:PB级
用户分布广泛, 网络情况复杂
安全环境恶劣:大型网站几乎每天都被攻击
需求快速变更, 发布频繁:大型网站每周都有新版本上线
渐进式发展:大型网站都从小网站发展而来
1.2 大型网站架构演化发展历程
初始阶段的网站架构
只用一台服务器。
应用服务和数据服务分离
分出了应用, 数据, 文件三台服务器.
应用服务器要处理大量的业务, 所以需要更快更强的CPU.
数据服务器快速磁盘检索和数据缓存, 需要更快的硬盘和大内存
文件服务器用于存储用户的文件, 需要更大的硬盘
使用缓存改善网站性能
大部分业务访问集中在一小部分数据上。
本地缓存:速度快,受应用服务器内存限制
分布式缓存服务器(集群):使用大内存服务器
使用应用服务器集群改善网站的并发处理能力
通过持续增加应用服务器的方式来改善负载压力, 实现系统的可伸缩性。
通过负载均衡调度服务器,将访问请求分发到应用服务器集群的任意一台服务器。
数据库的读写分离
使用缓存后,少部分读和全部写还是要访问数据库
配置主从数据库. 应用服务器要写数据时, 访问主数据库. 主数据库通过主从复制机制将数据更新同步到从数据库.
使用反向代理和CDN加速网站响应
基本原理都是缓存. 区别在于CDN部署在网络提供商机房中. 而反向代理部署在网站机房中.
如果反向代理服务器缓存着用户请求的资源,则直接返回给用户,降低了服务器的压力。
目的都是为了尽早返回数据给用户。
使用分布式文件系统和分布式数据库系统
通常使用业务分库,将不同业务的数据部署在不同的服务器上。
单表规模非常庞大时,才使用分布式数据库。
使用NoSQL和搜索引擎
NoSQL和搜索引擎都是源自互联网的技术手段,对可伸缩的分布式特性具有更好的支持。
应用服务器则通过一个统一数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。
业务拆分
将整个网站业务拆分成不同的产品线。
大型购物网站会将首页,商铺,订单,买家,卖家分成不同的产品线,由不同的团队负责。
各个应用之间可以通过一个超链接建立关系,也可以通过消息队列进行数据分发。
分布式服务
比如用户管理,商品管理这些业务,可以将共用的业务提取出来,独立部署
第二章:大型网站架构模式
分层
应用层:负责具体业务和视图展示,如网站首页,搜索结果展示
服务层:为应用层提供服务支持,如用户管理,购物车
数据层:提供数据存储访问服务
分层架构是逻辑上的,但物理上也可部署在不同的机器上
分割
分割是在纵向方面对软件进行切分,将不同的功能和服务分割开来,包装成高内聚低耦合的模块单元,
有助于软件开发和维护,还便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力。
分布式
对于大型网站,分层和分割的一个主要目的就是为了切分后的模块便于分布式部署。
分布式可能遇到的问题:
1. 网络延迟的影响
2. 服务器宕机
3. 数据一致性保证
4. 开发维护的问题
分布式应用和服务
应用和服务模块分布式部署,便于业务功能扩展
分布式静态资源 (动静分离)
JS、CSS、LOGO图片等资源独立部署,采用独立域名
分布式部署减轻应用服务器压力
采用独立域名,加大浏览器的并发加载量,让网站更快的呈现在用户面前
分布式数据和存储
单台计算机无法存储海量数据
包括关系数据库的分布式和NoSQL的分布式
分布式计算
Hadoop及其MapReduce分布式计算框架,其特点是移动计算而不是移动数据
分布式环境下实现并发和协同的分布式锁
集群
多台服务器部署相同应用构成一个集群,通过负载均衡设备共同对外提供服务
当某台服务器发生故障,负载均衡设备或者系统的失效转移机制将请求转发到集群中的其他服务器上,提高系统的可用性
缓存
缓存就是将数据存放在距离计算最近的位置,以加快处理速度
CDN:内容分发网络,部署在距离用户最近的网络服务商,主要缓存网站的一些静态资源,如视频网站的热点内容
反向代理:部署在网站的前端,无须将请求转发给应用服务器就能返回给用户
本地缓存:在应用服务器中,缓存热点数据,这样就不用访问数据库了
分布式缓存:应用程序通过网络通信访问缓存数据
缓存的数据应该不能被频繁修改,且不会很快过期
异步
业务之间的消息传递不是同步调用,而是将一个业务操作分成多个阶段,每个阶段之间通过共享数据的方式异步执行进行协作。
异步架构是典型的生产者消费者模式,两者不存在直接调用,只要保持数据结构不变,彼此功能实现可以随意变化而不互相影响,这对网站扩展新功能非常便利。
异步消息队列可以提高系统可用性、加快网站响应速度,消除并发访问高峰。
冗余
要想保证在服务器宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份,这样当某台服务器宕机时,可以将其上的服务和数据访问转移到其他机器上。
数据库除了定期备份存档保存实现冷备份之外,为了保证在线业务高可用,还需要对数据库进行主从分离,实时同步实现热备份。
自动化
在无人值守的情况下,网站可以正常运行,一切都可以自动化是网站的理想状态。目前大型网站的自动化架构设计主要集中在发布运维方面。
①发布部署过程自动化;
②自动化代码管理;
③自动化测试;
④自动化安全监测;
安全
①通过密码和手机校验码进行身份验证;
②对登录、交易等操作进行加密;
③使用验证码进行识别;
④对于常见的XSS攻击、SQL注入、编码转换等进行防范;
⑤对垃圾或敏感信息进行过滤;
⑥对交易转账等操作进行风险控制;
第三章:大型网站核心架构要素
性能
浏览器端:浏览器缓存,使用页面压缩,合理布局页面,减少Cookie传输
CDN:将网站静态内容分发至离用户最近的网络服务商机房
反向代理:缓存热点文件,加快请求响应速度,减轻服务器压力
应用服务器端:服务器本地缓存和分布式缓存
异步:将用户请求发送至消息队列等待处理,当前请求直接返回
集群:多台应用服务器组成集群
数据库服务器端:索引,缓存,SQL优化,NoSQL
可用性
冗余:各服务器互相备份保证整体可用;
应用服务器端:通过负载均衡设备建立集群,其中一台宕机立即切换到其他服务器继续提供服务,这就保证了高可用性。
存储服务器端:需要对数据进行实时备份,当某台宕机立即将数据访问请求转换到其他服务器上,并进行数据恢复以保证数据高可用。
伸缩性
伸缩性:通过不断向集群中加入服务器的手段来缓解并发访问的压力和数据存储的需求
(1)衡量标准:
①是否可以多台服务器构建集群?
②是否容易向集群中添加新服务器?
③加入服务器后是否能提供无差别服务?
(2)主要手段:
①应用服务器:使用合适的负载均衡设备
②缓存服务器:改进缓存路由算法保证缓存数据的可访问性
③数据库服务器:通过路由区分等手段将多服务器组成一个集群
扩展性
(1)衡量标准:增加新业务时是否可以实现对现有产品透明无影响
(2)主要手段:
①事件驱动架构:利用消息队列实现;
②分布式服务:将业务和可复用服务分离;
安全性
衡量标准:针对现存和潜在的攻击窃密手段,是否有可靠的应对策略
第四章:网站的高性能架构
4.1 网站性能测试
性能测试指标:
响应时间:应用执行一个操作需要的时间,包括发出请求到收到最后响应所要的时间。
测试时通常采用重复测试,一个请求操作重复一万次,总响应时间之和再除以一万。
并发数:系统能够同时处理请求的数目,也指同时提交请求的用户数目。
吞吐量:单位时间内系统处理的请求数量。
性能计数器:描述系统性能的一些数据指标。
性能测试方法:
①性能测试;②负载测试;③压力测试;④稳定性测试;
性能优化策略:
①性能分析:检查请求处理各个环节的日志,分析哪个环节响应时间不合理,检查监控数据分析影响性能的因素;
②性能优化:Web前端优化,应用服务器优化,存储服务器优化;
4.2 Web前端性能优化
浏览器访问优化:
①减少http请求:因为http是无状态的,每次请求的开销都比较昂贵(需要建立通信链路、进行数据传输,而服务器端对于每个http请求都需要启动独立的线程去处理);
减少http的主要手段是合并CSS、合并JS、合并图片(利用偏移定位image);
②使用浏览器缓存:设置http头中Cache-Control和Expires属性;
③启用压缩:可以对html、css、js文件启用Gzip压缩,可以达到较高的压缩效率,但是压缩会对服务器及浏览器产生一定的压力;
④CSS放页面最上面,JS放页面最下面:浏览器会在下载完全部CSS之后才开始对整个页面进行渲染,因此最好将CSS放在页面最上面;
而浏览器在加载JS后会立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此最好将JS放在页面最下面;
⑤减少Cookie传输:一方面,太大的Cookie会严重影响数据传输;另一方面,对于某些静态资源的访问(如CSS、JS等)发送Cookie没有意义;
可以考虑静态资源使用独立域名访问,避免请求静态资源时发送Cookie
CDN加速:
CDN(内容分发网络)仍然是一个缓存,它将数据缓存在离用户最近的地方,便于用户以最快速度获取数据。即所谓的“网络访问第一跳”。
CDN只将访问频度很高的热点内容(例如:图片、视频、CSS、JS脚本等访问频度很高的内容)进行缓存,可以极大地加快用户访问速度,减少数据中心负载。
反向代理:
反向代理服务器位于网站机房,代理网站Web服务器接收Http请求,对请求进行转发。
反向代理服务器具有以下功能:
①保护网站安全:任何来自Internet的请求都必须先经过代理服务器;
②通过配置缓存功能加速Web请求:减轻真实Web服务器的负载压力;
维基百科及某些博客,会把热门词条,帖子,博客缓存在反向代理服务器上,动态内容变化时,通知反向代理服务器缓存失效,再重新加载冬天内容。
③实现负载均衡:均衡地分发请求,平衡集群中各个服务器的负载压力;
4.3 应用服务器性能优化
分布式缓存:
网站性能优化第一定律:优先考虑使用缓存优化性能。
定义:缓存是指将数据存储在相对较高访问速度的存储介质中(如内存),以供系统进行快速处理响应用户请求。
缓存本质是一个内存Hash表,数据以(Key,Value)形式存储在内存中。
缓存主要用来存放那些读写比很高、很少变化的数据,如商品的类目信息、热门商品信息等。这样,应用程序读取数据时,先到缓存中取,如缓存中没有或失效,再到数据库中取出,重新写入缓存以供下一次访问。
因此,可以很好地改善系统性能,提高数据读取速度,降低存储访问压力。
读写比高时,缓存才有意义。热门微博,缓存后可能会被读取百万次。
缓存超过一定时间失效后,要从数据库重新加载,失效前可能会有一段时间数据不一致。比如添加了新的分类,但却没有显示。
缓存预热:新启动的缓存系统没有任何数据,可以在启动时就把热点数据加载好。
缓存穿透:持续高并发地请求某个不存在的数据,会对数据库造成很大的压力。可以将不存在的数据也缓存起来,值为null。
分布式缓存架构:一方面是以以JBoss Cache为代表的互相通信派;另一方面是以Memcached为代表的互不通信派;
JBoss Cache需要将缓存信息同步到集群中的所有机器,代价比较大;而Memcached采用一种集中式的缓存集群管理,缓存与应用分离部署,应用程序通过一致性Hash算法选择缓存服务器远程访问缓存数据,缓存服务器之间互不通信,因而集群规模可以轻易地扩容,具有良好的伸缩性。
Memcached由两个核心组件组成:服务端(ms)和客户端(mc),在一个memcached的查询中,mc先通过计算key的hash值来确定kv对所处在的ms位置。当ms确定后,客户端就会发送一个查询请求给对应的ms,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以 memcached交互带给网络的影响是最小化的。
异步操作:
使用消息队列将调用异步化,可改善网站的扩展性,还可改善网站性能。
用户请求发送给消息队列后立即返回,再由消费者进程从队列中获取数据,异步写入数据库。
消息队列具有削峰的作用->将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。
使用集群:
①在高并发场景下,使用负载均衡技术为一个应用构建多台服务器组成的服务器集群;
②可以避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性;
③负载均衡可以采用硬件设备,也可以采用软件负载。商用硬件负载设备(例如出名的F5)成本通常较高(一台几十万上百万很正常),所以在条件允许的情况下我们会采用软负载,软负载解决的两个核心问题是:选谁、转发,其中最著名的是LVS(Linux Virtual Server)。
代码优化:
①多线程:使用多线程的原因:一是IO阻塞,二是多CPU,都是为了最大限度地利用CPU资源,提高系统吞吐能力,改善系统性能;
②资源复用:目的是减少开销很大的系统资源的创建和销毁,主要采用两种模式实现:单例(Singleton)和对象池(Object Pool)。例如,在开发中,经常使用到的线程池,数据库连接池等,本质上都是对象池。
③数据结构:在不同场合合理使用恰当的数据结构,可以极大优化程序的性能。
④垃圾回收:理解垃圾回收机制有助于程序优化和参数调优,以及编写内存安全的代码。
4.4 存储性能优化
机械硬盘:通过马达驱动磁头臂,带动磁头到指定的磁盘位置访问数据。它能够实现快速顺序读写,慢速随机读写。
固态硬盘(又称SSD):无机械装置,数据存储在可持久记忆的硅晶体上,因此可以像内存一样快速随机访问。
在目前的网站应用中,大部分应用访问数据都是随机的,这种情况下SSD具有更好的性能表现,但是性价比有待提升。
传统关系型数据库广泛采用B+树,B+树是对数据排好序后再存储,加快数据检索速度。
目前大多数DB多采用两级索引的B+树,树的层次最多三层。因此可能需要5次磁盘访问才能更新一条记录(三次磁盘访问获得数据索引及行ID,一次数据文件读操作,一次数据文件写操作)
NoSQL(例如:HBase)产品广泛采用LSM树:
具体思想是:将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘。不过读取的时候稍微麻烦,需要合并磁盘中历史数据和内存中最近的修改操作,所以写入性能大大提升,读取时可能需要先看是否命中内存,否则需要访问较多的磁盘文件。
LSM树的原理是:把一棵大树拆分成N棵小树,它首先写入内存中,随着小树越来越大,内存中的小树会被清除并写入到磁盘中,磁盘中的树定期可以做合并操作,合并成一棵大树,以优化读性能。
LSM树的优势在于:在LSM树上进行一次数据更新不需要磁盘访问,在内存即可完成,速度远快于B+树。