技术架构:十个10倍应用程序性能提升的技巧

提高web应用程序性能比以往任何时候都更加重要。在线经济活动的份额正在增长;超过5%的发达国家的经济现在是在互联网上的(参见参考资料中的互联网统计数据)。而我们这个始终在线、高度连接的现代世界意味着用户的期望比以往任何时候都要高。如果您的站点没有立即响应,或者您的应用程序不能立即工作,用户将很快转向您的竞争对手。

例如,亚马逊近10年前的一项研究证明,即使在那时,页面加载时间每减少100毫秒,收入也会增加1%。最近的另一项研究强调了这样一个事实:超过一半的受访网站所有者表示,由于应用程序性能不佳,他们失去了收入或客户。

一个网站需要多快?每加载一个页面一秒钟,大约有4%的用户会放弃它。顶级电子商务网站提供从1秒到3秒的首次互动时间,这提供了最高的转化率。很明显,web应用程序性能的风险很高,而且可能还会增加。

想要提高性能很容易,但实际看到结果却很难。为了帮助你的旅程,这篇博客文章为你提供了10个技巧,帮助你将网站性能提高10倍。这是一个系列文章的第一部分,详细介绍了如何在一些经过良好测试的优化技术的帮助下,并在NGINX的支持下,提高应用程序的性能。本系列还概述了在此过程中可能获得的安全性改进。

技巧1 -使用反向代理服务器加速并保护应用程序


如果您的web应用程序在一台机器上运行,那么性能问题的解决方案可能很明显:使用一台更快的机器,拥有更多处理器、更多RAM、更快的磁盘阵列,等等。然后,新机器可以运行您的WordPress服务器,Node.js应用程序,Java应用程序等,比以前更快。(如果您的应用程序访问数据库服务器,解决方案可能看起来仍然很简单:获得两台更快的机器,以及它们之间更快的连接。)

问题是,机器的速度可能不是问题所在。Web应用程序通常运行缓慢,因为计算机在不同类型的任务之间切换:在数千个连接上与用户交互、从磁盘访问文件、运行应用程序代码等等。应用程序服务器可能会崩溃——耗尽内存、将内存块交换到磁盘,并让许多请求等待磁盘I/O等单个任务。

您可以采用完全不同的方法,而不是升级硬件:添加反向代理服务器来卸载这些任务。反向代理服务器位于运行应用程序的机器前面,处理Internet流量。只有反向代理服务器直接连接到Internet;与应用服务器的通信是通过一个快速的内部网络进行的。

使用反向代理服务器可以让应用服务器从等待用户与web应用程序交互的过程中解放出来,并让它集中精力构建页面,以便反向代理服务器通过Internet发送。不再需要等待客户机响应的应用程序服务器可以以接近优化基准测试的速度运行。

添加反向代理服务器还可以增加web服务器设置的灵活性。例如,如果一个给定类型的服务器被重载,可以很容易地添加另一个相同类型的服务器;如果服务器宕机,可以很容易地替换它。

由于它提供的灵活性,反向代理服务器也是许多其他性能提升功能的先决条件,比如:

负载平衡(参见技巧2)——负载平衡器运行在反向代理服务器上,以便在多个应用服务器之间均匀地共享流量。有了负载平衡器,您就可以添加应用程序服务器,而不需要更改您的应用程序。
缓存静态文件(参见技巧3)——直接请求的文件,如图像文件或代码文件,可以存储在反向代理服务器上,并直接发送到客户机,这样可以更快地为资产提供服务,并卸载应用程序服务器,从而使应用程序运行得更快。
保护您的站点——反向代理服务器可以配置为高安全性,并进行监视,以便快速识别和响应攻击,保护应用程序服务器。
NGINX软件是专门为用作反向代理服务器而设计的,具有上面描述的附加功能。NGINX使用事件驱动的处理方法,这比传统服务器更有效。NGINX Plus添加了更高级的反向代理特性,比如应用程序健康检查、特殊的请求路由、高级缓存和支持。


技巧2 -添加一个负载平衡器
添加负载平衡器是一个相对容易的更改,它可以显著提高站点的性能和安全性。不需要使核心web服务器更大更强大,而是使用负载平衡器在多个服务器之间分配流量。即使应用程序编写得很差,或者存在伸缩性问题,负载平衡器也可以在不进行任何其他更改的情况下改善用户体验。

