Django无缝升级与CDN
[我在使用AWS,但我觉得这个问题对所有CDN都适用]
我想把我的Django服务器顺利地部署到AWS云上。
所有的静态内容(比如图片、JavaScript等)都放到亚马逊的Cloudfront CDN上。
问题是,我想让升级过程尽可能“原子化”,但我对CDN对象失效的时机几乎没有控制权。
根据官方文档,解决办法是给我的对象加上版本号,也就是说,重命名它们,像这样:arrow_v123.png。显然,如果新服务器指向arrow_v124.png,我就能完全控制整个分发的时机。
我查了一下,发现大公司都是这么做的——比如Facebook的静态内容对象都有一个哈希命名(和路径)。
但是我怎么才能在Django中自动做到这一点呢?
我需要以某种方式:
- 生成一个新的版本号
- 更改所有静态对象的名称
- 修改所有模板和Python代码,以使用这些新名称
或者以某种方式与开发过程集成:
- 我编辑了一张图片或一个JavaScript文件
- 我保存它,它就会获得一个新名称?!而且所有引用它的地方都会自动更正?!
我在使用Fabric进行部署,所以我需要以某种方式修改我的fabfile。
请帮帮我。
Tal.
4 个回答
我觉得最后一部分(把所有模板和Python代码都改成新名字)其实挺简单的。你只需要在设置里存一个当前样式的“版本号”。确保这个版本号在使用模板的时候能传递到模板上下文中。然后,在渲染模板的时候用这个版本号来选择静态文件的真实网址。
发布一组新的静态文件的步骤是:
- 把新文件发布到你的CDN上
- 编辑你的设置文件
- 重新加载你的应用设置
你也可以通过把版本号存到数据库里,而不是设置文件,来实现类似的效果。这样就不需要重新加载,改动会立刻生效,但每次渲染视图时会增加一次数据库查询。
如何将这些步骤整合到你的开发流程中,完全取决于你自己。你可以考虑自动化一些步骤,比如条件性地发布到CDN、编辑设置文件和重启应用。为了方便“编辑”设置文件,你可以把版本号存到一个单独的文件里,然后在启动时让设置文件读取这个文件。
看看html5boilerplate,它有一些ant构建脚本,这些脚本除了做很多其他事情外,还会把你的静态js和CSS文件的引用名称改成随机数字,并且会在你的模板文件中把这些新的随机数字的js和CSS引用也改掉。我觉得它对图片资源没有做同样的处理,不过我想ant文件可以修改来实现同样的效果。
html5boilerplate的Django版本在这里: https://bitbucket.org/samkuehn/django-html5-boilerplate
http://www.allbuttonspressed.com/projects/django-mediagenerator 提供了资源版本管理的功能。它有一个函数和一个模板标签,可以让你从实际的文件名中获取带版本号的文件名。此外,它还提供了一些很不错的附加功能,比如将 JavaScript 和 CSS 文件进行压缩和合并。