帮助Web应用性能提升10倍的10个建议

提升 Web 应用的性能变得越来越重要。线上经济活动的份额持续增长,当前发达世界中 5 % 的经济发生在互联网上(查看下面资源的统计信息)。 我们现在所处的时代要求一直在线和互联互通,这意味着用户对性能有更高的期望。如果网站响应不及时,或者应用有明显的延迟,用户很快就会跑到竞争者那边去。

例如,Amazon 十年前做的一项研究表明,网页加载时间减少 100 毫秒,收入就会增加 1%。最近另一项研究凸显了一个事实,就是有一半以上的受调查网站经营者说他们会因为应用的性能不好,而损失收入或客户。

一个网站需要多快?网页加载时间每增加 1 秒钟,就会有 4 % 的用户选择离开。顶尖的电子商务网站把第一次交互时间控制在 1-3 秒内,这样带来了很高的转换率。很明显 Web 应用性能的风险很高而且还在持续增长。

提升性能说起来容易,实现起来却很难。为了帮助大家,这篇文章提出了十个建议,可以让网站的性能提升 10 倍。本篇作为系列文章的第一篇,详细描述了如何借助一些验证过的优化技术和一点来自 NGINX 的帮助,就能提升应用的性能。该系列还概述了在安全性方面可能获得的改善。

建议一、利用反向代理服务器加速和保护应用

如果 Web 应用运行在一台独立的电脑上,性能问题的解决方案是显而易见的:换一台更快的电脑,里面加上更多的处理器、内存、快速磁盘阵列等等。然后在这台新电脑上运行 WordPress 服务、Node.js 应用、Java 应用等等,会比以前快很多。(如果应用需要访问服务器,方案还是很简单:换两台更快的电脑,用更快速的连接把它们连接起来。)

但电脑速度可能不是问题所在。通常 Web 应用运行缓慢,是由于电脑一直在不同的任务间切换:同成千上万的客户交互、访问磁盘上的文件、执行应用代码和其它的任务。应用服务器可能会因为下面这些问题而崩溃 —— 内存耗尽、把很多的数据从内存交换到磁盘上、以及很多请求都在等待一个类似磁盘 I/O 的单个任务。

你应该采用一种完全不同的方式,而不是升级硬件:增加一个反向代理服务器来分担这些任务。这台反向代理服务器设置在运行应用的电脑之前,用来处理网络流量。只有这台反向代理服务器直接连到网络上,它和应用服务器通过一个快速的内部网络进行通信。

利用这台反向代理服务器,应用服务器就不用等着和 Web 应用的用户进行交互,它可以专注在建立网页,并通过反向代理服务器把它们发送到网络上。因为应用服务器不必再等待客户的响应,所以能以最优的速度运行。

增加一台反向代理服务器也增加了 Web 服务器的弹性。如果一台服务器过载了,很容易增加另一台同类型的服务器。如果一台服务器宕机,也很容易把它换掉。

因为反向代理服务器带来的灵活性,它也成为了很多其它性能提升方法的先决条件,比如:

  • 负载均衡(查看 建议二)—— 反向代理服务器上运行一个负载均衡器,把流量平均分配给一堆应用服务器。由于负载均衡器的引入,在增加应用服务器时可以完全不用修改应用程序。
  • 缓存静态文件(查看 建议三)—— 直接请求的文件,比如图片或者代码文件,可以存在反向代理服务器上,并直接发送给客户端,这样可以更快地提供服务,分担了应用服务器的负载,可以让应用执行得更快。
  • 保护网站 —— 反向代理服务器可以设置较高的安全级别,通过监控进快速识别和响应攻击,这样就可以把应用服务器保护起来。

NGINX 软件是专门设计用做反向代理服务器的,具有上述这些附加功能。NGINX 利用事件驱动处理的方法,比其它传统的服务器更加高效。NGINX Plus 增加了更多反向代理的高级功能和支持,包含应用程序健康检查、特定请求路由和高级缓存等

建议二、增加一个负载均衡器

增加一个负载均衡器是一个相对简单的改动,而且会大幅度地改善网站的性能和安全性。你可以利用负载均衡器把业务分配给一些服务器,而不是建造一台更大更强的 Web 核心服务器。就算应用程序编写得很烂或者扩展性很差,负载均衡器都能提升用户体验而不需要任何其它的改动。

