第六章 永无止境:网站的伸缩性架构
- 网站的伸缩性是指不需要改变网站的软硬件设计,仅仅通过改变部署的服务器数量就可以扩大或者缩小网站的服务处理能力
- 大型网站的“大型”:在用户层面为大量用户及大量访问,在功能方面为功能庞杂,在技术层面为需要部署大量的服务器
- 大型网站是从小型网站渐进演化而来的,也有可能出现脉冲,传统企业易忽视这点(一开始就试图打造大型网站)
网站架构的伸缩性设计
- 不同功能进行物理分离实现伸缩
新增服务器总是从现有服务器中分离出部分功能和服务进行处理
- 纵向分离(分层后分离)
将业务处理流程上的不同部分分离部署 - 横向分离(业务分割后分离)
将不同的业务模块分离部署,粒度可以很小,甚至一个关键网页部署为一个独立服务
- 纵向分离(分层后分离)
- 单一功能通过集群规模实现伸缩
不同功能分离部署,随着网站访问量的逐步增加,即使最小粒度分离部署,也不能满足业务规模要求,因此要使用服务器集群,集群规模需要同时考虑对其可用性、性能及关联服务集群的影响
- 应用服务器集群
- 数据服务器集群
- 缓存数据服务器集群
- 存储数据服务器集群
- 不同功能进行物理分离实现伸缩
应用服务器集群的伸缩性设计
应用服务器是无状态的,如果负载均衡服务器可以感知或者可以配置集群的服务器数量,可以及时发现集群中新上线或下线的服务器,并能向新上线的服务器分发请求,停止向已下线的服务器分发请求,那么就实现了应用服务器集群的伸缩性负载均衡的实现技术有以下几种
- HTTP重定向负载均衡
根据用户HTTP请求计算服务器地址,返回302重定向给浏览器再进行访问
- 优点:简单
- 缺点:一次访问浏览器需要两次请求,性能较差;重定向服务器本身性能可能成为瓶颈;302响应重定向可能会被搜索引擎判断为SEO作弊,降低搜索排名
- DNS域名解析负载均衡
DNS服务器中配置多个记录,每次域名解析请求都会计算不同的服务器地址返回进行访问
- 优点:负载均衡工作交给DNS,省掉网站管理维护负载均衡服务器的麻烦;DNS还支持地理位置域名解析,可根据地理就近进行地址返回,加快访问速度,改善性能
- 缺点:DNS为多级解析,下线服务器时修改记录后,生效需要较长的时间,这段时间导致访问失败;DNS负载均衡控制权在域名服务商那,网站无法进行更多改善和强大的管理
- 反向代理负载均衡
反向代理服务器缓存资源改善网站性能的同时,计算服务器地址并进行请求转发,服务器处理完后返回给反向代理服务器,反向代理服务器再将相应返回给用户
Web服务器不需要外部IP地址,反向代理服务器需要配置双网卡和内部外部两套IP地址
- 优点:负载均衡和反向代理集成一起,部署简单
- 缺点:反向代理服务器成为所有请求响应的中转站,本身性能可能成为瓶颈
IP负载均衡
负载均衡服务器在操作系统内核进程获取网络数据包,计算服务器地址并进行目的IP地址修改,服务器处理完后返回给负载均衡服务器,负载均衡服务器再将数据包源地址修改为自身的IP地址并返回给用户真实物理Web服务器响应数据包返回给负载均衡服务器的两种方式 * 修改目的地址同时修改源地址为自身IP,即源地址转换(SNAT) * 将负载均衡服务器作为真实服务器集群的网关服务器
- 优点:内核中完成数据分发,较反向代理服务器(在应用层分发数据)有更好的性能
- 缺点: 数据吞吐量受限于负载均衡服务器网卡带宽,对于下载、视频服务等难以满足需求
- 数据链路层负载均衡(直接路由方式)
三角传输模式,计算服务器Mac地址,不修改IP地址,只修改目的mac地址,配置真实物理服务器集群所有机器虚拟IP和负载均衡服务器IP地址一致,达到数据分发的目的,物理服务器响应发送给网关服务器后直接返回给用户
- 优点:避免负载均衡服务器网卡宽带成为瓶颈
事实上,大型网站总是使用DNS域名解析作为第一级负载均衡,域名解析得到一组提供负载均衡服务的内部服务器,然后再进行负载均衡分发请求
数据链路层负载均衡是目前大型网站使用最广的一种负载均衡手段- 负载均衡算法
- 轮询(可加权)
- 随机(可加权)
- 最少连接(可加权)
- 源地址散列:会实现会话黏滞
- HTTP重定向负载均衡
- 分布式缓存集群的伸缩性设计
分布式缓存服务器集群中不同服务器缓存的数据各不相同,请求不可以在任意一台缓存服务器上处理,严重制约了分布是缓存集群的伸缩性设计
新加入缓存服务器后应该使整个缓存服务器集群中已经缓存的数据尽可能被访问,这是分布式缓存集群伸缩性设计的最主要目标
- Memcached分布式缓存集群的访问模型
应用程序通过Memcached客户端访问Memcached服务器集群,Memcached客户端主要由一组API、Memcached服务器集群路由算法、Memcached服务器集群列表及通信模块构成
读写使用相同的集群路由算法,因此只要缓存存在便能保证命中 - Memcached分布式缓存集群的伸缩性挑战
简单的路由算法使用余数Hash,也可稍微改进为加权余数Hash,但是集群需要扩容时大部分数据不能命中,比例随着规模一起增大,应用就会直接访问数据库服务器,大大超过数据库的负载能力,导致数据库宕机,不能简单重启恢复,需要较长时间恢复正常
一种解决办法:网站访问量最小时扩容,此时对数据库负载冲击最小,并且通过模拟请求方式逐渐预热缓存,使缓存服务器中的数据重新分布 - 分布式缓存的一致性Hash算法
构造一致性Hash环(通常使用二叉查找树),缓存服务器根据节点名称的Hash值进行放置,缓存数据根据数据KEY值的Hash值在Hash环上顺时针查找距离最近的缓存服务器节点,完成KEY到服务器的映射查找
扩容时新加入节点只影响环中一小段,继续命中率随着规模一起增大
一致性Hash算法会带来负载不均衡问题,可以通过增加一个虚拟层解决,将每台物理缓存服务器虚拟为一组虚拟缓存服务器,然后根据虚拟缓存服务器Hash进行放置,最终结果是新加入服务器分摊原有缓存服务器集群中所有服务器的一小部分负载,总的影响范围和不使用虚拟层相同
一般一台物理服务器虚拟为150个虚拟服务器比较合理
- Memcached分布式缓存集群的访问模型
数据存储服务器集群的伸缩性设计
- 关系数据库集群的伸缩性设计
- 业务分库
- 主从数据库复制
- 单表分片
常见的产品有Amoeba、Cobar
分布式关系数据库访问代理,应用程序访问代理,代理根据SQL和分库规则分解SQL,分发到MySQL集群不同的数据库实例上执行,合并结果后进行统一返回应用程序
代理通常是无状态的应用服务器可以简单负载均衡进行伸缩;MySQL数据库服务器则利用一致性Hash算法和以Schema为单位的数据同步功能进行迁移,同步完成后进行Schema的IP修改并删除原有机器中的相关Schema即可
- 优点:性能和直接访问数据库相当;代理代替应用程序连接数据库,需要维护更少的连接,减少不必要的资源消耗
- 缺点:需要避免事务或利用事务补偿机制代替数据库事务;需要分解数据访问逻辑避免Join操作;带有Join功能的代理延迟太高
- NoSQL数据库的伸缩性设计
- 放弃关系型数据库的以关系代数为基础的结构化查询语言(SQL)和事务一致性保证(ACID),强化高可用性和可伸缩性
- 应用最广泛的产品有HBase
- 数据以HRegion为单位进行管理,每个Region存储一段Key值间的数据,HRegionServer是物理服务器,每个HRegionServer可以启动多个HRegion实例,HRegion写入数据太多到达阈值时会分裂成两个HRegion,并在整个集群中进行迁移,使得HRegionServer的负载均衡
- 数据写入和访问:应用程序通过Key向Zookeeper(分布式数据管理服务)请求主HMaster地址,应用程序再通过Key向HMaster请求HRegionServer地址,最后再请求HRegionServer上的HRegion得到数据
- 关系数据库集群的伸缩性设计