Django项目的部署


单服务器 + 小型的项目 Single-Server for Small Projects

缺点:无法迅速扩展,不支持突发流量

何时选择这种方式

如果之前没有相关经验的。这种方式能让你深入理解 Python Web 应用的工作原理。

如果你的项目是实验性或试着玩的。

如果你确信单台服务器性能足够。

实例 Ubuntu + Guniorn 快速设置

➤ An old computer or cheap cloud server
➤ Ubuntu Server OS
➤ PostgreSQL
➤ Virtualenv
➤ Gunicorn
  • 安装相关的依赖

pip/virtualenv: python-pip, python-virtualenv

PostgreSQ: postgresql, postgresql-contrib, libpq-dev, python-dev

其它的程序和包(比如 Django 和 Gunicorn 等),能用 pip 安装的都用 pip 安装。

  • 运行

gunicorn myproject.wsgi ,即可在浏览器中通过服务器的 IP 地址访问了

How to use Django with Gunicorn

中大型项目用多台服务器 Multi-Server for Medium to Large Projects

需要的服务器:

数据库服务器:如 PostgreSQL 和 MySQL

WSGI 应用服务器: 如 uWSGI,Gunicorn + Nginx, Apache + mod_wsgi

静态文件服务器: 自己的服务器可以用 Nginx 或 Apache。但是 CDN (如 Amazon CloudFront) 可能更经济

缓存/异步消息队列服务器:如 Redis,Memcached 或 Varnish

其它服务器: 其它的 CPU 密集型任务,或者涉及等待外部接口的任务可以从 WSGI 应用服务器上分流出去

所有的临时数据都用 Redis 保存

Redis 和 Memcached 类似,但它还有以下的功能

认证功能
能保持状态,因此服务器重启后能恢复数据
额外的数据类型使其能作为异步消息队列使用(可以和 celery 和 rq 一起使用)

对每台服务器上的进程进行管理

Supervisord

initscripts

高级的多服务器设置 Advanced Multi-Server Setup

负载均衡设备

可以是硬件也可以是软件。

基于软件的: HAProxy, Varnish, Nginx
基于硬件的: Foundry,Juniper,DNS load balancer
基于云的: Amazon Elastic Load Balancer,Rackspace Cloud Load Balancer

水平和垂直扩展

水平扩展是增加多台服务器来分流负载。

垂直扩展是对现有服务器硬件进行升级,如加内存等。因此,垂直扩展更加容易。

解决水平扩展时的 会话维持问题

如上传文件时访问的是 server1,但是后来返回时,通过负载均衡器,访问的是 server2。

解决这个问题的一般方法是将上传的数据保存到一个共享的驱动器中或到云服务器中(如 Amazon S3)

WSGI 应用服务器 WSGI Application Servers

Django 项目一定要用 WSGI 部署。

1 常用的 WSGI 部署设置:

uWSGI + Nginx

Gunicorn 置于 Nginx 代理后

Apache + mode_wsgi
设置方式 优点 缺点
uWSGI + Nginx 有大量的功能和选项。配置非常灵活。据说性能比其它的都好 文件还在完善。使用时间比 Apache 少。相比较对新手不太友好
Gunicorn (sometimes with Nginx) 用纯 Python 实现 文档少
Apache + mod_wsgi 非常稳定,文档相当多 无法使用环境变量,Apache 配置可能很复杂

2 性能优化 uWSGI Gunicorn

As of now, uWSGI is more configurable, but Gunicorn is very configurable too, and arguably easier to configure.

related doc:

uWSGI

How to use Django with uWSGI

gunicorn

How to use Django with Gunicorn

uwsgi-vs-gunicorn

3 稳定且容易部署的 Gunicorn and Apache

Apache used to be the easiest option

Gunicorn has come a long way.

These days, with Gunicorn and the default Django-provided wsgi.py file, the setup “just works” with zero or minimal debugging

4 Apache 中的问题

  • 不要使用 mod_python, 使用 mod_wsgi

    Django’s mod_python support was deprecated in Django 1.3.

    In Django 1.5, the mod_python request handler was removed from Django

  • Apache 和 环境变量

Apache 不支持环境变量。

因此需要将保密值先放在 .ini、.cfg、.json、.xml 文件中, 然后再导入配置文件中。

  • Apache 和 Virtualenv

Apache 和 virtualenv 很容易使用:

