Django的无缝部署到单服务器

5
我有一个基于Django和Python 2.6构建的新网站,已经部署到云端(符合流行语,并且Amazon微型EC2实例是免费的!)。以下是我的详细笔记:https://docs.google.com/document/d/1qcZ_SqxNcFlGKNyp-CXqcFxXXsKs26Avv3mytXGCedA/edit?hl=en_US 由于这是一个新网站(想要玩最新的),我使用了Nginx和Gunicorn来管理Supervisor。所有软件都是从trunk中使用YUM/easy_install安装的。我的数据库是Sqlite(目前还不确定下一步该怎么做,但这不是问题所在)。还在待办事项列表中:virtualenv + pip。到目前为止一切顺利。我的代码在SVN中。我编写了一个简单的fabfile来进行部署——检出最新的代码并通过Supervisor重新启动Gunicorn。我将我的DNS名称与弹性IP关联起来。它工作了。 我的问题是,如何在不影响服务的情况下更新网站?当我运行我的小型更新脚本时,网站用户会收到404 / 500错误。
有没有一种方法可以做到这一点而不添加另一个服务器(价格很重要)?
我希望有一个分段系统(在不同的端口上?),并且可以在Staging和Production之间进行无缝切换。在同一(免费)服务器上。通过Fabric。
我该怎么做?是否使用相同的Nginx运行两个站点?我可以升级Staging而不伤害Production吗?fabfile会是什么样子?目录树会是什么样子?
谢谢!
Tal。
相关链接:

对于任何阅读“EC2微型免费”的人:它实际上并不是免费的(至少不再是)。它在前750小时内是免费的,这大约相当于20美元的优惠。请查看其他ASW免费优惠 - Stefano
2个回答

3
Nginx允许您为反向代理设置故障转移,您可以将一个gunicorn实例作为主实例,只要该版本正在运行,它就不会查看故障转移。如果您将新版本配置为故障转移实例,则只需要编写fab文件以使用站点的新版本更新故障实例,然后在准备好时关闭主实例。Nginx将无缝切换到第二个实例,您将在没有停机时间的情况下运行新版本。
然后,您可以更新主要版本,然后将其重新启动,您的主要版本现在是活动的。此时,您可以保持故障转移实例运行以防万一,或者关闭它。
需要考虑一些事情。您必须小心数据库,如果您正在使用sqllite,请确保两个gunicorn实例都可以访问sqllite文件。
如果您有普通数据库,则这不是问题,您只需要确保在切换到新版本之前应用任何数据库迁移即可。
如果它们是向后兼容的更改,则不是什么大问题。如果它们不向后兼容,请小心,您可能会在切换到新版本之前破坏旧版本的站点。
为了使事情变得更容易,我会在不同的虚拟环境中运行版本。
如果您使用supervisord来控制gunicorn,则可以使用supervisorctl命令重新加载/重启任何要部署的实例,而不会影响其他实例。
希望这有所帮助。
以下是nginx配置示例(不是完整的配置文件,删除了不重要的部分)。
假设主要的gunicorn实例正在端口9005上运行,另一个实例正在端口9006上运行。
upstream service-backend {
    server localhost:9005;        # primary
    server localhost:9006 backup; # only used when primary is down
}

server {
    listen 80;
    root /opt/htdocs;
    server_name localhost;

    access_log /var/logs/nginx/access.log;
    error_log  /var/logs/nginx/error.log;

    location / {
        proxy_pass http://service-backend;
    }
}

我该如何配置Nginx来实现这个功能?这是我的Nginx配置:http://pastebin.com/xdYxPeS2。我可以同时运行两个Gunicorn监听不同的端口(Staging / Production),并且仍然像你描述的那样进行切换吗? - Tal Weiss
添加了nginx的示例配置。是的,您可以在不同端口上同时运行它们。最好的方法是使用supervisord或其他进程管理器来实现。 - Ken Cochrane
这使我能够拥有两个Gunicorn,每个都有不同的软件,并且可以使用Supervisorctl杀死正在运行的Gunicorn,让Nginx管理切换。但是,我如何测试运行新软件的备份服务器?它没有连接到外部世界。在此配置中,Nginx监听的唯一端口不是80吗? - Tal Weiss
@Tal,您可以设置第二个服务器配置,该配置在不同的端口上运行,或者在相同的端口上但使用不同的URL(子域名?),并确保代理传递仅使用备份服务器。 - Ken Cochrane
@Ken,但是切换将涉及更改nginx配置(并重新启动ngnix)吗?除非我有3个独角兽-1个运行当前的SW,1个备份新的SW和1个分段侦听不同端口。我将测试分段服务器,如果正常,则切换到备份服务器。这有意义吗? - Tal Weiss
@Tal 不需要更改nginx配置,除非你想关闭暂存服务器,但你可以轻松地关闭guincorn实例,就可以做到。你的计划听起来很可行,你可能只需要两个实例就能完成,但3个实例更安全。 - Ken Cochrane

1

听起来您需要弄清楚如何告诉gunicorn进行优雅重启。似乎您只需向gunicorn进程发出一个HUP信号,以通知其重新加载应用程序即可。正如所述的链接所述,gunicorn文档解释了如何执行此操作。


Gunicorn是否可以“优雅地”进行重启?所有网站用户是否会像什么都没有发生一样继续使用?当Nginx向Gunicorn端口发送作业但短暂时间内没有人监听时,这是如何工作的?此外,这并未解决源代码升级的问题 - 新的Gunicorn实例如何知道运行新代码? - Tal Weiss
通常,“优雅重启”是指在重新启动时不丢失任何请求。我已经阅读了一些有关独角兽和gunicon的材料。我相信当您发出SIGHUP时正在处理的请求将完成处理,因为您的新代码正在启动。此外,独角兽被设计为在工作进程“准备就绪”时从请求队列中拉取请求。这篇博客文章提到了它:https://github.com/blog/517-unicorn ... 这个链接也描述了优雅重启功能:http://tomash.wrug.eu/2010/01/30/the-awesomeness-of-unicorn.html - pcting
我想要补充的另一件事与Ken的回答有些相关...我会在所有上游gunicorn服务器上执行滚动重启,这样你的gunicorn服务器就不会因为挂起的请求和加载新的worker而过载。 - pcting

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接