Python 因其易于使用且有趣、使软件开发变得更容易以及运行时性能超过其他脚本语言而闻名。 (尽管 PHP 的最新版本 PHP 7 可能会与 Python 展开竞争。)
每个人都希望自己的网站和应用运行得更快。 此外,每个流量不断增长或流量急剧飙升的网站都容易出现性能问题和停机,而且这些问题和停机通常发生在最糟糕的时候,也就是最繁忙的时候。 此外,无论是流量稳步增长还是使用量急剧增加,几乎所有网站都会遭遇性能问题和停机。
这就是 NGINX 和 NGINX Plus 的作用所在。 他们通过三种不同方式提高网站性能:
无论您将 NGINX 和 NGINX Plus 用作 Python 应用程序的 Web 服务器、反向代理服务器、负载均衡器还是同时用于这三个用途,它们都能带来优势。
在本系列文章的第一部分中,我们介绍了五条提高 Python 应用程序性能的技巧,包括使用 NGINX 和 NGINX Plus 作为 Web 服务器、如何实现静态文件的缓存以及应用生成文件的微缓存。 在第 2 部分中,我们将描述如何使用 NGINX 和 NGINX Plus 作为反向代理服务器以及多个应用服务器的负载均衡器。
在两种截然不同的条件下,Python应用的性能至关重要 —— 首先,每天有“合理”数量的用户;其次,在高负载下。 许多网站所有者很少担心轻负载下的性能,而以我们的拙见,他们应该为响应时间每十分之一秒的性能而担忧。 将响应时间缩短几毫秒是一项困难且吃力不讨好的工作,但它可以让用户更满意,业务成果更好。
然而,这篇博文和随附的第 2 部分重点关注的是每个人都担心的情况:网站繁忙时出现的性能问题,例如性能大幅下降和崩溃。 此外,许多黑客攻击模仿用户数量突然激增的影响,而提高网站性能通常也是应对攻击的重要步骤。
对于为每个用户分配一定量内存的系统(如 Apache HTTP Server),随着越来越多的用户加入,添加用户会导致物理内存超载。 服务器开始交换磁盘,性能下降,并随之出现性能不佳和崩溃。 正如这篇博客文章中所述,迁移到 NGINX 有助于解决此问题。
Python 特别容易出现与内存相关的性能问题,因为它通常比其他脚本语言使用更多的内存来完成其任务(因此执行速度更快)。 因此,在其他条件相同的情况下,与使用其他语言编写的应用程序相比,基于 Python 的应用程序在较少的用户负载下可能会“失败”。
优化您的应用程序可能会有所帮助,但这通常不是解决流量相关的网站性能问题的最佳或最快的方法。 这篇博文以及随附的第 2 部分中介绍的步骤是解决流量相关性能问题的最佳和最快方法。 然后,在完成这里给出的步骤后,一定要回去改进您的应用程序,或者重写它以使用微服务架构。
小型网站在单台服务器上部署时运行良好。 大型网站需要多台服务器。 但如果你处于中间的灰色地带——或者你的网站正在从一个小网站发展成为一个大网站——你就需要做出一些有趣的选择。
如果您采用单服务器部署,当遇到流量高峰或总体流量快速增长时,您将面临巨大的风险。 您的可扩展性是有限的,可能的修复包括改进您的应用程序、将您的 Web 服务器切换到 NGINX、获取更大更快的服务器或将存储卸载到内容分发网络 (CDN)。 每个选项都需要花费时间去实现,需要花费成本,并且有在实现过程中引入错误或问题的风险。
此外,采用单服务器部署,您的网站根据定义就会有一个单点故障——并且许多可能导致您的网站离线的问题都没有快速或简单的解决方案。
如果您在单服务器部署中将服务器切换到 NGINX,则可以自由选择 NGINX 开源和 NGINX Plus。 NGINX Plus 包括企业级支持和附加功能。 某些附加功能(例如实时活动监控)与单服务器部署相关,而其他功能(例如负载均衡和会话持久性)在多服务器部署中使用 NGINX Plus 作为反向代理服务器时才会发挥作用。
从各方面因素来看,除非您确定您的网站在未来很长一段时间内都会保持较小的规模,并且停机时间不是一个主要的问题,否则单服务器部署还是有一定的风险。 多服务器部署几乎可以任意扩展——可以消除单点故障,并且性能可以根据您的选择而变化,同时能够快速增加容量。
在 Web 的早期,“Apache”这个名称是“Web 服务器”的同义词。 但是 NGINX 是在 21 世纪初开发出来的,并且正在稳步提升其受欢迎程度;它已经是世界上 1,000、10,000、100,000 和 [ngx_snippet name='proportion-top-sites'] 的排名第一的 Web 服务器。
NGINX 的开发是为了解决C10K 问题——即在给定的内存预算内处理超过 10,000 个同时连接。 其他 Web 服务器需要为每个连接分配一块内存,因此当数千个用户同时想要访问某个网站时,它们就会耗尽物理内存,导致速度变慢甚至崩溃。 NGINX 单独处理每个请求,并优雅地扩展到更多用户。 (它也非常适合其他用途,正如我们将在下面描述的。)
下面是 NGINX 架构的高级概述。
在图中,Python应用服务器适合后端的应用服务器块,并显示由 FastCGI 访问。NGINX 不“知道”如何运行 Python,因此它需要一个网关来访问运行 Python 的环境。 FastCGI 是 PHP、Python 和其他语言广泛使用的接口。
然而,Python 和 NGINX 之间通信的更流行的选择是 Web 服务器网关接口 (WSGI)。 WSGI 在多线程和多进程环境中工作,因此它可以很好地扩展到本博文中提到的所有部署选项。
如果您将 NGINX 用作 Web 服务器,则涉及以下步骤,可以获得很多支持:
此代码片段展示了如何配置 NGINX 以与 uWSGI 一起使用——在本例中,项目使用 Python 框架 Django:
http { # ...
上游 django {
服务器 127.0.0.1:29000;
}
服务器 {
监听 80;
服务器名称 myapp.example.com;
根 /var/www/myapp/html;
位置 / {
索引 index.html;
}
位置 /static/ {
别名 /var/django/projects/myapp/static/;
}
位置 /main {
包括 /etc/nginx/uwsgi_params;
uwsgi_pass django;
uwsgi_param 主机 $host;
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto;
}
}
}
静态内容的缓存涉及在应用服务器以外的位置保存不经常更改的文件的副本(这可能意味着每隔几个小时或从不更改)。 静态内容的典型示例是作为网页一部分显示的 JPEG 图像。
静态文件缓存是增强应用性能的常用方法,它实际上发生在几个层面:
在 Web 服务器上实现静态文件缓存有两个好处:
静态文件缓存在单服务器实现下工作得很好,但是底层硬件仍然由 Web 服务器和应用服务器共享。 如果 Web 服务器的硬件忙于检索缓存文件(即使非常高效),这些硬件资源也无法供应应用使用,从而可能在一定程度上降低其速度。
为了支持浏览器缓存,请为静态文件正确设置 HTTP 标头。 考虑 HTTP Cache-Control
标头(特别是其max-age
设置)、 Expires
标头和Entity
标签。 有关该主题的详细介绍,请参阅 NGINX Plus 管理指南中的使用 NGINX 和 NGINX Plus 作为带有 uWSGI 和 Django 的application网关。
以下代码配置 NGINX 来缓存静态文件,包括 JPEG 文件、GIF、PNG 文件、MP4 视频文件、Powerpoint 文件等等。 将www.example.com替换为您的 Web 服务器的 URL。
server { # 用您的 Web 服务器 URL 替换“www.example.com”
server_name www.example.com;
root /var/www/example.com/htdocs;
index index.php;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
# 用您的 Python 服务器的套接字或地址和端口替换
fastcgi_pass unix:/var/run/php5-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
}
位置 ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
}
微缓存为提高运行 Python、PHP 和其他语言的应用服务器的性能提供了巨大的机会。 出于缓存目的,网页有三种类型:
微缓存对于上面描述的第二种页面类型(应用生成的非个性化页面)很有用。 “微”是指短暂的时间范围。 当您的网站每秒生成几次相同的页面时,将其缓存一秒钟可能不会对页面的新鲜度造成太大影响。 然而,这个短暂的缓存期可以极大地减轻应用服务器的负载,尤其是在流量高峰期间。 它不会在缓存超时期间生成 10、20 或 100 个页面(内容相同),而是只生成一次给定页面,然后该页面被缓存并从缓存中提供给许多用户。
效果相当神奇。 一个服务器在每秒处理几十个请求时会很慢,但在处理一个请求时就会变得非常快。 (当然,还有任何个性化页面。) 我们自己的 Owen Garrett 发表了一篇博客文章,详细阐述了微缓存的好处,并提供了配置代码。 核心的变化是设置一个超时时间为一秒的代理缓存,只需要几行配置代码。
proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;server {
proxy_cache 缓存;
proxy_cache_valid 200 1s;
# ...
}
有关更多示例配置,请参阅 Tyler Hicks‑Wright 关于Python 和 uWSGI 与 NGINX 的博客。
在第一部分中,我们讨论了提高单服务器 Python 实现性能的解决方案,以及缓存,它们可以部署在单服务器实现上,也可以在反向代理服务器或单独的缓存服务器上运行。 (缓存在单独的服务器上效果更好。) 下一部分,第 2 部分,介绍需要两台或更多台服务器的性能解决方案。
如果您想探索NGINX Plus为您的应用提供的高级功能,例如支持、实时活动监控和动态重新配置,请立即开始30 天免费试用或联系我们讨论您的用例。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”