如何使用Nginx后面的CherryPyWeb服务器部署PythonWSGI应用程序
介绍
阅读本教程的标题后,您可能会发现自己提出以下问题之一:
- 为什么我应该为我的 WSGI 应用程序使用 CherryPy 的纯 Python Web 服务器而不是“真正的”独立的(可能是基于 C 的)服务器?
- CherryPy……那不是一个框架吗? 这与我的 Bottle、Flask 等的部署有什么关系? 基于应用程序?
两者都有很多好的答案和理由。 在这篇 DigitalOcean 文章中,我们将找到它们。 我们将首先讨论 CherryPy 到底是什么以及将它用于您的 Web 应用程序的优势。 我们将继续解释“为什么”以及最重要的是“如何”使用 CherryPy 的 Web 服务器部署 Python 应用程序。
词汇表
1. 了解 CherryPy 并使用 Nginx
- CherryPy WSGI Web 服务器简介
- 为什么使用 CherryPy 的 WSGI Web 服务器进行部署?
- 在 CherryPy 前使用 Nginx 作为反向代理
2. 为生产准备 Droplet
- 更新默认操作系统
- 设置 Python、pip 和 virtualenv
- 创建虚拟 (Python) 环境
- 下载和安装 CherryPy
- 下载和安装 Nginx
3. 使用 CherryPy Web 服务器为 Python Web 应用程序提供服务
4. 配置 Nginx
5. 其他提示和建议
了解 CherryPy 并使用 Nginx
CherryPy 整体是一个极简的 Python Web 框架。 极简主义在这里的意思是,无论您是否喜欢(或需要)它们,它都不会附带太多开箱即用的组件。 极简主义基本上是避免在不给他们选择的情况下将事情强加给开发人员。 CherryPy - 和其他类似的框架 - 通常处理人们期望的核心必需品(例如 会话、缓存、文件上传等),剩下的——以及选择——由 你 决定使用什么以及如何使用。
CherryPy 与其他 Python 框架(包括一些“成熟”的框架)的不同之处在于它的开发人员希望它能够随时工作(即 开发)并准备部署为自包含的应用程序包(包)。 为了完成这个任务,对于 Web 应用程序来说,一个可靠的 Web 服务器是必须的。 这正是 CherryPy 擅长的地方,它拥有自己的 HTTP/1.1 兼容、WSGI 线程池 Web 服务器 。 它已准备好生产,非常棒。
CherryPy WSGI Web 服务器简介
CherryPy 的纯 Python Web 服务器是一个紧凑的解决方案,它带有同名框架。 [CherryPy] 项目将其定义为高速、生产就绪、线程池、通用 HTTP 服务器。 它是一个模块化组件,可用于为任何 Python WSGI Web 应用程序提供服务。
CherryPy Web 服务器的亮点:
- 一个非常紧凑且易于使用的纯 Python 解决方案
- 易于配置,易于使用
- 线程池和快速
- 允许缩放
- 支持 SSL
为什么使用 CherryPy 的 WSGI Web 服务器进行部署?
正如我们在开头提到的那样,您可能想知道使用此解决方案而不是您可能听说过甚至尝试过的另一个大肆宣传和著名的解决方案的原因。 事实上,由于 WSGI 的出色规范,创建 Web 服务器相当容易。 多年来,这催生了许多,其中一些达到了一定程度的受欢迎程度,而大多数仍然隐藏在其开发人员的机器中。
选择的数量是巨大的,而且它们(大部分)在很大程度上都在做同样的事情。
为什么要使用 CherryPy Web 服务器来部署应用程序?
答案很简单:合作是一种乐趣。 使用 CherryPy 的服务器为您的 WSGI Web 应用程序提供服务的易用性非常出色。 当您在一两分钟内起床并跑步时,它将为您节省大量的头痛。 它在一定程度上是可定制的,使您能够以最简单的方式通过单个文件运行多进程和多线程实例(例如 server.py)。
记住: 对于多进程设置,您需要配置多个“服务器”对象实例。
除非您确定在您的应用程序上线后的几分钟内,它将每秒收到数万个请求,并且您不能简单地使用更多服务器来平衡负载,否则您最好花时间继续开发应用程序而不是麻烦库、CPU 优化、处理崩溃等。
CherryPy Web 服务器,加上(轻松)使用 Nginx 作为前端反向代理,是服务基于 Python WSGI 的 Web 应用程序的真正坚如磐石的方式,无论是在 Bottle、CherryPy、 Django、Flask、Pyramid 或任何其他框架。
记住:上面提到的架构(解释如下)使您能够轻松地水平扩展(更多服务器)甚至垂直扩展(每台服务器的容量更大)。 您的“瓶颈”很可能是后端(数据库)。 这就是为什么在承诺极端负载之前尝试将事物优化到死是不值得的。 即便如此,如果引入合理的缓存机制,可能会解决您的大部分问题。
在 CherryPy 前使用 Nginx 作为反向代理
Nginx 是一个非常高性能的 web 服务器 / (reverse)-proxy。 由于重量轻、相对容易使用和易于扩展(使用附加组件/插件),它已经流行起来。 由于其架构,它能够处理 很多 的请求(实际上是 无限制 ),这取决于您的应用程序或网站负载 - 使用其他一些可能很难解决,较旧的替代品。
记住:“处理”连接在技术上意味着不丢弃它们,并且能够使用 something 为它们服务。 您仍然需要您的应用程序和数据库运行良好才能让 Nginx 为客户端 响应 而不是错误消息。
为什么要在应用服务器前使用 Nginx 作为反向代理?
虽然你的应用服务器——在我们的例子中是 CherryPy WSGI web 服务器——可以为你的应用和它的静态文件提供服务(例如 javascript, css, images 等),使用反向代理是一个非常好的主意,在前面设置,例如 Nginx。 当它处理 客户端请求(和开销) 和各种其他任务时,这减轻了 [来自应用程序服务器的] 大量负载,从而为您提供更好的整体性能。
随着应用程序的增长,您将希望对其进行优化,并在时机成熟时将其分布在服务器上,以便能够同时处理更多连接并拥有通常更健壮的架构。 在您的应用程序服务器前面拥有一个反向代理也可以从一开始就帮助您解决这个问题。
它的可扩展性(例如 本机缓存以及故障转移和其他机制)也是一项伟大的壮举,与(更简单的)应用程序服务器不同,它有利于 Web 应用程序。
基本服务器架构示例:
Client Request ----> Nginx (Reverse-Proxy) | /|\ | | `-> App. Server I. 127.0.0.1:8081 | `--> App. Server II. 127.0.0.1:8082 `----> App. Server III. 127.0.0.1:8083
注意: 当应用程序设置为侦听 127.0.0.1
上的传入连接时,只能在本地访问它。 但是,如果您使用 0.0.0.0
,它也将接受来自 外部 的连接。
为生产准备 Droplet
在本节中,我们将为生产准备我们的液滴(即 用于部署我们的应用程序)。
我们将从:
- 更新默认操作系统
- 下载和安装常用的 Python 工具(即 点,虚拟环境)
- 并创建一个虚拟环境来包含应用程序(其中包含其依赖项,例如 CherryPy)。
注意: 此处给出的说明保持简短。 要了解更多信息,请查看我们关于 pip 和 virtualenv 的操作指南文章:常用 Python 工具:使用 virtualenv、使用 Pip 安装和管理包。
更新默认操作系统
注意: 我们将使用最新版本的操作系统在新的 Droplet 上执行以下设置和准备工作。 理论上,在服务器上尝试它们应该不会有问题。 但是,如果您已经在积极使用它,我们强烈建议您在尝试之前切换到新系统。
为确保我们拥有最新可用版本的默认应用程序,我们需要更新我们的系统。
对于基于 Debian 的系统(即 Ubuntu、Debian),运行以下命令:
aptitude update aptitude -y upgrade
对于基于 RHEL 的系统(即 CentOS),运行以下命令:
yum -y update
设置 Python、pip 和 virtualenv
CentOS / RHEL 用户注意事项:
CentOS / RHEL,默认情况下,作为一个非常精简的服务器。 它的工具集很可能已经过时以满足您的需求, 不是 用于运行您的应用程序,而是为服务器的系统工具(例如 百胜)。
为了准备你的 CentOS 系统,需要设置 Python(即 从源代码编译)和 pip / virtualenv 需要使用该解释器安装。
要了解如何使用 pip 和 virtualenv 在 CentOS 6.4 和 5.8 上设置 Python 2.7.6 和 3.3.3,请参阅:如何在 CentOS 上设置 Python 2.7.6 和 3.3.3。
在 Ubuntu 和 Debian 上,默认提供最新版本的 Python 解释器,您可以使用它。 它使我们只需要安装有限数量的附加软件包:
- python-dev(开发工具),
- pip(管理包),
- virtualenv(创建隔离的虚拟环境)。
蟒蛇开发:
python-dev 是一个操作系统级别的包,其中包含用于构建 Python 模块的扩展开发工具。
运行以下命令以使用 aptitude 安装 python-dev:
aptitude install python-dev
点:
pip 是一个包管理器,它将帮助我们安装我们需要的应用程序包。
运行以下命令安装 pip:
curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py | python - curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python - export PATH="/usr/local/bin:$PATH"
您可能需要 sudo 权限。
虚拟环境:
最好在自己的环境中包含 Python 应用程序及其所有依赖项。 可以将环境最好(简单地说)描述为所有内容所在的隔离位置(目录)。 为此,使用了一个名为 virtualenv 的工具。
运行以下命令以使用 pip 安装 virtualenv:
sudo pip install virtualenv
创建自包含的虚拟 (Python) 环境
准备好所有必要的工具供我们使用,我们可以创建一个环境来部署我们的应用程序。
记住: 如果您的项目的开发(本地)机器上没有 virtualenv,您应该考虑创建一个并将您的应用程序(及其依赖项)移动到其中。
让我们首先创建一个文件夹,其中将包含 虚拟环境 和 您的应用程序模块 :
您可以在此处使用任何名称以满足您的需要。
mkdir my_app
我们可以继续进入这个文件夹并在里面创建一个新的虚拟环境:
您还可以为您的虚拟环境选择任何您喜欢的名称。
cd my_app virtualenv my_app_venv
让我们在那里创建一个新文件夹来包含您的 Python 应用程序模块:
这是您的应用程序模块所在的文件夹。
mkdir app
并激活虚拟环境中的解释器以使用它:
如果您选择“my_app_venv”以外的名称,请确保使用您为虚拟环境选择的名称。
source my_app_venv/bin/activate
最后,您的主应用程序部署目录应如下所示:
my_app # Main Folder to Contain Everything Together | |=== my_app_venv # V. Env. folder with the Python Int. |=== app # Your application module |.. |.
下载和安装 CherryPy
为了使用 CherryPy 的 WSGI Web 服务器,我们首先需要下载并安装它。
要使用 pip 安装 CherryPy,请运行以下命令:
pip install cherrypy
注意: 如果您在环境中工作,CherryPy 将安装在那里。 否则,安装会全局可用(即 全系统)。 不建议全局安装。 始终选择在您的服务器和开发机器上使用 virtualenv。
下载和安装 Nginx
CentOS / RHEL 用户注意事项:
以下说明不适用于 CentOS 系统。 请在此处 参阅 CentOS 的说明 。
运行以下命令以使用默认系统包管理器 aptitude 安装 Nginx:
sudo aptitude install nginx
要运行 Nginx,您可以使用以下命令:
sudo service nginx start
要停止 Nginx,您可以使用以下命令:
sudo service nginx stop
要重启 Nginx,可以使用以下命令:
每次重新配置 Nginx 后,都需要重新启动或重新加载才能使新设置生效。
sudo service nginx restart
注意:想了解更多关于Ubuntu上的Nginx,请参考我们的文章:如何在Ubuntu 12.04上安装Nginx。
使用 CherryPy Web 服务器为 Python Web 应用程序提供服务
在本节中,我们将了解 WSGI 应用程序如何与 CherryPy Web 服务器一起工作。 这个过程包括为服务器提供一个 WSGI 应用程序 callable(例如 application = (..)
) 作为入口点。
WSGI
简而言之,WSGI 是 Web 服务器和应用程序本身之间的接口。 它的存在是为了确保各种服务器和应用程序(框架)之间以标准化的方式相互工作,在必要时允许互换性(例如 从开发环境切换到生产环境),这是当今的必备需求。
注意:如果您有兴趣了解更多关于WSGI和Python Web服务器的知识,请查看我们的文章:基于Python的Web服务器比较网络应用程序。
WSGI 应用程序对象(可调用):wsgi.py
如上所述,在 WSGI 上运行的 Web 服务器需要一个应用程序对象(即 您的应用程序的)。
对于大多数框架和应用程序,这包括:
我们将从创建一个示例性的“wsgi.py”开始,然后继续为 CherryPy 创建一个通用的“server.py”。
让我们开始创建一个 wsgi.py 文件来包含一个基本的 WSGI 应用程序。
运行以下命令以使用文本编辑器 nano 创建 wsgi.py:
nano wsgi.py
让我们继续移动(复制/粘贴)内部的基本 WSGI 应用程序代码(应该替换为您自己的应用程序的生产可调用代码):
def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return ["Hello!"]
这是服务器包含的文件,每次请求到来时,服务器使用此应用程序可调用来运行应用程序的请求处理程序(即 控制器)在解析 URL(例如 mysite.tld/控制器/方法/变量)。
放入应用程序代码后,按 CTRL+X,然后按 Y 确认,将此文件保存在虚拟环境和包含实际应用程序的应用程序模块旁边的 my_app
文件夹中。
注意: 这个 WSGI 应用程序是同类中最基本的示例。 您将需要替换此代码块以包含应用程序模块中您自己的应用程序对象。
完成后,您的主应用程序部署目录应如下所示:
my_app # Main Folder to Contain Everything Together | |=== my_app_venv # V. Env. folder with the Python Int. |=== app # Your application module | |--- wsgi.py # File containing application callable |.. |.
创建脚本以使用 CherryPy Web 服务器:server.py
在我们当前的工作目录中(例如 my_app) 文件夹,我们现在需要创建一个 Python 脚本:
- 包括应用程序
- 创建一个或多个 CherryPy Web 服务器实例
- 配置这些服务器实例
- 启动和停止服务器引擎
获取此类脚本的方法有多种,在下面的示例中,我们将使用一种简单但易于配置的方法。
创建一个 server.py 文件以包含使用 nano 的 Web 服务器启动脚本:
nano server.py
在此文件中,写入(复制/粘贴)以下服务器代码段:
# Import your application as: # from wsgi import application # Example: from wsgi import application # Import CherryPy import cherrypy if __name__ == '__main__': # Mount the application cherrypy.tree.graft(application, "/") # Unsubscribe the default server cherrypy.server.unsubscribe() # Instantiate a new server object server = cherrypy._cpserver.Server() # Configure the server object server.socket_host = "0.0.0.0" server.socket_port = 8080 server.thread_pool = 30 # For SSL Support # server.ssl_module = 'pyopenssl' # server.ssl_certificate = 'ssl/certificate.crt' # server.ssl_private_key = 'ssl/private.key' # server.ssl_certificate_chain = 'ssl/bundle.crt' # Subscribe this server server.subscribe() # Example for a 2nd server (same steps as above): # Remember to use a different port # server2 = cherrypy._cpserver.Server() # server2.socket_host = "0.0.0.0" # server2.socket_port = 8081 # server2.thread_pool = 30 # server2.subscribe() # Start the server engine (Option 1 *and* 2) cherrypy.engine.start() cherrypy.engine.block()
按 CTRL+X 并用 Y 确认再次保存并退出。
最后,您的主应用程序部署目录应如下所示:
my_app # Main Folder to Contain Everything Together | |=== my_app_venv # V. Env. folder with the Python Int. |=== app # Your application module | |--- wsgi.py # File containing application callable |--- server.py # Python executable to launch the server |.. |.
运行服务器
要开始为您的应用程序提供服务,您只需使用 Python 安装执行 server.py。
运行以下命令以按照配置启动服务器:
注意: 这将使用激活的 Python 解释器执行脚本,因为我们仍在虚拟环境中工作。 如果未激活,则需要说明路径:my_app/bin/python server.py。
python server.py
这将在前台运行服务器。 如果要停止它,请按 CTRL+C。
要在后台运行服务器,请运行以下命令:
python server.py &
要返回命令行,只需按 Enter。 该应用程序仍将运行。
当您在后台运行应用程序时,您将需要使用进程管理器(例如 htop) 杀死(或停止)它。
配置 Nginx
在设置 CherryPy 以运行我们的应用程序之后,我们现在需要对 Nginx 执行相同的操作,以便它与 CherryPy 服务器通信。 为此,我们需要修改 Nginx 的配置文件:“nginx.conf”
运行以下命令打开 nginx.conf 并使用 nano 文本编辑器对其进行编辑:
sudo nano /etc/nginx/nginx.conf
之后,您可以将文件替换为以下示例配置,以使 Nginx 作为反向代理工作,与您的应用程序对话。
注意:要了解加入SSL支持,请先阅读这篇文章:在Nginx上创建SSL证书。
Web 应用程序的示例配置:
worker_processes 1; events { worker_connections 1024; } http { sendfile on; gzip on; gzip_http_version 1.0; gzip_proxied any; gzip_min_length 500; gzip_disable "MSIE [1-6]\."; gzip_types text/plain text/xml text/css text/comma-separated-values text/javascript application/x-javascript application/atom+xml; # Configuration containing list of application servers upstream app_servers { server 127.0.0.1:8080; # server 127.0.0.1:8081; # .. # . } # Configuration for Nginx server { # Running port listen 80; # Settings to serve static files location ^~ /static/ { # Example: # root /full/path/to/application/static/file/dir; root /app/static/; } # Serve a static file (ex. favico) # outside /static directory location = /favico.ico { root /app/favico.ico; } # Proxy connections to the application servers # app_servers location / { proxy_pass http://app_servers; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } } }
完成修改配置后,按 CTRL+X 并按 Y 确认保存并退出。 您需要重新启动 Nginx 才能使更改生效。
运行以下命令重启 Nginx:
sudo service nginx stop sudo service nginx start
注意:想了解更多关于Nginx的知识,请参考我们的文章:如何在VPS上配置Nginx Web服务器。
其他提示和建议
防火墙:
保护 SSH:
创建警报:
每天监控和观察服务器访问日志: