【译文】使用Nginx最大化Python Web性能

更多可以查看我的博客

第一部分描述提高Python应用程序的五个技巧,包括使用Nginx和Nginx Plus作为web服务器,如果实现静态文件的缓存,以及应用程序生成文件的微缓存;第二部分,描述Nginx和Nginx Plus用做反向代理服务器和多个应用服务器的负载均衡。

Web服务和缓存

原文

Nginx如何与Python使用

每个人都希望自己的网站和应用程序运行得更快。然而,最糟糕的情况时,每次用户增长或流量急剧上升的网站都容易出现性能问题和停机。几乎所有的网站都会存在性能问题和宕机,无论是流量稳定增长,还是使用量激增。

这就是Nginx和Nginx Plus的作用,他们通过下面三种不同的方式提高网站性能:

  1. 作为Web服务器:Nginx最初是为了解决C10K问题而开发的,也就是说他可以轻松支持10000个或者更多的并发连接。使用Nginx作为Python应用程序的web服务器,即使在低流量的情况下都可以使网站访问更快。当拥有数千个用户时,几乎可以肯定需要提供更高的性能、减少崩溃和避免停机。可以在Nginx web服务器上进行静态文件缓存或微缓存,不过在单独的Nginx反向代理服务器上运行时,下面的两种方法的效果更好。

  2. 作为反向代理服务器:在当前的应用服务器配置的前方,可以将Nginx放进来作为一个反向代理服务器。Nginx面向web并将请求传递给应用服务器,这样配置不仅可以使网站运行得更快,减少停机时间,消耗更少的服务器资源,并且可以提高安全性。还可以在反向代理服务器上缓存静态文件(非常有效),添加动态内容的微缓存以减少应用程序本身的负载等。

  3. 作为多个应用服务器的负载均衡:首先部署一个反向代理服务器,然后,通过运行多台应用服务器,并使用Nginx和Nginx Plus来均衡它们之间的负载流量,从而扩展规模。通过这种部署,还可以根据流量需求轻松的调整网站的性能,提高可靠性和稳定性。如果需要给特定的用户会话保持在同一服务器上,需要配置负载均衡来支持会话持久性。

无论您将它们用作Python应用程序的web服务器、反向代理服务器、负载均衡,还是三种都用上,Nginx都具有优势。

技巧1:找到Python性能瓶颈

有两种不同的情况,Python应用程序的性能显得非常重要。首先,每天都有很多的用户;其次,高负载。大部分站长都不需要担心性能问题,因为他们网站的负载很小,但需要优化降低响应时间。将响应时间控制在毫秒级是非常困难的,可以让用户体验更好,但很少人关注这个。

这篇文章关注的是每个人都可能担心的场景:当站点繁忙时出现的性能问题,比如性能下降和站点崩溃。此外,还有黑客模拟用户访问攻击造成流量激增,提高网站性能也是解决攻击的重要步骤。

像Apache HTTP Server对每个用户分配一定量的内存,随着越来越多的用户进入,消耗内存会导致物理内存过载。服务器开始使用磁盘的交换分区,性能直线下降,随后出现性能低下甚至崩溃。所以迁移到Nginx有助于解决这个问题。

Python特别容易出现与内存相关的性能问题,因为与其他脚本相比,Python通常会使用更多的内存完成任务(因此执行速度更快)。所以在其他条件相同的情况下,及时用户负载小,基于Python的应用程序比其他编程语言可能更容易“崩溃”。

优化应用程序对解决问题会有所帮助,但这通常不是解决与流量相关的性能问题的最快最好的方法。后面的步骤将讲解一种最好最快的方式。

技巧2:选择单服务器和多服务器部署

当部署在单个服务器上,小型网站可以正常工作,而大型网站需要多个服务器。但是如果网站正在从一个小网站成长为大网站,可以做一些其他选择。

如果使用单服务器部署,如果流量峰值或总体流量快速增长时,那么将面临巨大的风险。因为服务器的伸缩性是有限的,可能需要将应用程序,web服务器迁移到配置高的服务器,或者使用内容分发网络(CDN)。而这些选择都比较消耗时间和成本,并且在迁移过程中还可能发生错误。

使用单服务器部署,存在单点故障,很多问题都可以导致站点宕机,而且没有简单快速的解决方案。

【译文】使用Nginx最大化Python Web性能_第1张图片
image.png

如果把服务器切换成Nginx并且使用单服务器部署,可以在开源的Nginx和Nginx Plus之间自由选择。Nginx Plus包含企业级支持和附加功能。如果在多服务器部署中使用Nginx Plus作为反向代理服务器,那么其他一些附加功能(比如活动实施监控)就会发挥作用,还有负载均衡和会话持久性。

除非站点一直都是一个小网站,否则单机部署有很多风险。分布式部署比较易于扩展,单点故障可以解决,性能根据需求而定,具有快速扩容的能力。