负载均衡器首先是一个反向代理服务器(查看建议一)—— 它接收网络流量,并把请求转交给另一个服务器。一个窍门就是让负载均衡器支持两台以上的应用服务器,利用一个选择算法在服务器间分配请求。最简单的方法就是轮询,每个新请求发送给列表中的下一台服务器。其它方法包括把请求发送给活动连接数量最少的服务器。NGINX Plus 可以在同一台服务器上维持一个给定的用户会话,这个功能被称为会话持久性。

负载均衡器可以极大地改善性能,因为它们避免让一台服务器过载,而其它服务器却处于空闲的状态。它们也很容易扩展 Web 服务器的能力,增加相对便宜的服务器并确保它们物尽其用。

负载均衡可以运用在很多协议上,包含HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、memcache,还有一些应用程序,包含基于 TCP 的应用和 L4 协议。分析 Web 应用使用了什么技术和性能落后在什么地方。

同一台服务器或者用于负载均衡的服务器,还能处理其他任务,包含 SSL 终端、支持客户端使用的 HTTP/1/x 和 HTTP/2、以及缓存静态文件。

NGINX 通常被用于负载均衡:想了解更多,请参考这些资料,一篇介绍性的文章、一篇关于配置的文章、一本电子书和相关的网络课程和相关文档。我们的商业版本(NGINX Plus),支持更多负载均衡的特殊功能,比如基于服务器响应时间的路由规划,和基于微软 NTLM 协议的负载均衡。(译者注:NTLM 是NT LAN Manager的缩写,NTLM 是 Windows NT 早期版本的标准安全协议。)

建议三、缓存静态和动态内容

缓存通过更快地向客户端提供内容来改善 Web 应用的性能。缓存包含一些策略:对内容预处理以便更快地发布、在更快的设备上保存内容、在更靠近客户端的地方保存内容,或者上述方法的组合。

有两种不同类型的缓存需要考虑:

  • 静态内容的缓存。不经常变化的文件,比如图像文件(JPEG,PNG)和代码文件(CSS,JavaScript),可以存在一个边缘服务器上,以便在内存或磁盘上进行快速检索。
  • 动态内容的缓存。很多 Web 应用为每个页面请求生成新的 HTML。通过简单地将已经生成 HTML的副本保存一小段时间,就可以大幅度减少需要生成页面的总数,发布这些已经生成的 HTML 副本已经足够满足需求了。

比如一个网页每秒有十次访问,把它缓存 1 秒钟,这个网页 90% 的请求都可以用缓存满足。如果你单独缓存静态内容,甚至最新生成的网页也会大量包含这些缓存的内容。

Web 应用生成缓存内容主要有三种技术:

  • 让内容更靠近用户。内容副本靠近用户,可以减少传输时间。
  • 把内容存在更快的电脑上。内容可以保存在更快的电脑上以便加快检索。
  • 把内容移出过载的电脑。有时候电脑运行一个特定任务比基准性能要慢,这是因为它同时还在忙其他任务。把缓存设置在另一台电脑上,都能提升有缓存资源和没有缓存资源的性能,因为这台主机不再过载了。

设置 Web 应用的缓存从 Web 应用服务器开始,是从内到外来实现的。首先,缓存动态内容,减轻了应用服务器的负担。接下来,缓存静态内容(包括原本是动态内容的临时副本),进一步分担应用服务器的负担。然后把缓存从应用服务器移到更快的、距离用户更近的电脑上,这样卸下了应用服务器的负担,减少了检索和传输的时间。

提高缓存可以大大加快应用程序。大多数网页中,一半以上的内容都是静态数据(比如大的图像文件)。在没有缓存的情况下,检索和传输数据可能要花费好几秒钟,但如果数据缓存在本地,只需要几分之一秒就可以。

举一个例子说明实际上如何使用缓存,NGINX 和 NGINX Plus 用两条指令来创建缓存:proxy_cache_path 和 proxy_cache。你指定了缓存的位置和大小、文件保存在缓存的最长时间和其它参数。使用的第三条指令(也相当常用),proxy_cache_use_stale,甚至可以在服务器忙碌或挂掉而不能提供最新内容的情况下,由缓存直接提供过期的内容,给客户端提供一些东西总比什么都没有强。从用户的角度来看,这会大大改善网站和应用的正常运行时间。