首先,负载均衡器是一个反向代理服务器(请参阅技巧1)——它接收Internet流量并将请求转发到另一台服务器。诀窍在于负载均衡器支持两个或多个应用程序服务器,使用多种算法在服务器之间分割请求。最简单的负载平衡方法是轮询,将每个新请求发送到列表上的下一个服务器。其他方法包括向活动连接最少的服务器发送请求。NGINX Plus具有在同一服务器上继续给定用户会话的功能,这称为会话持久性。

负载平衡器可以极大地提高性能,因为当其他服务器等待流量时,它们可以防止一个服务器过载。它们还可以方便地扩展web服务器的容量,因为您可以添加成本相对较低的服务器,并确保它们将得到充分利用。

可以负载平衡的协议包括HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、memcached,以及其他几种应用程序类型,包括基于TCP的应用程序和其他第4层协议。分析您的web应用程序,以确定您使用的是哪种应用程序,以及在哪些地方性能比较差。

用于负载平衡的同一或多个服务器还可以处理其他几个任务,比如SSL终止、对HTTP/1的支持。客户端使用x和HTTP/2,并缓存静态文件。

NGINX通常用于负载平衡。要了解更多,请下载我们的电子书,选择软件负载平衡器的五个理由。您可以使用NGINX和NGINX Plus获得负载平衡的基本配置说明,第1部分以及NGINX Plus管理指南中的完整文档。NGINX Plus是我们的商业产品,支持更专业的负载平衡特性,比如基于服务器响应时间的负载路由,以及基于微软NTLM协议的负载平衡能力。

技巧3 -缓存静态和动态内容
通过更快地将内容交付给客户机,缓存提高了web应用程序的性能。缓存可以包括几种策略:在需要时对内容进行预处理以实现快速交付、将内容存储在更快的设备上、将内容存储在离客户机更近的地方,或者组合使用。

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

静态内容缓存——不经常更改的文件,如图像文件(JPEG、PNG)和代码文件(CSS、JavaScript),可以存储在边缘服务器上,以便从内存或磁盘快速检索。
缓存动态内容——许多Web应用程序为每个页面请求生成新的HTML。通过在短时间内缓存生成的HTML的一个副本,您可以显著减少必须生成的页面总数,同时仍然交付足够新鲜的内容来满足您的需求。
例如,如果一个页面每秒有10个视图,而您将其缓存1秒,那么对该页面的90%的请求将来自缓存。如果单独缓存静态内容,即使是新生成的页面版本也可能主要由缓存的内容组成。

缓存web应用程序生成的内容有三种主要技术:

将内容移动到离用户更近的地方——将内容的副本保持在离用户更近的地方,可以减少其传输时间。
将内容移动到更快的机器上——内容可以保存在更快的机器上,以便更快地检索。
将内容从过度使用的机器上移开——机器有时在特定任务上的运行速度比基准测试慢得多,因为它们忙于其他任务。在不同的机器上进行缓存可以提高缓存资源的性能,也可以提高非缓存资源的性能,因为主机的过载更少。
web应用程序的缓存可以从内部(web应用程序服务器)到外部实现。首先,缓存用于动态内容,以减少应用服务器上的负载。然后,缓存用于静态内容(包括动态内容的临时副本),进一步卸载应用服务器。然后缓存将从应用服务器转移到速度更快和/或更接近用户的机器上,从而减轻应用服务器的负担,减少检索和传输时间。

改进的缓存可以极大地加快应用程序的速度。对于许多web页面,静态数据(如大型图像文件)占内容的一半以上。在没有缓存的情况下,检索和传输这样的数据可能需要几秒钟,但是如果数据是本地缓存的,那么只需要几秒钟。

作为在实践中如何使用缓存的示例,NGINX和NGINX Plus使用两个指令来设置缓存:proxy_cache_path和proxy_cache。您可以指定缓存位置和大小、缓存中保存的最大时间文件以及其他参数。使用第三个(也是非常流行的)指令proxy_cache_use_陈腐,您甚至可以在提供新鲜内容的服务器繁忙或宕机时直接使用缓存来提供陈旧的内容,从而为客户机提供一些内容,而不是什么也没有。从用户的角度来看,这可能会极大地提高站点或应用程序的正常运行时间。

NGINX Plus具有高级缓存功能,包括支持缓存清除和在仪表板上显示缓存状态,以便实时监控活动。

有关NGINX缓存的更多信息,请参阅参考文档和NGINX Plus管理指南。

注意:缓存跨越了开发应用程序的人员、进行资本投资决策的人员和实时运行网络的人员之间的组织界线。复杂的缓存策略(如这里提到的那些)是DevOps透视图价值的一个很好的例子,在DevOps透视图中,应用程序开发人员、体系结构和操作透视图被合并,以帮助满足站点功能、响应时间、安全性和业务结果(如完成的事务或销售)的目标。

