如何部署基于 Pyramid 的 Python WSGI Web 应用程序
简介
当你第一次开始开发 Python web 应用程序时,特别是如果你来自不同的编程语言或者有桌面(GUI)应用程序的背景,你可能会在将你的新作品上线的过程中感到有些迷茫。
在这篇文章中,我们将继续之前关于使用不同的 web 服务器开始使用 Pyramid 并部署 Python web 应用程序的文章,我们将了解如何打包一个 Pyramid WSGI web 应用程序,创建其依赖项列表,并将其部署(即发布到线上)。
注意: 本文的示例,尽管也提供了一个使用示例,但是遵循了之前入门文章中使用的命名约定。如果你对使用 Pyramid 开始 web 应用程序开发有疑问,或者只是想熟悉之前使用的名称,你可以在这里查看文章。
术语表
1. 简要介绍 Pyramid
- Web 应用程序部署
- WSGI
- 使用 Nginx 作为反向代理
2. 部署基于 Pyramid 的 WSGI Web 应用程序
- 更新系统
- 设置 Python、pip 和 virtualenv
- 准备一个暴露了 “app” 对象的简单应用程序
- 使用 .ini 设置暴露一个脚手架应用程序对象
- 使用 pip 处理应用程序依赖项
- 创建应用程序依赖项列表
- 从应用程序依赖项列表中下载
3. 设置 Python WSGI Web 应用程序服务器
- 使用 CherryPy Web 服务器提供 Pyramid 应用程序
- 运行和管理应用程序服务器
4. 设置 Nginx
- 安装 Nginx
- 配置 Nginx
简要介绍 Pyramid
与一些较重的对手相比,Pyramid 是一个轻量级的 Python web 应用程序框架之一。然而,与 Flask 或其他 “微型” 框架不同,Pyramid 仍然具有许多内置功能和功能。
作为一个非常好的项目,Pyramid 非常受欢迎,并且有几种不同的方式(web 服务器和方法)可以部署基于它的 web 应用程序。
Web 应用程序部署
对于所有 Python WSGI web 应用程序来说,部署包括准备一个包含对你的 应用程序 对象的引用的 WSGI 模块,然后该对象被用作 web 服务器传递请求的入口点。
WSGI
简而言之,WSGI 是 web 服务器和应用程序本身之间的接口。它存在的目的是确保各种服务器和应用程序(框架)之间的标准化工作方式,允许在必要时进行互换(例如从开发环境切换到生产环境),这是当今必不可少的需求。
注意: 如果你对了解更多关于 WSGI 和 Python web 服务器感兴趣,可以查看我们的文章:Python 基于 Web 应用程序的 Web 服务器比较。
使用 Nginx 作为反向代理
Nginx 是一个非常高性能的 web 服务器 /(反向)代理。它因为轻量级、相对易于使用和易于扩展(使用插件/扩展)而受到欢迎。由于其架构,它能够处理 大量 的请求(几乎无限),这取决于你的应用程序或网站负载,使用其他一些老旧的替代方案可能会很难应对。
记住: “处理” 连接在技术上意味着不丢弃它们,并且能够用 某些东西 来提供它们。你仍然需要你的应用程序和数据库正常运行,以便 Nginx 提供不是错误消息的客户端响应。
Python WSGI Web 应用程序服务器
Python web 应用程序服务器通常是独立的基于 C 的解决方案或者完全(或部分)基于 Python 的(即纯 Python)解决方案。
它们通过接受一个包含 - 如前面所述 - 用于 包含 web 应用程序并在网络上提供它的应用程序可调用的 Python 模块来运行。
尽管其中一些是非常有能力的服务器,可以直接使用,但基于上面提到的原因(例如更高的性能),建议在前面使用 Nginx。同样,通常随 web 应用程序框架一起提供的开发服务器不建议在生产中使用,因为它们缺乏功能 - 当然也有一些例外!
一些流行的 Python WSGI web 服务器包括:
-
CherryPy
-
Gunicorn
-
uWSGI
-
waitress
部署基于 Pyramid 的 WSGI Web 应用程序
由于 Python 的 WSGI 中间件规范,对于所有设置为在该协议上运行的应用程序,有许多选择可供选择的 web 应用程序服务器。
总结:更新系统
为了拥有一个稳定的部署服务器,保持系统更新和良好维护是至关重要的。
为了确保我们拥有默认应用的最新版本,我们需要更新我们的系统。
对于基于 Debian 的系统(如 Ubuntu、Debian),运行以下命令:
aptitude update
aptitude -y upgrade
对于基于 RHEL 的系统(如 CentOS),运行以下命令:
yum -y update
提示: 对于 CentOS,upgrade
意味着升级操作系统。然而,update
更新应用程序。对于 Debian/Ubuntu,update
更新应用程序源列表,upgrade
升级应用程序到它们的新版本。
总结:设置 Python、pip 和 virtualenv
对于 CentOS / RHEL 用户:
CentOS / RHEL 默认是一个非常精简的服务器。它的工具集可能对你的需求来说过时,它们不是用来运行你的应用程序,而是用来支持服务器的系统工具(例如 YUM)。
为了准备你的 CentOS 系统,需要设置 Python(即从源代码编译)并使用该解释器安装 pip / virtualenv。
要了解在 CentOS 6.4 和 5.8 上设置 Python 2.7.6 和 3.3.3,以及 pip 和 virtualenv,请参考:在 CentOS 上设置 Python 2.7.6 和 3.3.3。
在 Ubuntu 和 Debian 上,默认提供了一个可以使用的最新版本的 Python 解释器。这让我们只需要安装有限数量的额外软件包:
-
python-dev – 开发工具
-
pip – 用于管理软件包
-
virtualenv – 用于创建隔离的虚拟环境
python-dev:
python-dev 是一个操作系统级别的软件包,其中包含了用于构建 Python 模块的扩展开发工具。
运行以下命令使用 aptitude 安装 python-dev:
aptitude install python-dev
pip:
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 权限。
virtualenv:
最好将 Python 应用程序及其所有依赖项放在自己的环境中。一个环境可以最好地描述为一个隔离的位置(一个目录),其中包含了一切。为此,使用一个名为 virtualenv 的工具。
运行以下命令使用 pip 安装 virtualenv:
sudo pip install virtualenv
准备一个简单的应用程序,暴露“app”对象
注意: 本节重点是从上一个教程中将我们的示例单页面应用程序上线。
目前,我们有一个单页面应用程序(即 application.py
),它构建为使用 Pyramid 的开发服务器在端口 8080 上提供“Hello world!”。
我们当前的工作目录位于 ~/pyramid_sites/hello_world
我们当前的 Pyramid 应用程序示例(application.py
)如下:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('<h1>Hello world!</h1>')
if __name__ == '__main__':
config = Configurator()
config.add_view(hello_world)
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
为了将此示例转换为包含 WSGI 可调用的模块,我们可以进行以下修改:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('<h1>Hello world!</h1>')
# 将应用程序对象移到这里。
# 创建一个配置器来制作 *wsgi 应用(lication)*
config = Configurator()
config.add_view(hello_world)
# 要暴露的“app”对象
app = config.make_wsgi_app()
# 如果直接运行,仍然构造一个[开发]服务器进程,并开始在端口#8080上提供服务。
if __name__ == '__main__':
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
修改后,按下 CTRL+X 并确认 Y 保存并退出。
从现在开始,我们可以将此文件作为一个模块传递给任何 Python WSGI web 服务器,其中包含了可调用的应用程序。
使用 .ini 设置暴露一个搭建好的应用对象
或者,如果您使用 Pyramid 的脚手架创建了一个更复杂的应用程序,您可以构建一个 wsgi.py
文件,其中包含一个使用 Pyramid 的 “.ini” 文件来加载部署(或开发)配置的应用程序。
注意: 该文件需要位于您的根应用程序文件夹内,与 requirements.txt
或您的 .ini 文件一起。它通过将您的应用程序作为一个对象来工作。
注意: 你可以在这个文件中选择任何名称(包括 application.py
)。然而,wsgi.py
可能 - 并且通常 - 比其他名称更可接受。
使用 nano 文本编辑器创建 wsgi.py
文件,运行以下命令:
nano wsgi.py
复制并粘贴以下内容:
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.paster import get_app
def hello(request):
return Response('Hello!')
config = Configurator()
config.add_route('hello', '/')
config.add_view(home, route_name='hello')
app = config.make_wsgi_app()
# 或者从 .ini 文件中获取:
# app = get_app('config.ini', 'application_name')
使用 pip 处理应用程序依赖关系
由于您很可能已经在本地机器上开始了开发过程,当部署应用程序时,您需要确保所有依赖项都已安装(在您的虚拟环境内)。
创建应用程序依赖项列表
在生产环境中获取依赖项的最简单方法是使用 pip。通过一个命令,它能够生成您已安装的所有软件包(或依赖项),并且再次通过一个命令,它允许您下载并安装它们。
注意: 本节包含要在本地开发机器上执行的信息,或者您想要生成应用程序依赖项列表的任何地方。该文件应放在应用程序目录中并上传到服务器上。
使用 “pip” 创建已安装软件包的列表:
pip freeze > requirements.txt
此命令将创建一个名为 “requirements.txt” 的文件,其中包含所有已安装软件包的列表。如果您在虚拟环境中运行它,列表将包含仅在该环境内安装的软件包。否则,所有全局安装的软件包将被列出。
从应用程序依赖项列表中下载
使用 pip 从列表中安装软件包:
注意: 本节包含要在生产(即部署)机器/环境上执行的信息。
pip install -r requirements.txt
此命令将下载并安装所有列出的软件包。如果您在激活的环境中工作,文件将在那里下载。否则,它们将被全局安装 - 这不是前面部分所述原因的推荐方式。
设置 Python WSGI Web 应用程序服务器
在设置好我们的 Pyramid 应用程序以暴露其应用对象之后,我们可以开始使用下载和安装我们选择的 Web 应用程序服务器来进行实际部署过程。
在本文中,我们将专注于使用 CherryPy,因为它具有的功能和简单性。
注意: 这里给出的说明很简要。要了解更多,请查看我们的有关 pip 和 virtualenv 的 how-to 文章 Common Python Tools: virtualenv and pip。如果您正在使用基于 CentOS 的服务器,您可能还想查看如何在 CentOS 上设置 Python 2.7.6 和 3.3.3 的文章。
使用 CherryPy Web 服务器提供 Pyramid 应用程序
CherryPy 的纯 Python Web 服务器是一个紧凑的解决方案,它与同名框架一起提供。该项目定义为“高速、生产就绪、线程池化、通用 HTTP 服务器”,它是一个模块化组件,可用于提供任何 Python WSGI Web 应用程序。
在我们的第一个 Pyramid 教程之后,我们可以继续在虚拟环境(~/pyramid_sites/env)中工作并在那里安装 CherryPy。如果您在不同位置创建了另一个虚拟环境,您也可以在那里进行安装。
# 安装 CherryPy 框架和 HTTP Web 服务器
pip install cherrypy
安装应用程序包后,为了提供您的 Pyramid 应用程序,您需要为您的 Python 解释器创建一个 “server.py” 文件来运行。正是这个文件包含了您的应用程序包,并使用 CherryPy 的 Web 服务器来提供它。
要创建一个 server.py 文件,运行以下命令:
nano server.py
复制并粘贴以下内容以创建一个使用 CherryPy 的 HTTP 服务器的示例服务器应用程序:
# 导入您的应用程序,例如:
# from wsgi import application
# 示例:
# 如果您使用 wsgi.py(标准 Pyramid)
# from wsgi import app
# 如果使用 application.py(单页示例):
from application import app
# 导入 CherryPy
import cherrypy
if __name__ == '__main__':
# 挂载应用程序(或 *app*)
cherrypy.tree.graft(app, "/")
# 取消订阅默认服务器
cherrypy.server.unsubscribe()
# 实例化一个新的服务器对象
server = cherrypy._cpserver.Server()
# 配置服务器对象
server.socket_host = "0.0.0.0"
server.socket_port = 8080
server.thread_pool = 30
# 对 SSL 支持
# server.ssl_module = 'pyopenssl'
# server.ssl_certificate = 'ssl/certificate.crt'
# server.ssl_private_key = 'ssl/private.key'
# server.ssl_certificate_chain = 'ssl/bundle.crt'
# 订阅此服务器
server.subscribe()
# 第二个服务器的示例(与上述步骤相同):
# 记得使用不同的端口
# server2 = cherrypy._cpserver.Server()
# server2.socket_host = "0.0.0.0"
# server2.socket_port = 8080
# server2.thread_pool = 30
# server2.subscribe()
# 启动服务器引擎(选项 1 *和* 2)
cherrypy.engine.start()
cherrypy.engine.block()
运行和管理应用服务器
要开始提供您的应用程序,您只需要使用您的 Python 安装执行 server.py
。
运行以下命令以启动配置的服务器:
python server.py
这将在前台运行服务器。如果您想要停止它,请按下 CTRL+C。
要在后台运行服务器,请使用以下命令:
python server.py &
当您在后台运行应用程序时,您将需要使用进程管理器(例如 htop)来终止(或停止)它。
设置 Nginx
安装 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。
配置 Nginx
注意: 以下是使用 Nginx 作为反向代理的简短教程。要了解有关 Nginx 的更多信息,请查看在 VPS 上配置 Nginx Web 服务器的文章。
在选择和设置运行我们应用程序的 Web 服务器后,我们可以继续使用 Nginx 并准备它与后端服务器(运行 WSGI 应用程序)进行通信。
为了实现这一点,我们需要修改 Nginx 的配置文件:nginx.conf
运行以下命令以打开 nginx.conf 并使用 nano 文本编辑器进行编辑:
sudo nano /etc/nginx/nginx.conf
您可以使用以下示例配置替换文件,使 Nginx 作为反向代理与您的应用程序通信。
复制并粘贴以下示例配置:
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;
# 包含应用服务器列表的配置
upstream app_servers {
server 127.0.0.1:8080;
# server 127.0.0.1:8081;
# ..
# .
}
# Nginx 的配置
server {
# 运行端口
listen 80;
# 用于提供静态文件的设置
location ^~ /static/ {
# 示例:
# root /full/path/to/application/static/file/dir;
root /app/static/;
}
# 提供静态文件(例如 favico)
# 在 /static 目录之外
location = /favico.ico {
root /app/favico.ico;
}
# 代理连接到应用服务器
# 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 后,您现在可以通过您喜爱的浏览器访问它,使用您的 droplet 的 IP 地址。
http://[您的 droplet 的 IP 地址]/
# Hello world!