NGINX Plus 有一些高级的缓存功能,包括支持缓存清除,和将缓存状态可视化并显示在 dashboard 上,用于监控实时活动。

关于 NGINX 缓存的更多信息,可以参考相关文档和 《NGINX Plus 管理指南》的「NGINX 内容缓存」章节。

注意:缓存跨越了组织间的界限,让从事应用开发的人、进行资本投资决策的人和维护网站的人都参与其中。成熟的缓存策略就像这里提到的,很好得体现了DevOps 方式的价值,也就是应用程序员、架构师和运维人员等各方力量都团结起来,努力达成对网站的功能、响应时间、安全性和业务结果(比如完成的交易量或销售额)的要求。

(译者注:DevOps 不仅仅是一种软件的部署方法。 它通过一种全新的方式,来思考如何让软件的作者(开发部门)和运营者(运营部门)进行合作与协同。)

建议四、压缩数据

压缩是一个有巨大潜能的性能加速器。已经有很多精心设计和高效的压缩标准,有针对图像的(JPEG 和 PNG)、视频的(MPEG-4)、音乐的(MP3)等等。这些标准都可以大幅减少文件的大小。

文本数据 —— 包含 HTML(包含了纯文本和 HTML 标签)、CSS 和类似 JavaScript 的代码,这些数据通常不经过压缩就进行传输了。压缩这些数据会大大改善对 Web 应用性能的体验,特别是那些连接缓慢或受限的移动客户端。

这是因为用户在和网页交互时,文本数据通常已经足够了,而多媒体数据就需要更多的支持。智能内容压缩可以减少 HTML、Javascript、CSS 和其它文本内容对带宽的要求,通常是 30% 或者更多,从而减少加载时间。

如果使用 SSL,压缩可以减少 SSL 加密的数据量,从而减少一些 CPU 时间。(译者注:SSL,Security Socket Layer,加密套接字层,一种加密的通讯协议,用在客户端与服务器之间。参考建议五。)

压缩文本数据的方法有所不同。比如,本文的 HTTP/2 章节提到的一种新颖的文本压缩方案,专门用来压缩头部数据。另一个例子是可以在 NGINX 中打开 GZIP。对文本数据进行预先压缩后,可以通过 gzip_static 指令直接提供 .gz 的压缩文件(给客户端)。

建议五、优化 SSL/TLS

加密套接字层(SSL)协议及其后继者 —— 传输层安全(TLS)协议,被越来越多得的网站所采用。SSL/TLS 加密了服务器发送给用户的数据,提升了网站的安全性。影响这一趋势的部分原因是,Google 现在提升了启用 HTTPS 网站的搜索排名。

尽管 SSL/TLS 越来越普遍,它们却是影响许多网站性能的症结所在。SSL/TLS 降低网站性能有两个原因:

  1. 每当打开一个新的连接,最初的握手都需要建立加密密钥。浏览器使用 HTTP/1.x 和服务器建立多条连接,随着服务器的增多,连接会成倍增加。
  2. 服务器上加密数据,客户端解密数据,这些都是持续的开销。

为了鼓励使用 SSL/TLS,HTTP/2 和 SPDY (在下一章节详细介绍)的作者在设计协议时,让每个浏览器会话只使用一个连接。这样大大减少了 SSL 开销的一个重要来源。但是,在提升基于 SSL/TLS 的应用性能方面,还是有很多可以做的事情。

优化 SSL/TLS 的机制因 Web 服务器而有所差别。比如,NGINX 使用 OpenSSL,运行在标准硬件上,提供类似专用硬件解决方案的性能。NGINX SSL 性能解决方案有详细的文档、减少了 SSL/TLS 加解密对 CPU 和 时间的消耗。