技巧3:使用Nginx替换web服务

Nginx可以单独处理一个请求,并能优雅的扩展到同时处理多个用户请求。

Nginx架构如下

【译文】使用Nginx最大化Python Web性能_第2张图片
image.png

在图中,Python应用程序被部署到后端的应用服务器块中,FastCGI可以访问它。Nginx不知道如何运行Python,所以它需要一个网关来运行Python。FastCGI是PHP、Python和其他语言广泛使用的网关接口。

然而,Python和Nginx之间更流行的通信选择是Web Server Gateway Interface(WSGI)。WSGI可以在多线程和多进程环境中工作,因此它可以很好的扩展本文中提到的所有部署选项。

如果将Nginx作为web服务器,这里有很多有用的软件:

  • 配置 gunicorn:“绿色独角兽”,一个流行的WSGI服务器,用于Nginx。
  • 配置 uWSGI:另一个流行的WSGI服务器,用于Nginx。uWSGI包括对Nginx的直接支持。
  • 使用uWSGI+Nginx+Django:一个流行的Python web框架。

下面的代码展示了如何配置Nginx以便和uWSGI一起使用,在本例中,是一个使用Python框架Django的项目中:

http {
    # ...
    upstream django {
       server 127.0.0.1:29000;
    }

    server {
        listen 80;
        server_name myapp.example.com;

        root /var/www/myapp/html;

        location / {
            index index.html;
        }

        location /static/  {
            alias /var/django/projects/myapp/static/;
        }

        location /main {
            include /etc/nginx/uwsgi_params;
            uwsgi_pass django;

            uwsgi_param Host $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;
        }
    }
}

技巧4:实现静态文件缓存

静态内容的缓存包括在应用程序服务器之外的位置,这些文件不经常更改(可能意味着每隔几小时或从不更改)。例如一个jpeg图片就是静态内容,它作为web页面的一部分显示。

静态文件缓存是提高应用程序性能的常见方法,下面这些情况经常被用到:

  • 在用户的浏览器中
  • 从公司内部网络到互联网服务提供商(ISP)
  • 在web服务器上,下面讲到

在web服务器上实现静态文件缓存有两个好处:

  • 更快的展示给用户:Nginx针对静态文件缓存进行了优化,并比应用程序更快的执行静态文件的请求。
  • 减少应用服务器的负载:应用服务器甚至不需要处理请求的已缓存的静态文件,因为web服务器直接提供

静态文件缓存在单服务器工作更好,但是底层硬件仍然由web服务器和应用服务器共享。如果web服务器要处理多个静态文件,会消耗硬件资源,从而造成应用程序运行慢。

如果要支持浏览器缓存,需要正确设置静态文件的头部信息。如HTTPCache Control(特别是它的max age设置),Expires,和Entity标记。详细介绍查看使用nginx作为uWSGI+Django的应用程序内容。

下面的代码将就是在nginx上配置静态文件缓存,包括jpeg、gif、ppt、mp4等,将 www.example.com 替换为web服务器的URL即可。

server {
    # substitute your web server's URL for "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;
        # substitute the socket, or address and port, of your Python server
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        #fastcgi_pass 127.0.0.1:9000;
    }

   location ~* .(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;
    }
}

技巧5:实现微缓存

微缓存可以很明显的大幅提升Python、PHP和一些其他语言开发的应用服务性能,根据是否适合缓存,将网页分为三类:

  • 静态文件:可以缓存这些文件,如技巧4所述。
  • 应用程序生成的(动态),非个性化页面:因为他们需要刷新,所以不适合做缓存。例如一个电商网页,在登陆前可用的商品、相似推荐经常要发生变化,所以必须提供一个新的页面。但是有另外一个用户,在0.1s之后发送同样的请求,将前一用户看到的网页缓存并发给后一个用户就是可以的。
  • 应用程序生成的(动态),个性化页面:这些页面不适合缓存,因为他们是特定用户的,同一用户不希望两次看到同一个个性化页面。例如一个电商网站登陆后的页面不应该显示给其他用户。
【译文】使用Nginx最大化Python Web性能_第3张图片
image.png

微缓存适用于上面提到的第二类页面–动态,非个性化页面。“微”是指很短的时间。如果你的网站在一秒内要多次生成同一个页面,如果把这个页面只缓存一秒,并不影响该页面的刷新。但这个短暂的缓存可以极大的降低应用服务的负载,特别是流量较大时。将原来在一个缓存区间内,同一内容生成10,或者20,甚至100次,调整为只生成一次并缓存,为其他用户提供缓存内容。

这有点不可思议,一个服务如果一秒钟要处理大量请求会变得很慢,但如果只处理一个请求,就会变得很快。(包括任何个性化页面)。微缓存的好处和配置代码核心更改(设置超时1秒的代理缓存)只需要几行配置代码。

proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;
server {
    proxy_cache cache;
    proxy_cache_valid 200 1s;
    # ...
}

更详细的实例配置,可以查看Python和uWSGI使用nginx

总结

在第一部分,讨论了一下在单机环境下提高Python应用性能的解决方案,还有缓存的使用,在单机情况下缓存可以应用于反向代理服务器或者独立缓存服务(缓存比独立服务性能更好)。在下一部分,将会介绍分布式环境下的性能提升方案。

负载均衡和监控

原文

简介:使用分布式服务器

第一部分讲解了单个服务器最大化Python应用服务器性能,以及如何使用Nginx实现静态文件缓存和微缓存。这两种缓存都可以在单服务器中实现,或者为了更好的性能在分布式环境中也可以使用。

Python是一种高性能的脚本语言。Nginx可以对代码实际运行速度提供帮助。在单服务器上,将应用迁移到以Nginx作为web服务器可以大大提高性能。从理论上讲,一个网页中包含一半静态文件,使用静态文件缓存可以将网页的性能提高大约一倍。缓存动态页面也会大大提高应用程序性能。

然而,可能这些步骤不一定适用,有时,实现的性能提升还不够,就需要考虑向外扩展---转向功能强大、灵活、可伸缩、成本低的分布式服务器实现。

迁移到分布式服务器同时也可以考虑从开源的Nginx升级到Nginx Plus。开源的Nginx有自己的有点:社区支持、被广泛使用、并提供预构建的发行版和源代码。对于单服务器来说,将Nginx作为web服务器是一个很好的选择。

而Nginx Plus添加预配置的发行版;专业支持;Nginx工程师支持;HTTP、TCP和UDP流量的高级负载均衡;智能会话持久性;应用程序健康检查,实施活动监控;媒体传递特性;以及基于订阅的价格(按实例数量、应用程序范围或站点范围)

这些Nginx Plus特性在单服务器上非常有用,但在分布式服务器体系结构中更有用。可以使用Nginx Plus创建快速、灵活、有弹性和易于管理的应用程序。

技巧6:将Nginx作为反向代理服务器

从单个服务器环境迁移,部署到反向代理服务器,这个步骤非常简单,而且功能强大。添加反向代理服务器可以立即提高性能,为后面的优化打开大门:

  • 提高性能:在现有的Python应用程序前面放置一个Nginx服务器。不需要更改web服务器软件或配置。现有的web服务器和应用程序服务器只是运行在气泡中,并对直接访问web流量隔离,由反向代理服务器转发请求。
  • 更多的性能:第一部是讲到的,实现静态文件缓存和应用程序生成文件的微缓存。但现在,使用一台新的反向代理服务器而不是直接在应用服务器实现它们。运行应用程序的服务器工作负载会下降,从而增加应用程序的能力为用户提供更好的性能。
  • 向外扩展:添加更过的应用服务器,在他们之间实现负载均衡(Nginx Plus具有的高级特性),并且使用会话持久性来保持每个用户体验的连续性。
  • 添加高可用:通过镜像反向代理服务器实时备份,且拥有备用应用服务器,使站点具有高可用性。
  • 监控和管理:Nginx Plus包括高级监控和管理功能,以及主动健康检查,当这样配置时,反向代理服务器主动向服务器发起带外请求,以验证其可用性。
【译文】使用Nginx最大化Python Web性能_第4张图片
image.png

Nginx还具有很多安全优势。当作为反向代理服务器时,可以优化和更新Nginx的安全性,包括防止拒绝服务攻击,同时配置的应用服务器也能获得最大的性能。

静态缓存和微缓存都是增强性能的强大工具。要启用内容缓存,在配置中包括 proxy_cache_path 和 proxy_cache 指令:

# Define a content cache location on disk
proxy_cache_path /tmp/cache keys_zone=mycache:10m inactive=60m;

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://localhost:8080;

       # reference the cache in a location that uses proxy_pass
       proxy_cache mycache;
    }
}

还有其他几个指令可以对内容缓存配置进行微调,Nginx Plus管理指南。

Nginx还提供了跨不同云部署选项和自有服务器的灵活性。例如,一些Nginx用户在其本地服务器上运行,当流量达到某个阀值,就添加云实例以处理流量峰值,并覆盖内部服务器的停机时间。一旦将Nginx部署为反向代理服务器,这种灵活性和功能就相对容易实现。

使用反向代理服务器需要增加额外的成本,对于服务器来说,无论是硬件还是云实例,以及一些配置工作。但是对站点的好处是不更改应用程序代码或web服务器配置的情况下就可以实现。

技巧7:重写URLs

Web服务器配置通常包括URL重写规则。可以创建用户便于理解好看的url,在资源移动时可以保持URL不变,以及管理缓存和动态生成的流量等。

