利用 NGINX 最大化 Python 性能,第一部分:Web 服務和緩存

【編者按】本文主要介紹 nginx 的主要功能以及如何經過 NGINX 優化 Python 應用性能。本文系國內 ITOM 管理平臺 OneAPM 編譯呈現。php

Python 的著名之處在於使用簡單方便,軟件開發簡單,並且聽說運行性能優於其它腳本語言。(雖然最新版本的 PHP、PHP 7 可能會與它展開激烈競爭。)css

全部人都但願本身的網站和應用程序運行得更快一些。可是,每一個網站在流量增加或驟然出現流量峯值時都很容易發生性能問題、甚至宕機(這通常會在服務器最繁忙的時候發生)。此外在運行期間,不管是流量穩步增加仍是使用量急速飛漲,幾乎全部的網站都會經歷性能問題。html

而關於網站性能問題,那就到了 NGINX 和 NGINX Plus 發揮做用的時候。通常能夠經過如下三種方式改善網站性能:python

做 web 服務器,NGINX 最開始的設計初衷就是解決 C10K 問題,也就是可以輕鬆支持1萬以上的同時訪問。NGINX 做爲 Python web 服務器,能夠保證網站在流量較低時依然可以快速運行。當擁有上千名用戶同時訪問時,你就必須提供更高性能、更少崩潰和更短停機時間的 web 服務器。你也能夠在 NGINX 服務器上進行靜態文件緩存或微程序緩存,不過這二者在單獨的 NGINX 反向代理服務器(見下段)上運行表現更佳。nginx

作反向代理服務器---你能夠在當前應用程序服務器上把 NGINX 設置爲反向代理服務器。NGINX 會將網絡請求發送到應用程序服務器。這種古怪招數能夠提升網站運行速度,減小停機時間,減小服務器資源佔用,而且提升網站安全。你還能夠在反向代理服務器上緩存靜態數據(很是高效),增長動態數據的微程序緩存,從而減小應用程序自己的負擔。web

作多個應用程序服務器的負載均衡器---首先要部署反向代理服務器,而後同時運行多個應用程序服務器,並使用 NGINX 或 NGINX Plus 來均衡通過它們傳送的流量,進行擴展。經過這種部署,你能夠輕鬆的根據流量需求來衡量網站性能,增長可靠度和正常運行時間。若是你須要既定的用戶會話保存在同一個服務器上,配置負載均衡器還能夠支持會話持久性。數據庫

不管是將其用做 Python 的 web 服務器、反向代理服務器、負載均衡器,仍是同時使用以上三種功能,NGINX 和 NGINX Plus 都能帶來很大好處。django

下面介紹改善 Python 應用程序性能的5個技巧,本文會分多個章節進行介紹,包括把 NGINX 和 NGINX Plus 做爲 web 服務器,如何實施靜態文件緩存,以及微程序緩存應用程序生成文件。瀏覽器

再就是下篇文章會介紹如何把 NGINX 和 NGINX Plus 看成反向代理服務器和多個應用程序服務器的負載均衡器。緩存

技巧1---找出 Python 性能瓶頸

檢驗 Python 應用程序的性能分有兩種不一樣狀況。

第一種是在平常合理用戶數量的狀況下;第二種則是負載很大的狀況下。

不少站長絕不關心輕負載時網站性能,然而殘酷的現實經驗告訴咱們,響應時間的每一秒鐘都應該爲之捏一把汗。雖然將響應時間縮短几毫秒是個苦差事,但卻會帶來更好的用戶體驗和更好的運營成果。

另外一個就是全部人都擔憂的情境:網站繁忙時出現的性能問題,例如運行嚴重減緩和崩潰。此外,不少黑客攻擊也會表現爲用戶數量急劇增加,因此改善網站性能也是解決攻擊問題的重要一步。

服務器會爲每位用戶分配必定數量的內存,例如 Apache HTTP 服務器,隨着用戶數量的增加,物理內存就會出現超負載,服務器開始將數據交換到磁盤上,性能驟降,隨之產生性能不良和崩潰。而使用 NGINX 將會有助於解決這一問題。