此外,这篇文章中还详细介绍了提升 SSL/TLS 性能的各种方式。简单总结一下,这些技术包括:

  • 会话缓存。使用 ssl_session_cache 指令,缓存 SSL/TLS 加密每个新连接所使用的参数。
  • 会话标签或 ID。这些特定 SSL/TLS 会话信息都存在一个标签或 ID 中,所以可以顺畅地重用一个连接,而不需要再次握手。
  • OCSP 封装。缓存 SSL/TLS 证书信息,来缩短握手时间。(译者注:OCSP,Online Certificate Status Protocol,在线证书状态检查协议(RFC6960),用来向 CA 站点查询证书状态,比如是否撤销。通常情况下,浏览器使用 OCSP 协议发起查询请求,CA 返回证书状态内容,然后浏览器接受证书是否可信的状态。这个过程非常消耗时间,因为 CA 站点有可能在国外,网络不稳定,RTT 也比较大。那有没有办法不直接向 CA 站点请求 OCSP 内容呢?OCSP 封装(stapling) 就能实现这个功能。简单原理就是浏览器发起 client hello 时会携带一个 certificate status request 的扩展,服务器看到这个扩展后将 OCSP 内容直接返回给浏览器,完成证书状态检查。由于浏览器不需要直接向 CA 站点查询证书状态,这个功能对访问速度的提升非常明显。 )

NGINX 和 NGINX Plus 可以用在 SSL 或 TLS 终端上 —— 当和其它服务器进行明文通信时,对客户端流量进行加解密。按照这些步骤设置 NGINX 或 NGINX Plus,就能用在 SSL 或 TLS 终端上。当用在接受 TCP 连接的服务器上,NGINX Plus 还有特别的设定步骤。

建议六、实现 HTTP/2 或 SPDY

对于已经使用 SSL/ TLS 的网站而言,因为 HTTP/2 和 SPDY 中的一个连接只需要一次握手,所以它们很有可能提升性能。对于没有使用 SSL/TLS 的网站,改到 SSL/TLS 会让性能变慢, 而 HTTP/2 和 SPDY 对 SSL/TLS 的性能改进,就和性能下降的效果抵消了。

(译者注:SPDY,一种开放的网络传输协定,由Google开发,用来传送网页内容。基于传输控制协议(TCP)的应用层协议 。Google最早是在Chromium中提出该协议。目前已经被用于Google Chrome浏览器中来访问Google的SSL加密服务。SPDY并不是首字母缩略字,而仅仅是”speedy”的缩写。)

Google 在 2012年 引入 SPDY ,以实现比 HTTP/1. x 更快的性能。HTTP/2 基于 SPDY,最近刚被采纳为 IETF 标准。SPDY 已被广泛支持,不过很快就要被HTTP/2 所取代。

SPDY 和 HTTP/2 的关键特性是仅用一条单一连接而不是多条连接。这条连接是被复用的,同时可以有多个请求和应答在上面传输。

这些协议充分发挥了单条连接的最大功效,避免了 HTTP/1.x 需要建立和管理多条连接的开销。使用单条连接对于 SSL 特别有帮助,因为这样最大程度地减少了 SSL/TLS 建立一个安全连接所需的握手次数,因为握手通常是比较耗时的。

SPDY 协议需要使用到 SSL/TLS,HTTP/2 的官方说法是不需要用到它们,但是目前支持 HTTP/2 的浏览器只有在 SSL/TLS 被打开的情况下,才会用到 SSL/TLS。也就是说,只有当一个网站使用 SSL 并且它的服务器接受 HTTP/2 流量时,一个支持 HTTP/2 的浏览器才可以使用 SSL/TLS。否则,这个浏览器还是基于 HTTP/1.x 进行通信。

一旦实现了 SPDY 或者 HTTP/2,你就不再需要传统的 HTTP 性能优化方法,比如区域切分、资源整合和雪碧图。(译者注:image spriting,工作原理是一堆的图像(称为“sprites”,精灵)合并成一张大的图像(国内称为雪碧图),以达到减少 HTTP 的请求数量)这些改动让代码和部署变得更加简单,也更容易管理。要了解 HTTP/2 上相关改动的更多信息,可以参考这篇白皮书。

NGINX 作为支持这些协议的一个例子,从一开始就支持 SPDY,目前很多使用 SPDY 的网站都在运行 NGINX。 NGINX很早就支持 HTTP/2 了,2015 年 9 月 NGINX 的开源版本 和 NGINX Plus 就已经支持了。