如果使用 mod_wsgi 3.4 +

daemon 模式 在WSGIDaemonProcess 指令下添加: python-home:/some/path/to/root/of/virtualenv

embded 模式 在WSGIDaemonProcess 指令下添加: WSGIPythonHome /some/path/to/root/of/virtualenv

如果使用 mod_wsgi 3.3 -

daemon 模式 在 WSGIDaemonProcess 下设置 python-path=/some/path/to/root/of/virtual/lib/pythonX.Y

自动化部署

服务器的配置应该自动化并且注明文档

应该能通过一个命令就可配置一台全新的服务器。

这个命令应该有准确的文档描述。

运行该命令时,应该不与现存的服务器存在依赖关系。

任何一个脚本都应该是幂等的,无论它们运行多少次。

1 配置管理工具的变化:

日期 配置管理工具
直到 2011 年 Chef/Puppet
2012 年 最好的是 Chef/Puppet,Salt/Ansible 还在开发
2013 年 1 月 Chef/Puppet 还很强, Salt/Ansible 正变得流行
2013 年 5 月 Docker 开源
2014 年 1 月 Salt/Ansible 变得稳定和流行,Chef/Puppet 不再流行,Docker 还在开发
2015 年 5 月 Docker 变得流行,Salt/Ansible 还在变强,Chef/Puppet 快速衰亡
2016 年 Docker 成熟

2 使用哪个自动管理工具

当前流行的自动化工具

Docker, Ansible, SaltStack, Puppet 和 Chef 都很流行。

由于这些工具意在管理多台主机,因此都变得越来越复杂。

这些工具具有的功能:

远程执行

在远程服务器上安装程序

在远程服务器上运行命令

在远程服务器上开启服务

当命令在远程执行时,将日志和应答返回本地

配置管理

创建或更新服务器上的 conf 文件。

     如为一个新安装的 PostgreSQL 实例创建 pg_hba.conf 文件
    
为不同的服务器设置不同的配置值,

     如基于服务器 IP 或 OS 相关信息进行配置

业务流程和目标:

控制任务将发给哪台服务器,何时发送

管理不同组件,创建管道用于处理不同的工作流

从主服务器上将任务推送到其它服务器,用 ‘push mode’

询问主服务器需要实现什么, 有 ‘pull mode’

区别:

工具 优点 缺点
Docker 由于只需关注变动的部分,故部署很快。容器方式。YAML 配置。社区大。开源 用 Go 编写。还在开发
SaltStack YAML 配置。网上有大量示例。社区大。开源。用 Python 实现。 可能会变得非常复杂。还不够成熟
Ansible OpenSSH,无需运行其它后台程序。易于学习。YAML 配置。开源。用 Python 实现。 用 SSH 传输较慢,但通用 Fireball 模式可以临时设置一个 Omq 后台进程。还不够成熟。
Chef 大量的示例。社区大。开源。 非常难学。用 Ruby 实现。非常复杂
Puppet 社区大。开源。 非常难学。用 Ruby 实现。配置文件用自定义的 DSL 编写,很难用。

另:

关于 FabricInvoke

它们只关注实现在远程执行命令

常和上面提到的这些工具一起使用。

现在的趋势是使用 Docket, SaltStack 和 Ansible。

部署的准备工作

上线前的检查工作。

python manage.py check --deploy

将DEBUG设置为False并配置ALLOWED_HOSTS。

DEBUG = False
ALLOWED_HOSTS = ['*']

安全相关的配置。

# 保持HTTPS连接的时间
SECURE_HSTS_SECONDS = 3600
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# 自动重定向到安全连接
SECURE_SSL_REDIRECT = True

# 避免浏览器自作聪明推断内容类型
SECURE_CONTENT_TYPE_NOSNIFF = True

# 避免跨站脚本攻击
SECURE_BROWSER_XSS_FILTER = True

# COOKIE只能通过HTTPS进行传输
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

# 防止点击劫持攻击手段 - 修改HTTP协议响应头
# 当前网站是不允许使用<iframe>标签进行加载的
X_FRAME_OPTIONS = 'DENY'

敏感信息放到环境变量或文件中。

SECRET_KEY = os.environ['SECRET_KEY']

DB_USER = os.environ['DB_USER']
DB_PASS = os.environ['DB_PASS']

REDIS_AUTH = os.environ['REDIS_AUTH']
Buy me a 肥仔水!