Django服务器设置之旅--第一部分

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

如果没有大量部署过Django应用程序的经验,你可能会想知道:专业人员怎么把Django应用程序放到互联网上?当投入生产的时候,Django通常是什么样子的?你甚至可能在想到底什么是生产?


从事开发工作之前,我本应该了解生产基础架构的相关知识,脑子里却是模糊一片。如果你跟我一样,我们一起来解决吧。为了实现更好的性能、成本效益和可靠性,我们有很多扩展Django服务器设置的方法。本文将带你了解一些常见的Django服务器设置,从最简单、最基本的设置到更复杂、更强大的设置。我希望这能建立你的心智模型,让你了解Django是怎么逐步托管到生产环境中的。


你的本地机器


我们首先回顾一下你熟悉的Django设置:你的本地机器,为后面的章节做准备。在本地运行Django时,你有:


  • 网络浏览器(Chrome,Safari,Firefox等)

  • 用runserver管理命令运行的Django

  • 项目文件夹中的SQLite数据库


1.png


很简单吧?接下来,让我们看看部署到web服务器的类似的东西。


最简单的Web服务器


你能设置的最简单的Django web服务器与本地开发环境很像。大多数专业的Django开发人员不会在生产环境中使用这样的基本设置。这种设置可以很好地完成工作,但是有一些局限性,我们会在后面讨论。它看起来像这样:

2.png


通常,人们用Ubuntu发行版在Linux虚拟机上运行Django。虚拟机由云提供商托管,如Amazon、Google、Azure、DigitalOcean、Linode等。


