大型网站技术核心原理与案例分析

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

1.大型互联网应用系统特点
  • 高并发,大流量: 高并发用户,大流量访问。
  • 高可用: 系统7*24小时不间断服务。
  • 海量数据: 存储管理海量数据,需要使用大量服务器。
  • 用户分布广泛,网络情况复杂: 大型互联网为全球用户提供服务。
  • 安全环境恶劣: 互联网的开放性,更容易受到攻击。
  • 需求快速变更,发布频繁: 互联网产品为快速适应市场,满足用户需求,产品发布频率极高。
  • 渐进式发展: 大型互联网站几乎都是从一个小网站开始,渐进的发展起来的。
  • 2.大型网站架构模式
  • 2.1. 分层
    • 概念: 系统在横向纬度上切分成几个部分,每个部分负责相对单一的职责,然后通过上下层依赖和调用组成一个完整系统。(应用层、服务层、数据层)
    • 目的: 规划软件清晰的逻辑结构便于开发维护;分层结构对网站支持高并发向分布式方向发展至关重要。
  • 2.2. 分割
    • 概念: 纵向方面对软件进行切分。网站越大,功能越复杂,服务和数据处理的种类也就越多。将这些不同的功能和服务分割开来,包装成高内聚低耦合的模块单元。
    • 目的: 有助于软件的开发和维护,便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力。
  • 2.3. 分布式
    • 概念: 不同模块部署在不同的服务器上,通过远程调用协同工作。分布式意味着可以使用更多的计算机来完成同样的功能。能够处理的并发访问和数据量就越大,进而能够为更多的用户提供服务。
    • 缺点:
    • 分布式意味着服务调用必须经过网络,可能对性能造成比较严重的影响。
    • 服务器越多,服务器宕机的概率也就越大,网站可用性会降低。
    • 分布式环境下数据保持一致性也非常困难,分布式事务难以保障,对业务正确性和业务流程可能造成影响。
    • 分布式导致网站依赖错综复杂,开发管理维护困难。
    • 分布式方案(常用):
    • 分布式应用和服务: 分层和分割后的应用和服务模块分布式部署,改善网站性能和并发性便于业务功能扩展。
    • 分布式静态资源: 静态资源独立分布式部署(减轻应用服务器的负载压力),并采用独立的域名(加快浏览器并发加载速度)。
    • 分布式数据和存储: 海量数据需要分布式部署,除了对传统关系型数据库分布式部署,各种NOSQL产品几乎都是分布式。
    • 分布式计算: Hadoop及其MapReduce分布式计算框架。
  • 2.4. 集群
    • 描述: 分布式已经将分层和分割后的模块独立部署,但是对于用户访问集中的模块(门户首页),需要将独立部署的服务器集群化。即多台服务器部署相同的应用构成一个集群,通过负载均衡设备对外提供服务。
    • 优点: 服务器集群有更多的服务器提供相同的服务,可以提供更好的并发特性,增加访问只需要向集群中添加机器。当某台服务器发生故障,负载均衡设备或系统的实效转移机制会将请求转发到集群中的其他服务器上。
  • 2.5. 缓存
    • 概念: 缓存就是将数据存放在距离计算机最近的位置以加快处理速度。缓存是改善软件性能第一手段。
    • 分类:
    • CDN: 内容分发网络,部署在距离终端用户最近的网络服务商。用户网络请求最先到达网络服务商那里。
    • 反向代理: 网站前端架构的一部分,部署在网站的前端,当用户请求到达网站的数据中心时,最先访问的就是反向代理服务器。(这里缓存着网站的静态资源)
    • 本地缓存: 应用服务器本地缓存着热点数据,可以直接在本机内存访问数据,无需访问数据库。
    • 分布式缓存: 大型网站数据量非常庞大,需要分布式缓存,应用程序通过网络通信访问缓存数据。
    • 条件:
    • 数据访问热点不均衡,某些数据会被更频繁的访问,这些数据应放在缓存中。
    • 数据在某个时间段内有效,不会很快过期,否则数据会因为失效而引起脏读,影响结果正确性。
    • 缓存除了可以加快数据访问速度,还可以减轻后端应用和数据存储的负载压力。网站数据库几乎都是按照有缓存的前提进行负载能力设计。
  • 2.6. 异步
    • 概念: 异步降低软件耦合性,业务之间的消息传递不是同步调用,而是将一个业务操作分成多个阶段,每个阶段间通过共享数据的方式异步执行进行协助。在分布式系统中,多个服务器集群通过分布式消息队列实现异步,分布式消息队列可以看作是内存队列的分布式部署。
      异步架构是典型的生产者消费者模式,两者不存在直接调用,只要保持数据结构不变,彼此功能实现可以随意变化而不互相影响,对网站扩展新功能非常便利。
    • 异步消息队列特性:
    • 提高系统可用性: 消费者服务器发生故障,数据会在消息队列服务器中存储堆积,生产者服务器可以继续处理业务请求,系统整体表现无故障。消费者服务器恢复正常,继续处理消息队列中的数据。
    • 加快网站响应速度: 业务处理前端的生产者服务器在处理完业务请求后,将数据写入消息队列。不需要等待消费者服务器处理就可以返回,响应延迟减小。
    • 消除并发访问高峰: 使用消息队列将突然增加的访问请求数据放入消息队列中,等待消费者服务器依次处理,就不会对整个网站负载造成太大压力。
  • 2.7. 冗余:
    • 描述: 保证服务器在宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份,当某台服务器宕机时,可以将其上的数据和服务转移到其他机器上。
  • 2.8. 自动化:
    • 发布: 自动化代码管理,自动化测试,自动化安全监测,自动化部署
    • 运维: 自动化监控,自动化报警,自动化失效转移, 自动化失效恢复, 自动化降级, 自动化分配资源
  • 2.9. 安全: 互联网的开放特性使得其从诞生起就面对巨大的安全挑战,网站在安全架构方面也积累了许多模式。
  • 3.大型网站核心架构要素

    架构: 最高层次的规划,难以改变的决定

  • 3.1. 瞬时响应:网站的高性能架构(性能)
    • 1 ).网站性能测试
    • 性能测试指标
      • 响应时间: 执行一个操作需要的时间,从发出请求到收到最后响应数据所需要的时间。
      • 并发数: 系统能够同时处理的请求数目(同时提交请求的用户数目)。
      • 吞吐量: 单位时间内系统处理的请求数量,体现系统的整体处理能力。
      • 性能计数器: 服务器或操作系统的一些数据指标。
    • 性能测试方法
      • 性能测试
      • 负载测试
      • 压力测试
      • 稳定性测试
    • 性能测试报告
    • 性能优化策略
      • 性能分析: 对请求经历的各个环节进行分析。
      • 性能优化: 根据网站分层架构 Web前端性能优化、应用服务器性能优化、存储服务器性能优化
    • 2 ).Web前端性能优化
    • 浏览器访问优化
      • 减少http请求: http协议是无状态的应用层协议,意味着每次http请求都需要建立通信链路,进行数据传输。而在服务器端,每个http都需要启动独立的线程去处理。这些通信和服务的开销都很贵,减少http请求数目可有效提高访问系能(合并CSS,合并Javascript,合并图片)。
      • 使用浏览器缓存: 静态资源缓存到浏览器中(Http头中的Cache-Control和Expires)。
      • 启用压缩: 服务器端对文件压缩,浏览器端对文件解压缩。减少通信传输数据量。
      • CSS放在页面最上面,JavaScript放在页面最下面 : 如果页面解析需要用到JavaScript除外。
      • 减少Cookie传输: Cookie包含在每次请求响应中,太大的Cookie会严重影响数据传输。静态资源使用独立的域名访问,避免请求静态资源时发送Cookie。
    • CDN加速 (内容分发网络) 将数据缓存在离用户最近的地方(部署在网络运营商机房),使用户以最快的速度获取数据。(CDN能缓存的一般是静态资源)
    • 反向代理 反向代理服务器位于网站机房一侧,代理网站Web服务器接受http请求。
      • 保护网站安全,来自互联网的请求必须经过代理服务器,服务器和可能的网络攻击间建立一个屏障
      • 缓存功能加速Web请求,静态内容和部分动态内容缓存。
      • 负载均衡功能,提高系统整体处理能力,改善网站高并发情况下的性能。
    • 3 ). 应用服务器性能优化
    • 分布式缓存
      • 缓存的基本原理 : 缓存是指将数据存储在相对较高访问速度的存储介质中,以供系统处理。一方面缓存访问速度快,可以减少数据访问时间,另一方面缓存起到减少计算时间的作用。
        缓存的本质是一个内存Hash表,网站应用中,数据缓存以一对Key、Value形式存储在内存Hash表中。
      • 合理使用缓存
      • 频繁修改的数据: 数据写入缓存后,应用还来不及读取缓存,数据就已经失效,徒增系统负担。
      • 没有热点的访问: 如果应用系统访问数据没有热点(二八定律)。那缓存就没有意义,缓存数据还有被再次访问就已经被挤出缓存。
      • 数据不一致与脏读: 缓存数据设置失效时间,一旦超过失效时间,就要从数据库中重新加载。
      • 缓存可用性: 通过分布式缓存服务器集群,将缓存数据分布到集群多台服务器上可在一定程度上改善缓存的可用性。
      • 缓存预热: 系统启动时就把热点数据加载好。
      • 缓存穿透: 因不恰当的业务或者恶意攻击持续高并发的请求某个不存在的数据(对策是将不存在的数据也缓存起来)。
      • 分布式缓存架构: 缓存部署在多个服务器组成的集群中,以集群的方式提供缓存服务。
    • 异步操作
      • 描述: 使用消息队列将调用异步化,可改善网站的扩展性和网站系统性能。
    • 使用集群
      • 描述: 网站高并发访问场景下,负载均衡技术构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢。
    • 代码优化
      • 多线程
      • 公式: 启动线程数 = [任务执行时间/(任务执行时间-IO等待时间)] * CPU内核数
      • 线程安全解决手段:
        • 对象设置为无状态对象: 即对象本身不存储状态信息(对象无成员变量或成员变量也是无状态对象),Web开发中常用的贫血模型对象都是无状态对象。(面向对象的设计角度看无状态对象是不良设计)
        • 使用局部对象: 方法内部创建对象
        • 并发访问资源时使用锁: 多线程访问资源的时候,通过锁的方式使多线程并发操作转化为顺序操作,从而避免资源被并发修改。
      • 资源复用
      • 单例(Singleton): Web开发中使用的贫血模式;Spring默认构造的对象都是单例。
      • 对象池(Object Pool): 通过复用对象实例,减少对象的创建和资源消耗。(连接池、线程池)
      • 数据结构
      • 描述: 灵活组合各种数据结构改善数据读写和计算特性可极大优化程序性能。
      • 垃圾回收
      • 栈(Stack): JVM内存指令区,存储线程上下文信息。如方法参数、局部变量。
      • 堆(Heap): JVM内存数据区,存储对象内存空间。对象的创建和释放,垃圾回收都在这里进行。
    • 4 ). 存储性能优化
    • 机械硬盘 vs. 固态硬盘
      • 机械硬盘: 快速顺序读写,慢速随机读写。
      • 固态硬盘: 随机读写性能高,但不太成熟;可靠性,性价比有待提升。
    • B+树 vs. LSM树
    • RAID vs. HDFS
  • 3.2. 万无一失:网站的高可用架构(可用性)

    • 网站可用性的度量

      网站不可用时间(故障时间) = 故障修复时间点 - 故障发现(报告)时间点
      网站年度可用性指标 = (1 - 网站不可用时间/年度总时间) * 100%

    • 高可用网站架构
    • 目的: 保证服务器硬件故障时服务依然可用、数据依然保存并能够被访问。
    • 手段: 数据和服务的冗余备份及失效转移。
    • 高可用的应用
    • 通过负载均衡进行无状态服务的实效转移
    • 应用服务器集群的Session管理
      • Session复制
      • Session绑定
      • 利用Cookie记录Session
      • Session服务器
    • 高可用的服务
    • 分级管理
    • 超时设置
    • 异步调用
    • 服务降级(拒绝服务、关闭功能)
    • 幂等性设计
    • 高可用的数据
    • CAP原理: 一个提供数据服务的存储系统无法同时满足数据一致性(Consistency)、数据可用性(Availibility)、分区耐受性(Patition Tolerance 系统具有夸网络分区的伸缩性)这三个条件。
    • 数据备份: 冷备和热备(异步热备和同步热备)
    • 失效转移: 失效确认(心跳监测、失败报告)、访问转移、数据恢复
    • 高可用网站的软件质量保证
    • 网站发布: 每次发布关闭服务都是集群中的一小部分,并在发布完成后可立即访问。
    • 自动化测试: ThoughtWorks开发的Selenium
    • 预发布验证: 预发布服务器和线上正式服务器都部署在相同的物理环境中,相同的线上配置,依赖相同的外部服务。

      网站应用中一个处理错误的理念:快速失败(fast failed),即如果系统在启动时发现问题就立刻抛出异常,停止启动排查错误,而不是启动后执行错误操作。

    • 代码控制: 主干开发、分支发布(SVN); 分支开发、主干发布(Git)
    • 自动化发布:
    • 灰度发布: 将集群服务器分成若干部分,每次只发布一部分服务器,观察运行稳定再继续发布。
    • 网站运行监控

      不允许没有监控的系统上线

    • 监控数据采集

      • 用户日志采集
        • 服务器端日志收集 : Web服务器日志记录。
        • 客户端浏览器日志收集: JavaScript脚本、基于实时计算框架Storm的日志统计与分析工具。
      • 服务器性能监控: 收集服务器性能指标,开源服务器性能监测工具 Ganglia
      • 运行数据报告: 运行数据需要在具体程序中采集并报告
    • 监控管理 : 系统报警、失效转移、自动优雅降级
  • 3.3. 永无止境:网站的伸缩性架构(伸缩性)

    • 网站架构的伸缩性设计
    • 不同功能进行物理分离实现
    • 单一功能通过集群规模实现
    • 应用服务器集群的伸缩性设计

      Http请求分发装置可以感知或者可以配置集群的服务器数量,可以及时发现集群中新上线或新下线的服务器,并能向新上线的服务器分发请求,停止向已下线的服务器分发请求,实现应用服务器集群的伸缩性

    • HTTP重定向负载均衡: 利用HTTP重定向协议实现负载均衡。

    • DNS域名解析负载均衡: 利用DNS处理域名解析请求的同时进行负载均衡处理。
    • 反向代理负载均衡: Squid:基于Linux的开源反向代理服务器
    • IP负载均衡: 网络层通过修改请求目标地址
    • 数据链路层负载均衡: 在通信协议的数据链路层修改mac地址进行负载均衡。
      Linux平台最好的链路层负载均衡开源产品是LVS(Linux Virtual Server)

    • 分布式缓存集群的伸缩性设计

      计算机的任何问题都可以通过增加一个虚拟层来解决。

    • 分布式缓存的一致性hash算法 : hash环 + 虚拟层

    • 数据存储服务器集群的伸缩性设计
    • 关系数据库集群的伸缩性设计 : 主从复制、分库、分片
    • NOSQL数据库集群的伸缩性设计
      • NOSQL: 主要指非关系的,分布式的数据库设计模式。(Not Only SQL观点 只是关系数据库的补充,而不是替代方案。) NOSQL数据库产品放弃了关系数据库的两大重要基础:以关系代数为基础的结构化查询语言(SQL)和事务一致性保证(ACID)。而强化了高可用性和伸缩性。

    扩展性(Extensibility): 对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。表现在系统基础设施稳定不需要经常变更,应用之间较少依赖和耦合,对需求变更可以敏捷响应。是系统架构设计层面的开闭原则(扩展开放,修改关闭),架构设计考虑未来功能扩展,当系统增加新功能时,不需要对现有系统的结构和代码进行修改。
    伸缩性(Scalability): 系统能够通过增加(减少)自身资源规模的方式增强(减少)自己计算处理事务的能力。如果这种增减是成比例的,即作线性伸缩性。网站架构中,通常指利用集群方式增加服务器数量,提高系统的整体事务吞吐能力。

  • 3.4. 随需应变:网站的可扩展架构(扩展性)

    • 构建可扩展的网站架构

      低耦合是软件设计的终极目标之一,低耦合的系统更容易扩展,低耦合的模块更容易复用,低耦合的设计让开发过程和维护变得更轻松和容易管理。
      设计网站可扩展架构的核心思想是模块化,并在此基础之上,降低模块间的耦合性,提高模块的复用性。
      模块分布式部署以后具体聚合方式主要有分布式消息队列和分布式服务 。

    • 利用分布式消息队列降低系统耦合性

    • 事件驱动架构
      • 概念: 在低耦合的模块之间传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块间合作。(生产者消费者模式)
    • 分布式消息队列

      • 描述: 分布式消息队列可以看作将这种数据结构部署到独立的服务器上,应用程序可以通过远程访问接口使用分布式消息队列,进行消息存取操作,进而实现分布式异步调用。(ESB、 SOA 、 MySQL)

      分布式消息队列通过消息对象分解系统耦合性,不同子系统处理同一个消息;
      分布式服务则通过接口分解系统耦合性,不同子系统通过相同的接口描述进行服务调用。

    • 利用分布式服务打造可复用的业务平台

    • WebService与企业级分布式服务

      WebService缺点

      • 臃肿的注册与发现机制
      • 低效的XML序列化手段
      • 开销相对较高的HTTP远程通信
      • 复杂的部署与维护手段

      难以满足大型网站对系统高性能、高可用、易部署、易维护的要求。

    • 大型网站分布式服务的需求与特点
      • 分布式服务框架支持特性:
      • 负载均衡: 支持服务请求者使用可配置的负载均衡算法访问服务,使服务提供者集群实现负载均衡。
      • 失效转移: 当某个服务实例不可用,将访问切换到其他服务实例上,以实现服务整体高可用。
      • 高效的远程通信: 核心服务的调用次数会达到数以亿计。
      • 整合异构系统: 网站服务可能会使用不同的语言开发并部署不同的平台,分布式服务架构需要整合这些异构系统。
      • 对应用最少侵入: 服务模块本身需要支持可集中式部署,也可分布式部署。
      • 版本管理: 分布式服务框架需要支持服务多版本发布,服务提供者先升级接口发布新版本的服务,并同时提供旧版本的服务供请求者调用,当请求者调用接口升级后才可以关闭旧版本服务。
      • 实时监控: 监控服务提供者和调用者的各项指标,提供运维和运营支持。
    • 分布式服务框架设计 (参考 Thrift、Dubbo)
  • 来自为知笔记(Wiz)

    相关内容推荐