我们 NGINX 希望有朝一日大部分网站都可以使用 SSL,并迁移到 HTTP/2。这会提升安全性,同时由于找到和实现了新的优化方法,代码会更加简洁而且性能更好。

建议七、更新软件版本

一个提升应用性能的简单方法,就是为软件技术栈选择稳定的、性能好的组件。此外,高质量组件的程序员愿意加班追求性能的提升和尽快修正 bug,所以最好使用软件最新的稳定版本。新的发布会得到程序员和用户社区的更多关注。新版本还会利用最新的编译器优化技术,包含对新硬件的优化。

稳定的新版本通常都兼容老版本,而且有更好的性能。如果你持续更新软件,很容易享受到性能优化、bug 修正和安全报警等诸多好处。

一直使用软件的老版本,还会让你不能使用到新功能。比如,上面提到的 HTTP/2 现在需要使用 OpenSSL 1.0.1。从 2016 年中开始,HTTP/2 就需要使用 OpenSSL 1.0.2,OpenSSL的这个版本是在 2015 年 1 月发布的。

NGINX 用户可以使用最新版本的 NGINX 开源软件或者 NGINX Plus,新功能都包含其中,比如套接字切分和线程池(查看下面),而且性能还在持续优化中。接下来仔细查看技术栈的软件,并尽可能快地使用最新的版本。

建议八、优化 Linux 性能

现在大多数 Web 服务器的底层操作系统都是基于 Linux 的,所以 Linux 作为基础设施的基础,在性能提升方面有很大的空间。默认情况下,很多 Linux 系统被优化成尽可能少地占用资源,以便适应通常的桌面工作。这意味着 Web 应用程序用例至少需要进行最大性能的优化。

Linux 针对 Web 服务器所做的优化。以 NGINX 为例,在加速 Linux 时,需要考虑这些重要的改动:

  • 缓冲队列。如果有的连接看上去没有响应了,试着增大 net.core.somaxconn 看看,这个参数代表可以排队等待的最大连接数。如果已存在的连接限制太小,你会看到错误消息,可以逐渐增大参数直至错误消息消失。
  • 文件描述符。NGINX 在每个连接上使用两个文件描述符。如果系统要服务很多连接,需要增大 sys.fs.file_max 和 nofile 这两个参数以应对增加的负载,前者是系统范围内文件描述符的限制,后者是用户文件描述符的限制。
  • 临时端口。当作为代理时,NGINX 为每个上行服务器创建了临时端口。你可以通过设定 net.ipv4.ip_local_port_range,来增加端口值的可用范围。你还可以设定 net.ipv4.tcp_fin_timeout,减少超时来重新使用一个不活跃的端口,以便更快地周转。

你可以查看《NGINX 性能优化指南》(伯乐在线正在翻译中),了解如何优化 Linux 系统,以便能毫不费力地处理大量的网络流量。

建议九、优化 Web 服务器的性能