技巧4 -压缩数据
压缩是一个巨大的潜在性能加速器。对于照片(JPEG和PNG)、视频(MPEG - 4)和音乐(MP3)等,都有精心设计和高效的压缩标准。这些标准中的每一个都将文件大小减少一个数量级或更多。

文本数据——包括HTML(包括纯文本和HTML标记)、CSS和JavaScript等代码——通常是未压缩传输的。压缩这些数据可能会对web应用程序的性能产生不成比例的影响,特别是对于移动连接缓慢或受限的客户端。

这是因为文本数据通常足以让用户与页面交互,而在页面中,多媒体数据可能更具支持性或装饰性。智能内容压缩可以减少HTML、Javascript、CSS和其他基于文本的内容的带宽需求,通常可以减少30%或更多,并相应地减少加载时间。

如果使用SSL,压缩会减少必须经过SSL编码的数据量,从而抵消了压缩数据所需的一些CPU时间。

压缩文本数据的方法各不相同。例如,请参阅技巧6了解SPDY和HTTP/2中的一个新的文本压缩方案,该方案专门针对头数据进行了调整。作为文本压缩的另一个例子,您可以在NGINX中打开GZIP压缩。在预压缩服务上的文本数据之后,可以使用gzip_static指令直接提供压缩后的.gz文件。

技巧5 -优化SSL/TLS
安全套接字层(SSL)协议及其后续协议传输层安全(TLS)协议正在越来越多的网站上使用。SSL/TLS对从源服务器传输到用户的数据进行加密,以帮助提高站点安全性。影响这一趋势的部分原因是,谷歌现在使用SSL/TLS作为对搜索引擎排名的积极影响。

尽管越来越受欢迎,但SSL/TLS涉及的性能问题仍然是许多站点的症结所在。SSL/TLS降低网站性能有两个原因:

每当打开新连接时,建立加密密钥所需的初始握手。浏览器使用HTTP/1的方式。为每台服务器建立多个连接。
在服务器上加密数据和在客户机上解密数据的持续开销。
为了鼓励使用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——这些信息存储在票证或ID中关于特定SSL/TLS会话的信息,这样就可以顺利地重用连接,而不需要新的握手。
通过缓存SSL/TLS证书信息,减少握手时间。
NGINX和NGINX Plus可用于SSL/TLS终止——处理客户机流量的加密和解密,同时与其他服务器进行明文通信。要设置NGINX或NGINX Plus来处理SSL/TLS终止,请参阅HTTPS连接和加密TCP连接的说明。

技巧6 -实现HTTP/2或SPDY
对于已经使用SSL/TLS、HTTP/2和SPDY的站点,很可能会提高性能,因为单个连接只需要一次握手。对于还没有使用SSL/TLS的站点,HTTP/2和SPDY将迁移到SSL/TLS(这通常会降低性能),从响应性的角度来看,这是一种洗刷。

谷歌在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时才使用它。也就是说,支持HTTP/2的浏览器只有在网站使用SSL且服务器接受HTTP/2流量时才使用它。否则,浏览器通过HTTP/1.x进行通信。

当您实现SPDY或HTTP/2时,您不再需要典型的HTTP性能优化,例如域分片、资源合并和图像spriting。这些更改使您的代码和部署更简单、更容易管理。要了解更多关于HTTP/2带来的变化,请阅读我们的白皮书《Web应用程序开发人员的HTTP/2》。

「技术架构」10个10倍提升应用程序性能的技巧
作为支持这些协议的一个例子,NGINX从一开始就支持SPDY,现在大多数使用SPDY的站点都运行在NGINX上。NGINX也是HTTP/2支持的先驱,截至2015年9月,NGINX开源和NGINX Plus都支持HTTP/2。

随着时间的推移,我们NGINX希望大多数站点能够完全启用SSL并迁移到HTTP/2。这将导致安全性的提高,并且,随着新的优化的发现和实现,更简单的代码执行得更好。

技巧7 -更新软件版本
提高应用程序性能的一个简单方法是根据组件的稳定性和性能为软件堆栈选择组件。此外,由于高质量组件的开发人员可能会追求性能增强并随着时间的推移修复bug,因此使用最新的稳定版本的软件是值得的。新版本得到了开发人员和用户社区的更多关注。更新的构建还利用了新的编译器优化,包括针对新硬件的调优。

稳定的新版本通常比旧版本更兼容,性能更高。当您关注软件更新时,更容易掌握调优优化、bug修复和安全警报。

