本书通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,作者为李智慧

1 性能优化

1 Web 前端性能优化

  • 浏览器优化访问
    • 减少 http 请求。主要是合并 css,合并 js,合并图片。将浏览器一次访问所需要的 js,css 合并成一个文件。
    • 使用浏览器缓存。css,js, logo, 图标等静态资源文件更新都比较低,而这些文件几乎又是每次 http 请求都需要的。通过设置 HTTP 头中的 Cache-Control, Expires 的属性,可设定浏览器缓存。
    • 启用压缩。在服务端对文件进行压缩,在浏览器端对文件进行解压缩,可以有效减少通信传输的数据量。对 html, css, js 文件启用 GZip 压缩可以达到较好的效果。但是压缩对服务器和浏览器会产生一定的压力。
    • css 放在页面最上面,js 放在页面最下面。浏览器会在下载完全部 css 之后才对整个页面进行渲染。浏览器在加载 js 后立即执行,有可能会造成页面显示缓慢。
    • 较少 Cookie 传输。要慎重选择哪些数据写入到 Cookie 中。
  • CDN 加速
  • 反向代理
    • 反向代理缓存。
    • 实现负载均衡。

2 应用服务器性能优化

  • 缓存 优先考虑使用缓存优化性能
  • 合理使用缓存 频繁修改的数据,没有热点的数据要考虑是否有缓存的意义。
  • 缓存预热 新启动的缓存系统可以加载好热点数据。
  • 缓存穿透 如果因为不恰当的业务,或者恶意攻击持续高并发的请求某个不存在的数据,由于缓存中没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大的压力。一个简单的对策是把不存在的数据也缓存起来,其值为 null。
  • 使用分布式缓存 比如 Memcached。
  • 异步操作 使用消息队列将调用异步化。将用户的请求数据发送到消息队列后立即返回,再由消息队列的消费者进程获取消息,异步写入数据库。
  • 使用集群 使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问分发到多台服务器上处理。避免单一服务器因负载压力过大而响应缓慢。

2 软件质量保证

1 代码控制

  • 分支开发,主干发布
  • 任何修改都不得在主干上直接进行,需要开发一个新功能或修复一个 BUG 时, 从主干拉一个分支进行开发,开发完成且测试通过后,再合并回主干,然后从主干进行发布。

2 自动化发布

  • 开发自动化发布工具实现发布过程的自动化。自动构造代码分支,进行代码合并,执行发布脚本。

3 灰度发布

  • 采用灰度发布模式,将集群服务器分成若干部分,每天只发布一小部分,待观察运行稳定没有故障之火,再继续发布一部分服务器。
  • 如果出现问题,只要回滚已发布的一部分服务器即可。

4 网站运行监控

  • 不允许没有监控的系统上线。
  • 监控数据采集
    • 用户行为日志收集。指用户在浏览器上所有的操作及其所在的操作环境,包括用户操作系统与浏览器信息,IP 地址,页面访问路径,页面停留时间等。这些数据对统计网站的 PV/UV 指标,分析用户行为,优化网站设计,个性化营销与推荐等都非常重要。
    • 通过服务器端日志收集,大部分 web 服务器都具备日志记录功能,比如 Apache。
    • 通过客户端浏览器日志收集,通过在页面嵌入专门的 js 代码收集用户真实的操作行为,比服务器日志收集更加的精准。
    • 随着日志数据量变大,数据存储与计算压力变大。目前许多网站逐步开发基于实时计算框架 Storm 的日志统计与分析工具。
  • 服务器性能监控
    • 收集服务器性能指标,如系统 Load,内存占用,磁盘 IO,网络 IO 等。
  • 运行数据报告
    • 比如缓存命中率,平均响应延迟时间等。

3 伸缩性设计

1 按功能物理分离

  • 不同功能进行分离。比如前台,后台,注册,登陆都分离开立,只是用链接相连。

2 负载均衡

  • 负载均衡
    • 是用 DNS 域名解析实现负载均衡。利用域名解析做为第一级负载均衡手段。
    • 是用反向代理实现负载均衡。
  • 负载均衡算法
    • 轮询。所有请求被依次分发到每台应用服务器上,即每台服务器需要处理的请求数目都相同,适合于所有服务器硬件都相同的场景。
    • 加权轮询。在高性能的服务器上分配更多的请求。
    • 最少连接。记录每个应用服务器正在处理的连接数,将新到的请求分发到最少连接的服务器上。
    • 源地址散列。根据请求的 IP 地址进行 Hash 计算,得到应用服务器,这样请求来自于同一个 IP 地址的请求总在同一台服务器上处理,请求的上下文信息可以存储在这台服务器上,在一个会话周期内重复使用。

3 分布式缓存

  • 要注意解决新增一台缓存服务器对缓存命中的影响。

4 可扩展设计

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

  • 如果模块之间不直接调用,那么新增模块或者修改模块就对其它模块影响最小。
  • 消息生产者应用程序通过远程访问接口将消息推送给消息队列服务器,消息队列服务器将消息写入本地内存队列后立即返回成功响应给消息生产者。消息队列服务器根据消息订阅列表查找订阅该消息的消息消费者程序,将消息队列中的消息按照先进先出的原则将消息通过远程通信接口发送给消息消费者程序。

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

  • 拆分。纵向拆分,将一个大应用拆分为多个小应用,甚至可以独立部署。横向拆分,将复杂的业务拆分出来,独立部署为分布式服务。
  • 负载均衡。要能够支持服务请求者使用可配置的负载均衡算法访问服务。
  • 失效转移。可复用的服务通常会被多个应用调用,一旦该服务不可用,就会影响到很多应用的可用性。对于大型网站的分布式服务而言,即使是很少访问的简单服务,也需要集群部署,提供失效转移机制。