无论你使用哪一种 Web 服务器,都需要为 Web 应用性能对它进行优化。下面的建议普遍适用于任何一个 Web 服务器,但有一些是针对 NGINX 的特别设定。这些优化的关键点包括:

  • 访问日志。可以把请求记录先缓存在内存中,然后一起写入磁盘,而不是把每笔请求立刻写到磁盘上。NGINX 使用 access_log 指令和 buffer=size 参数,在内存缓冲填满时,把日志记录写入磁盘。可以使用 flush=time 参数,在特定时间后将缓冲内容写入磁盘。
  • 缓冲区。缓冲区可以将一部分应答保存在内存中,直至缓冲被填满了,这样会让与客户端之前的通信更加高效。不能存入内存中的应答被写入磁盘,这样会导致性能的下降。当 NGINX 缓冲打开的时候,你可以通过 proxy_buffer_size 和 proxy_buffer 这两个指令来进行管理。
  • 客户端保活时间。保持连接可以减少开销,特别是使用 SSL/TLS 的时候。在 NGINX 上,你可以通过增加 keepalive_request 的最大数量,来设定客户端在指定连接上的请求数量,这个参数的默认值是 100 ,你还可以增加 keepalive_timeout 让连接在打开状态上持续得更久一些,从而更快地响应后续的请求。
  • 上行保活时间。上行连接也就是指连到应用服务器、数据库服务器等这些连接,它们也可以从保持连接中受益。对于上行连接,你可以增大 keepalive,这个参数表示每个工作进程中有多少空闲的保活连接是处于打开状态的。这样会增加重用连接的数量,减少打开全新连接的需求。保活的更多信息,参考这篇文章。
  • 限制。限制客户端所使用的资源也能提升性能和安全性。NGINX 可以通过 limit_conn 和 limit_conn_zone 指令限制一个给定源的连接数量,limit_rate 指令则用来限定带宽。这些设定可以阻止一个合法用户“占用”资源,也可以防止攻击。limit_req 和 limit_req_zone 指令限制客户端的请求。对于上行服务器的连接而言,可以在上行配置段中,使用 server 指令和 max_conns 参数。这样限制了连接到上行服务器的数量,可以防止过载。相关的 queue 指令创建了一个队列,当 max_conns 限制超过时,可以在一定时间内保存一定数量的请求。
  • 工作进程。工作进程负责处理请求。NGINX 采用了基于事件的模型,以及和操作系统相关的机制,高效地把请求分配给工作进程。work_processes 的推荐值是在每个 CPU 上设定为 1。绝大多数系统出于需要,会在保证安全的前提下提高 work_connections (默认值 512)的最大值,你可以通过实验来找到适合系统的值。
  • 套接字切分。通常用一个单独的监听套接字将新连接分配给各个工作进程。套接字切分会为每个工作进程创建一个监听套接字,当监听套接字可用时,内核会把连接分配给它们。这样在多核系统中可以减少对锁的竞争和提升性能。执行 listen 指令时配合 reuseport 参数,就可以打开套接字切分的功能。
  • 线程池。任何一个计算机进程都可能被一个慢速操作所拖累。对 Web 服务器软件来说,访问磁盘会拖累很多快速的操作,比如在内存上进行计算或者复制信息。当一个线程池被引入,可以把这个慢速操作分配给一个独立的任务,主进程仍然处理快速操作。磁盘操作完成后,结果再返回给主进程。 在 NGINX 中会把 read() 和 sendfile() 这两个系统调用分散到线程池上。

小提示:当改动任何系统或服务上的设定时,一次只修改一个设定,然后再测试性能。如果这个改动造成问题,或者没有让网站变快,把它改回来就好了。

关于优化 NGINX 的更多信息,请参考这篇文章。

建议十、监控实时活动来解决问题和瓶颈

开发和发布高性能应用的关键,在于密切和实时地关注应用程序在现实情况下的性能。你必须能够监控特定设备的活动和网站的基础设施。

大多数监控网站的活动都很被动 —— 它只告诉你将会发生什么,让你自己去发现问题和解决问题。

监控可以抓到不同类型的问题。它们包含:

  1. 服务器宕机。
  2. 服务器不稳定,容易掉线。
  3. 服务器大概率出现缓冲失效。
  4. 服务器发送的内容不正确。

你可以使用 New Relic 或 Dynatrace 这种全球性的应用性能监控工具,来监控遥远地方加载页面的时间,也可以利用 NGINX 监控应用程序的发布。当你考虑是否需要给基础设施扩容来维持流量时,应用性能数据可以告诉你这些优化是否真能给用户带来很大的改善。

NGINX Plus 增加了检查应用程序健康的功能 —— 综合一些定期重复性的操作,以及在问题发生时报警,这样可以快速地定位和解决问题。NGINX Plus 还有会话耗尽功能 —— 当任务完成后终止新的连接,以及慢启动的能力 —— 允许负载均衡集群中的一台服务器,从刚修复的状态慢慢赶上来。如果使用得当,健康检查可以在发生影响用户体验的重大问题前,就定位出问题。会话耗尽和慢启动,允许更换服务器,并保证在过程中不会对性能和正常的运行时间造成不好的影响。下图是一个在 NGINX Plus 中集成了实时活动监控的 dashboard,上面显示了Web 基础设施和服务器、TCP 连接以及缓存等相关信息。

总结:如何看到性能提升 10 倍

相关推荐