使用旧的软件也会阻止您利用新功能。例如,上面描述的HTTP/2目前需要OpenSSL 1.0.1。从2016年年中开始,HTTP/2将需要于2015年1月发布的OpenSSL 1.0.2。

NGINX用户可以从移动到最新版本的NGINX或NGINX Plus开始;它们包括新的功能,如套接字分片和线程池(请参阅技巧9),并且都在不断地进行性能调优。然后深入了解您的堆栈中的软件,并尽可能地使用最新的版本。

技巧8 -调优Linux的性能
Linux是当今大多数web服务器实现的底层操作系统,作为基础设施的基础,Linux代表着提高性能的重要机会。默认情况下,许多Linux系统都进行了保守的调优,以使用很少的资源并匹配典型的桌面工作负载。这意味着web应用程序用例至少需要一定程度的调优才能获得最大的性能。

Linux优化是特定于web服务器的。以NGINX为例,下面是一些你可以考虑的加速Linux的变化:

积压队列——如果您的连接似乎正在停滞,请考虑增加net.core。可以排队等待NGINX注意的最大连接数。如果现有连接限制太小,您将看到错误消息,您可以逐渐增加此参数,直到错误消息停止。
文件描述符- NGINX为每个连接使用最多两个文件描述符。如果您的系统正在提供大量连接,您可能需要增加sys.fs。file_max是文件描述符的系统范围限制,nofile是用户文件描述符的限制,以支持增加的负载。
临时端口——当用作代理时,NGINX为每个上游服务器创建临时(“临时”)端口。您可以增加由net.ipv4设置的端口值范围。ip_local_port_range,以增加可用端口的数量。您还可以在网络.ipv4重用非活动端口之前减少超时。tcp_fin_timeout设置,允许更快的周转。
对于NGINX,请查看NGINX性能调优指南,了解如何优化您的Linux系统,使其能够轻松处理大量网络流量!

技巧9 -调优Web服务器的性能
无论使用什么web服务器,都需要根据web应用程序性能对其进行调优。下面的建议通常适用于任何web服务器,但是为NGINX提供了特定的设置。主要包括:优化

访问日志—您可以缓冲内存中的条目,并将它们作为一个组写入磁盘,而不是立即为每个请求写入一个日志条目。对于NGINX,将buffer=size参数添加到access_log指令中,以便在内存缓冲区满时将日志条目写入磁盘。如果添加flush=time参数,缓冲区内容也会在指定的时间之后写入磁盘。

缓冲—缓冲将响应的一部分保存在内存中,直到缓冲区填满为止,这可以提高与客户机的通信效率。不适合内存的响应被写入磁盘,这会降低性能。当NGINX缓冲打开时,使用proxy_buffer_size和proxy_buffers指令来管理它。

客户机keepalives—Keepalive连接可以减少开销,特别是在使用SSL/TLS时。对于NGINX,您可以增加客户机在给定连接上可以发出的keepalive_requests的最大数量(默认值为100),您还可以增加keepalive_timeout以允许keepalive连接保持更长时间的打开状态,从而加快后续请求的速度。
上游保持连接—上游连接—到应用程序服务器、数据库服务器等的连接—也可以从保持连接中获益。对于上游连接,您可以增加keepalive,即为每个工作进程保持打开状态的空闲keepalive连接的数量。这允许增加连接重用,减少了打开全新连接的需要。有关更多信息,请参考我们的博客文章、HTTP Keepalive连接和Web性能。
限制——限制客户端使用的资源可以提高性能和安全性。对于NGINX, limit_conn和limit_conn_zone指令限制来自给定源的连接数量,而limit_rate限制带宽。这些设置可以阻止合法用户“占用”资源,还有助于防止攻击。limit_req和limit_req_zone指令限制客户机请求。对于到上游服务器的连接,使用max_conns参数到上游配置块中的服务器指令。这将限制到上游服务器的连接,防止过载。关联的queue指令创建一个队列,该队列在达到max_conns限制之后,在指定的时间长度内保存指定数量的请求。
工作进程——工作进程负责处理请求。NGINX使用基于事件的模型和依赖于操作系统的机制来有效地在工作进程之间分发请求。建议将worker_processes的值设置为每个CPU一个。如果需要,可以在大多数系统上安全地启动worker_connections的最大数量(默认为512);尝试找出最适合您的系统的值。
套接字分片——通常,一个套接字侦听器将新连接分配给所有工作进程。套接字分片为每个工作进程创建套接字侦听器,内核在套接字侦听器可用时将连接分配给它们。这可以减少锁争用,提高多核系统的性能。要启用套接字分片,请在listen指令上包含reuseport参数。
线程池——任何计算机进程都可以通过一个缓慢的操作来阻塞。对于web服务器软件,磁盘访问可以支持许多更快的操作,比如在内存中计算或复制信息。当使用线程池时,慢操作被分配给一组单独的任务,而主处理循环继续运行更快的操作。当磁盘操作完成时,结果返回到主处理循环。在NGINX中,两个操作——read()系统调用和sendfile()——被卸载到线程池。