Python 尤爲容易發生內存相關的性能問題,由於它在執行任務時通常比其它腳本語言佔用更多的內存(所以它的執行速度更高)。所以,在同等條件下,基於 Python 的應用程序可能比其餘語言的應用程序能承受的用戶負載量更小。

優化應用程序或多或少會有幫助,可是這一般不是流量相關網站性能問題的最佳或最快解決方案。本文後續會列出解決流量相關問題的最佳/最快解決方案。當你看完本文後,不管如何都要回去優化你的應用程序,或者使用微服務架構重寫。

技巧2---選擇單一服務器或多個服務器配置

小網站只要配置單一服務器就能夠運行良好,大網站則須要有多個服務器。而若是你處於中間地帶,或者你的網站正在由小網站發展壯大起來,那你就要作些有意思的選擇了。

若是你只具配置有單一服務器的能力,那麼在流量峯值或總體流量迅速增加時,你會面臨極大風險。由於此時你的擴展性會受限,此時解決問題的方法能夠包括優化應用程序、把網絡服務器改爲 NGINX、換一個更大更快的服務器,或者把存儲任務轉移到內容分發網絡(CDN)等。這其中每個選項都須要耗費時間、成本,而且在實施過程當中均可能會引入錯誤和問題。

此外,配置單一服務器的狀況下,你的網站就有一個單一的失敗節點,會有不少問題形成你的網站下線並且沒有很快很簡捷的解決方法。

利用 NGINX 最大化 Python 性能,第一部分:Web 服務和緩存

若是把配置單一服務器改爲使用 NGINX,能夠自由選擇開源 NGINX 軟件或 NGINX Plus。NGINX Plus 包含企業級支持及額外功能。有些額外功能能夠在單一服務器配置情況下實現,例如實時活動監控,而有些功能只有在把 NGINX Plus 做爲多個服務器配置下的反向代理服務器時纔會出現,例如負載均衡和會話持久性。

綜合以上全部考慮,除非你確信你的網站在接下來很長時間都不會擴大規模,中止運行也不會有大麻煩,能夠抵抗一些其餘的風險,那能夠配置單一服務器。但別忘了配置多個服務器幾乎能夠隨意擴展---單次失敗徹底能夠處理,能迅速擴充容量,總之你應用的性能由你來定。
Tip 3 – Change Your Web Server to NGINX

技巧3---把你的 web 服務器改爲 NGINX

在網絡發展早期,Apache等同於web 服務器。可是21世紀初 NGINX 誕生以後使用愈來愈普遍,它已經成爲世界上流量前1000、10000和100000的公司的 web 服務器首選。

NGINX 的設計初衷是解決 C10K 問題,也就是在給定內存預算的範圍內能支持10000以上的同時訪問。其它 web 服務器須要給每一個訪問分配一部份內存,但當幾千名用戶同時訪問網站時,它們會面臨物理內存不足、運行緩慢或崩潰的問題。NGINX 分別處理每一個請求,而且能優雅地應對更多用戶。(如上文所述,它在其它功能方面也有優異表現。)

如下爲 NGINX 架構的概述。

利用 NGINX 最大化 Python 性能,第一部分:Web 服務和緩存

在本圖中,是一個 Python 應用程序服務器的後臺應用程序塊,須要經過 FastCGI 來訪問。NGINX 並不知道如何運行 Python,所以它須要關口來進入一個可以運行 Python 的環境。FastCGI 是 PHP、Python 等語言普遍使用的用戶界面。

不過,Python 和 NGINX 之間的溝通更經常使用的備選是服務網關接口(WSGI)。WSGI 能夠在多線程、多進程環境下運行,所以它能夠在本文提到的全部配置選擇下運行。

若是你要把 NGINX 做成你的 web 服務器,網上有不少操做幫助信息:

  • 配置 gunicorn---綠色獨角獸,一個頗有名的 WSGI 服務器,以便使用 NGINX。

  • 配置 uWSGI---另一個有名的 WSGI 服務器,以便使用 NGINX。uWSGI 可以直接支持 NGINX。

  • 使用 uWSGI、NGINX 和 Django---一個很經常使用的 Python 網站框架。

如下片斷展現瞭如何配置 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 圖像。

靜態文件緩存是加強應用程序性能的常見方法,並且實際上會在下面幾個層面發生:

  • 在用戶的瀏覽器

  • 多個層級的網絡提供者---從一家公司的內網,到互聯網服務供應商(ISP)

  • web 服務器上,正如本文所述

在 web 服務器上實施靜態數據緩存有兩個好處:

  • 更快傳送到用戶---NGINX 針對靜態數據緩存作了優化,執行靜態內容的請求的速度比應用程序服務器快得多。

  • 減輕應用服務器的負擔---應用服務器甚至不會收到緩存靜態數據的請求,由於網絡服務器已經實現這些請求。

靜態文件緩存在單個服務器執行時運行良好,但其實硬件方面依然由 web 服務器和應用程序服務器共享。若是 web 服務器使用硬件找回緩存的文件(及時很是高效)應用程序將沒法使用這些硬件,運行速度可能會受到影響。

要支持瀏覽器緩存,就要爲靜態文件正確設置 HTTP 標頭。須要考慮 HTTP 緩存控制標頭(尤爲是它的 max‑age 設置)、Expires 標頭和實體標籤。如想了解更多這方面的介紹,能夠參考 Using NGINX as an Application Gateway with uWSGI and Django

下面的代碼配置 NGINX,用於緩存包括 JPEG 文件、GIF、PNG文件、MP4 視頻文件、ppt等多種類型的靜態文件(用你的網址來替代 www.example.com ):

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 和其它語言的應用程序服務器提高性能的大好機會。可緩存的網頁有如下3種類型:

  • 靜態文件---可緩存,見技巧4。

  • 應用程序生成的、非我的化頁面---通常來講,緩存這些沒有意義,由於這些內容須要不斷更新。舉個例子,用戶登陸電商網站時看到的頁面(見下段)---在售商品、同類商品推薦等等可能會不斷更新,所以提供最新的網頁很是重要。不過,若是另外一個用戶在十分之一秒以後登陸,向他們展現前一位用戶看到的一樣頁面也沒有什麼問題。

  • 應用程序生成的、我的化頁面---這些一般不會被緩存,由於它們是單個用戶所屬,並且同一個用戶也不會再次看到相同的頁面。舉個例子,用戶登陸電商網站後看到的頁面,一樣的頁面不能向其餘用戶展現。

利用 NGINX 最大化 Python 性能,第一部分:Web 服務和緩存

微程序緩存對上述第二種網頁類型頗有用---應用程序生成的、非我的化頁面。微是一個歸納的時間範圍。若是你的網站一秒以內數次生成一樣的頁面,緩存一秒鐘就不會影響網頁的新鮮度。不過這個歸納的緩存時間期限會極大地減輕應用程序服務器的負擔,尤爲是流程峯值期間。在緩存逾時期限內,不用生成10次、20次、100次(相同的內容),而是生成既定的網頁一次,而後這個網頁就會被緩存,而且經過緩存向多個用戶展現。

而這產生的效果卻難以想象,服務器一秒鐘處理大量請求運行緩慢,但在只處理一個請求時速度是極快的。(固然,還有任何我的化的頁面)。設置一秒超時的代理服務器這樣的核心變化只須要幾行配置代碼。

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

更多配置範例,請參考 Tyler Hicks‑Wright 的博客 Python and uWSGI with NGINX.

結論

在這部分,本文介紹了提高單一服務器提高 Python 應用性能的解決方案,能夠在單一服務器上配置,也可在反向代理服務器或單獨的緩存服務器上實現。(緩存在單獨的服務器上運行更好。)接下來的第二部分介紹須要兩個或更多服務器才能實現的性能提高方案。

固然若是你想了解 NGINX Plus 適用於你的應用程序的高級功能,例如支持、實時活動監控、運行時同時配置,能夠去 NGINX 官網查看。

OneAPM 可以幫你查看 Python 應用程序的方方面面,不只可以監控終端的用戶體驗,還能監控服務器性能,同時還支持追蹤數據庫、第三方 API 和 Web 服務器的各類問題。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客

本文轉自 OneAPM 官方博客

原文地址:Maximizing Python Performance with NGINX, Part I: Web Serving and Caching

相關文章
相關標籤/搜索