Nginx配置,包括URL重写,使用少量的指令,显得更加简单和清晰。然而,如果不熟悉它,就会有一个学习曲线。

下面是一个使用rewrite指定的Nginx重写规则示例。它匹配以字符串/download开头,然后在路径后面某个地方包含/media//audio/目录的url。将这些元素替换为/mp3/并添加适当的文件扩展名.mp3.ra$1$2变量捕获不变的路径元素。例如,/download/cdn-west/media/file1变成/download/cdn-west/mp3/file1.mp3。如果文件名上有扩展名(如.flv),表达式会将其删除,并将其替换为.mp3

server {
    # ...
    rewrite ^(/download/.*)/media/(\w+)\.?.*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(\w+)\.?.*$ $1/mp3/$2.ra  last;
    return  403;
    # ...
}

可能在Apache中写过重写规则,希望在Nginx上重新实现这些规则,可以直接实现,也可以作为Nginx配置的起点,Apache使用Nginx不支持的.htaccess文件。(因为.htaccess文件也是层次化的,而且在应用多个层次的.htaccess文件时,效果是累积的,因此可能需要进行一些研究,以确定在给定上下文中处于活动状态的配置规则。)

这里有一个简单的例子。以下Apache规则将http协议标识符和www前缀添加到URL:

RewriteCond %{HTTP_HOST} example.org
RewriteRule (.*)         http://www.example.org$1

为了在Nginx中完成同样的事情,在第一个服务器块中匹配较短URL的请求,并将他们重定向到第二个服务器块,吼着匹配较长的URL。

# USE THIS CONVERSION
server {
    listen      80;
    server_name example.org;
    return      301 http://www.example.org$request_uri;
}

server {
    listen      80;
    server_name www.example.org;
    # ...
}

有关更多示例,可以查看 将Apache重写规则转换为Nginx重写规则。

技巧8:实现负载均衡

扩展网站容量和可用性的最终方法是运行多个应用服务器并实现负载均衡。这是Nginx的一个非常广泛使用的功能,Nginx Plus包含了额外的、复杂的平衡算法和功能。

【译文】使用Nginx最大化Python Web性能_第5张图片
image.png

使用Nginx负载均衡首先要创建一个服务器组,这个服务器组都是用来均衡负载的服务器。下面的配置代码包含一个服务器权重,如果有一个性能更强的服务器,为其分配更大的权重,以增加发送到它的流量比例。

upstream stream_backend {
    server backend1.example.com:12345 weight=5;
    server backend2.example.com:12345;
    server backend3.example.com:12346;
}

Nginx Plus上的负载均衡提供了一些新请求路由短发,包括轮循(默认)、最少连接、最少时间(响应)、通用哈希(例如URL)和IP哈希(客户端IP地址)。对于Python和其他应用程序语言,使用最优负载均衡算法可能非常有效,因为任何一个请求都可能花费很长时间;将每个新请求发送到最不繁忙的服务器是最强大的优化。

技巧9:实现会话持久性和会话消耗

默认情况下,web是无状态交互而设计的;当需要特定于状态的信息时,有几种方法可以实现它。如果如果在应用服务器上有状态,那么需要让同一个应用服务器在会话期间处理来自特定用户的所有请求。这称为会话持久性。

Nginx Plus通过sticky指定提供高级会话持久性功能,包括时间sticky cookie;一个learn参数,它生成会话标识符并将其用于重复的服务器分配;以及粘性路由,它允许预先制定特定的服务器。

下面代码是使用的粘性指令

upstream backend {
    server webserver1;
    server webserver2;
    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

会话耗尽是管理多个负载均衡服务器的工具箱中非常有用的一部分。当使用Nginx Plus API 在一个upstream组服务器上配置drain参数时, Nginx Plus允许服务器关闭。也就是说,Nginx Plus不会发送新的请求,而是让现有的连接一直持续要会话结束。

有关会话持久性和会话消耗的更多信息,请参见会话持久性。

技巧10:使用监控和管理

当服务器更加复杂时,监控和管理对于维护高性能和避免停机变得至关重要。Nginx Plus运行活动健康检查,让管理者知道服务器何时会出现问题,但是需要在问题发生之前监控系统,以便对这些信息采取行动。

使用Nginx Plus,可以获得内置的仪表盘,用于监控Nginx服务器的健康状况。可以作为一个组跟踪进出Nginx服务器的数据流,并深入了解每个特定服务器的详细信息。

【译文】使用Nginx最大化Python Web性能_第6张图片
image.png

Nginx Plus还提供了Json格式的实时统计数据。可以将这些数据发送到自己的工具中分析。

总结

Nginx对于单服务器和多服务器都很有用,它们跨自己的服务器和云主机,提供了极大的灵活性和能力。

你可能感兴趣的:(【译文】使用Nginx最大化Python Web性能)