小费。当更改任何操作系统或支持服务的设置时,每次更改一个设置,然后测试性能。如果更改导致问题,或者没有使站点运行得更快,请将其更改回来。

有关优化NGINX web服务器的更多信息,请参阅我们的博客文章“优化NGINX以获得性能”。

技巧10 -监控活动以解决问题和瓶颈
应用程序开发和交付的高性能方法的关键是密切和实时地观察应用程序的实际性能。您必须能够监视特定设备内和跨web基础设施的活动。

监控站点活动主要是被动的——它告诉您发生了什么,然后让您发现问题并修复它们。

监视可以捕获几种不同类型的问题。它们包括:

服务器宕机。
服务器正在中断连接。
服务器的缓存丢失率很高。
服务器没有发送正确的内容。
像New Relic或Dynatrace这样的全局应用程序性能监视工具可以帮助您从远程位置监视页面加载时间,而NGINX可以帮助您监视应用程序交付端。应用程序性能数据告诉您,什么时候您的优化对用户产生了真正的影响,以及什么时候您需要考虑向基础设施添加容量来维持流量。

为了帮助快速识别和解决问题,NGINX Plus添加了应用程序感知的健康检查——经常重复的合成事务,用于提醒您注意问题。NGINX Plus还具有会话耗尽功能,在现有任务完成时停止新连接,启动速度较慢,允许恢复的服务器在负载平衡的组中加快速度。当有效使用时,健康检查允许您在问题严重影响用户体验之前识别问题,而会话耗尽和启动缓慢允许您替换服务器,并确保流程不会对感知的性能或正常运行时间产生负面影响。图中显示了内建的NGINX Plus活动监视仪表板,用于具有服务器、TCP连接和缓存的web基础设施。


结论-性能提高10倍
任何一个web应用程序的性能改进都有很大的不同,实际的收益取决于您的预算、您可以投入的时间和现有实现中的差距。那么,如何为自己的应用程序实现10倍的性能改进呢?

为了帮助您了解每种优化的潜在影响,这里有一些关于上述每种技巧可能带来的改进的提示,尽管您的经验几乎肯定会有所不同:

反向代理服务器和负载平衡——没有负载平衡,或者负载平衡不好,可能会导致性能非常差的情况。添加反向代理服务器(如NGINX)可以防止web应用程序在内存和磁盘之间发生抖动。负载平衡可以将处理从过载的服务器转移到可用的服务器,并使扩展变得容易。这些变化可以带来显著的性能改进,与当前实现中最糟糕的时刻相比,可以轻松实现10倍的性能改进,总体性能方面的成就虽小,但却很可观。
缓存动态和静态内容——如果您的web服务器负担过重,并且其性能是应用服务器的两倍,那么仅通过缓存动态内容就可以在峰值时间内提高10倍。静态文件的缓存也可以提高性能的个位数倍数。
压缩数据——使用媒体文件压缩,如照片的JPEG、图形的PNG、电影的MPEG - 4和音乐文件的MP3,可以大大提高性能。一旦这些都被使用,那么压缩文本数据(代码和HTML)可以将初始页面加载时间提高两倍。
优化SSL/TLS——安全握手对性能有很大的影响,因此优化握手可以使初始响应能力提高2倍,特别是对于文本较多的站点。在SSL/TLS下优化媒体文件传输可能只会带来很小的性能改进。
实现HTTP/2和SPDY——当与SSL/TLS一起使用时,这些协议可能会导致站点整体性能的增量改进。
调优Linux和web服务器软件(如NGINX)——诸如优化缓冲、使用keepalive连接和将耗费大量时间的任务卸载到单独的线程池等修复可以显著提高性能;例如,线程池可以将磁盘密集型任务的速度提高近一个数量级。
我们希望您亲自尝试这些技巧。我们希望听到您能够实现的应用程序性能改进。在下面的评论中分享你的结果,或者用#NGINX和#webperf的散列标签发布你的故事!

你可能感兴趣的:(技术架构:十个10倍应用程序性能提升的技巧)