你应该用Gunicorn这样的WSGI服务器来运行Django应用,而不是runserver 。否则,和本地机器没有太大区别:你仍然可以用SQLite作数据库(这里有详细介绍https://mattsegal.dev/simple-django-deployment-2.html#sqlite)。这里(https://mattsegal.dev/simple-django-deployment-2.html#wsgi)解释了WSGI。


这是设置的基本内容,还有其他细节需要处理,例如设置DNS、虚拟环境、使用诸如Supervisord之类的进程管理工具来管理Gunicorn, 或者如何用Whitenoise为静态文件提供服务。如果你对如何设置这样的简单服务器感兴趣,我写过一篇指南(https://mattsegal.dev/simple-django-deployment.html),解释了如何部署Django。


典型的独立Web服务器


我们来回顾一下专业Django开发人员使用单个服务器的时候可能在生产环境中设置的环境。这不是每个人都会使用的设置,但其结构非常常见。

3.png



有些与上面的简单设置相同:它仍然是Linux虚拟机,Django由Gunicorn运行。有三个主要区别:


  • SQLite已经被另一个数据库PostgreSQL取代

  • 一个NGINX Web服务器位于Gunicorn前面,采用反向代理设置

  • Django外部提供静态文件


为什么要把SQLite换成PostgreSQL?总的来说,Postgres更高级,功能更全面。例如,Postgres可以同时处理多个写操作,而SQLite不能。


为什么要在设置中添加NGINX?NGINX是专用的Web服务器,与仅使用Gunicorn来处理Web请求相比,它提供了额外的功能和性能改进。例如,我们可以使用NGINX直接为应用程序的静态文件和媒体文件提供服务,这样更高效。NGINX还可以配置其他许多有用的功能,例如用HTTPS加密网络流量,压缩文件,让网站更快。NGINX是最常与Django结合使用的Web服务器,我们也可以选择其他服务器,例如Apache HTTP服务器和Traefik。


需要注意的是,这里的所有内容都位于一台服务器上,这意味着如果服务器不可用,所有数据也都会消失,除非有备份。这些数据包括存储在Postgres中的Django表和用户上传的文件,这些文件会存储在文件系统的MEDIA_ROOT文件夹。只有一台服务器还意味着,如果服务器重启或关闭,网站也会重启或关闭。对小项目来说,这是可以的,但对于StackOverflow或Instagram这样的大型网站来说不行,因为它们的停机成本很高。


带有多个应用程序的单个Web服务器


一旦开始使用NGINX和PostgreSQL,就可以在同一台机器上运行多个Django应用程序。把多个应用打包到一台服务器上,而不是为每个应用分别购买一台服务器,可以节省托管费用。这样,就可以重用一些设置好的服务和配置。


NGINX可以根据域名将传入的HTTP请求路由到不同的应用程序,Postgres可以在一台机器上托管多个数据库。例如,我用一台服务器托管我的一些个人Django项目:Matt’s Links,Memories Ninja和Blog Reader。


4.png


简单起见,我省略了静态文件。注意,在一台服务器上安装多个应用程序可以节省托管成本,但是有缺点:重启服务器会重启所有应用程序。


带有辅助进程的单个Web服务器


一些Web应用程序需要做的不仅仅是CRUD。比如,我的网站Blog Reader要从网站上抓取文本,然后将其发送到Amazon API,转换为音频文件。另一个常见的例子是“缩略图”,上传一个5MB的超大图片到Facebook,Facebook会把它缩小为120kB的JPEG格式。这类任务不会在Django视图中发生,因为它们的运行时间太长了。相反,它们必须使用Celery,Huey,Django-RQ或Django-Q等工具在单独的工作进程中“脱机”运行。这些工具提供了一种在Django视图之外运行任务的方法,可以完成更复杂的任务,比如协调多个任务并按计划运行。


这些工具都遵循类似的模式:由Django分派任务,并放入队列等待执行。该队列由一个称为“代理”的服务管理,它跟踪所有需要完成的任务。Django任务的常用代理是Redis和RabbitMQ。工作进程使用和Django应用相同的代码库,从代理中取任务并运行。


5.png


如果你以前没有用过任务队列,可能还不清楚这一切是如何工作的。举个例子,你想把一张手机里的2MB 早餐照片上传到Django网站。为了优化图像加载性能,Django网站会把2MB的照片上传为70kB的显示图像和更小的缩略图。这是整个过程:


  • 用户将照片上传到Django视图,Django视图将原始照片保存到文件系统,并更新数据库,显示文件已接收

  • 视图将缩略图任务推送到任务代理

  • 代理接收任务并放到队列,等待执行

  • 辅助进程向代理请求下一个任务,代理发送缩略图任务

  • 辅助进程读取任务描述,运行Python函数,该函数从文件系统读取原始图像,创建较小的缩略图,保存,然后更新数据库,显示缩略图已完成


如果你想了解更多这方面的知识,我写了有关使用Django Q 进行离线任务(https://mattsegal.dev/offline-tasks.html)和计划任务(https://mattsegal.dev/simple-scheduled-tasks.html)的指南以供参考。


带缓存的单个Web服务器


有时候,你想用缓存来短期存储数据。比如,当你有一些从数据库或API提取成本很高的数据,并且想重用一段时间的时候,通常会使用缓存。Redis和Memcached都是Django生产中常用的缓存服务。这不是一个非常复杂的设置。


6.png


带Docker的单个Web服务器


如果之前听说过Docker,你可能想知道它在这些设置中的作用。对于创建一致的编程环境来说,这是一个很好的工具,但它不会过多地改变它们的工作方式。我描述的大多数设置基本上都以同样的方式工作……除了所有东西都在Docker容器内。


例如,如果你在一台服务器上运行多个Django应用,想用Docker容器,就可以使用Docker Swarm进行以下操作:


7.png


如你所见,和我们在Docker之前所做的相比,它的结构没有什么不同。容器只是我们已经运行的服务的包装器。把东西放入Docker容器不会改变服务间的通信方式。如果你想,可以用Docker容器包装更多东西,如NGINX、数据库、Redis缓存等。这就是为什么我说要先学习如何在没有Docker的情况下部署Django。也就是说,你可以用Docker容器进行一些更复杂的设置,稍后我们将对此进行讨论。


外部服务


目前为止,我展示了只有一台运行Ubuntu的虚拟机的服务器设置。这是能用的最简单的设置,但是有局限性:有些东西可能是一台服务器无法提供的。在本节中,我将介绍如何将单个服务器分解成更高级的设置。


如果学过编程,你可能读过有关关注点分离、单一责任原则和 模型视图控制器(MVC)的知识。我们要做的许多更改和这些类似:根据服务的“职责”把它们分成更小、更专业的单位。一点一点地把服务拆分,直到不能再分。注意:你可能不用这么做,这只是可执行操作的概述。


外部服务-数据库


首先要从服务器取数据库,包括把PostgreSQL放到它自己的虚拟机。你可以自己设置,也可以额外付费获取Amazon RDS这样的现成服务。


8.png


把数据库放在它自己的服务器上有以下原因:


  • 你可能在基于同一数据库的不同服务器上有多个应用程序

  • 数据库性能不会受“噪音邻居”占用同一台机器上CPU、RAM或磁盘空间的影响

  • 你已经从Django Web服务器移走了数据库,可以删除重建Django应用程序的服务器,不必担心

  • 安全性考虑


选择AWS RDS这样现成的很有吸引力,因为它减少了运行数据库服务器所需的管理工作量。如果你是后端Web开发人员,有大量工作要做,又不差钱,这是一个不错的选择。


英文原文:https://mattsegal.dev/django-prod-architectures.html
译者:momo