[原创中文翻译]symfony askeet24:第二十二天,上传服务器发布网站。
October 11, 2007 – 1:01 am[欢迎转载,转载请注名出处http://symfony.net.cn。本文英文版权归symfony官方网站所有]
Synchronization
同步
Good practices
推荐的方案
There are a lot of ways to synchronize two environments for a website. The basic file transfers can be achieved by an FTP connection, but there are two major drawbacks to this solution. First, it is not secure, the data stream transmits in the clear over the Internet and can be intercepted. Second, sending the root project directory by FTP is fine for the first transfer, but when you have to upload an update of your application, where only a few files changed, this is not a good and fast way to do it. Either you transfer the whole project again which, can be long or you browse to the directories where you know that some files changed, and transfer only the ones with different modification dates. That’s a long job, and it is prone to error. In addition, the website can be unavailable or buggy during the time of the transfer.
部署两种环境(开发和发布)到服务器上有很多方式。最基本的是FTP传输,但是有两个主要缺点。首先,不安全,网络明文传输而且会被截取。第二,第一次把站点目录用FTP传送上去不错,但是当你需要上传和更新程序,如果仅有几行代码需要改动,做起来就不方便了。再传一次整个站点文件,会很长时间,要么你在站点目录里浏览你需要改的文件,只传送修改的文件。也太费时间,而且有错误风险。另外,如果传输一半断网了呢?
The solution that is supported by symfony is rsync synchronization through a SSH layer.
symfnoy的解决方法是使用通过SSH层的rsync同步法。
Rsync is a command line utility that provides fast incremental file transfer, and it’s open source. By ‘incremental’, it means that only the modified data will be transferred. If a file didn’t change, it won’t be sent to the host. If a file changed only partially, only the differential will be sent. The major advantages is that rsync synchronizations transfer only a little data and are very fast.
Rsync是个命令行工具,提供了快速文件传输功能,而且是开源免费的。由于速度快,那么意味着只有修改的数据会被传送。如果一个文件没有被修改,那么就不会被传送到服务器。如果一个文件只有部分被修改了,那么只有不同的部分会被发送过去。最主要的特点是rsync同步传输只传输了少量数据,所以速度非常快。
Symfony adds SSH on top of rsync to secure the data transfer. More and more commercial hosts support an SSH tunnel to secure file uploads on their servers, and that’s a good practice that symfony encourages.
symfony把SSH加到rsync里保证数据传送安全。越来越多的商业服务器提供商支持SSH传送,这也是symfony推荐的。
For notes on installing rsync and SSH on Linux, read the instructions in the related websites. For Windows users, an open-source alternative called cwRsync exists, or you can try to install the binaries by hand (instructions can be found here). Of course, to be able to setup an SSH tunnel between an integration server and a host server, the SSH service has to be installed and running on both computers.
在Linux下安装rsync和SSH,看看相关网站上的资料。对windows用户,有一个cwRsync,你可以手动安装(方法见这里)。当然,为了在两个主机之间建立SSH通道,两个计算机都要安装运行SSH服务。
The symfony sync command
symfony sync命令
Doing a rsync over SSH requires several commands, and synchronization can occur a lot of times in the life of an application. Fortunately, symfony automates this process with just one command:
使用rsync要用到几个命令,传输文件到服务器在程序周期里占的时间也很大。幸运的是,symfony一个命令就自动实现了:
$ symfony sync production
This command, called from the root directory of a symfony project, launches the synchronization of the project code with the production hosted server. The connection details of this server are to be written in the project properties.ini, found in askeet/config/:
命令在symfony项目root目录里执行,在服务器上进入同步目录。连接信息写在askeet/config/下的properties.ini里:
name=askeet
[production]
host=myaskeetprodserver.com
port=22
user=myuser
dir=/home/myaccount/askeet/
The connection settings will be used by the SSH client call enclosed in the symfony sync command line.
连接设置会在SSH客户端使用。
If you just call symfony sync like mentioned above, the rsync utility will run in dry mode by default (–dry-run), i. e. it will show you which files have to be synchronized but without actually synchronizing them. If you want the synchronization to be done, you have to mention it explicitly:
如果用上面提到的方法调用symfony sync,rsync程序会默认在dry模式下运行(–dry-run),也就是说,会显示哪个文件需要同步,但现在不传输。如果你想让传输进行,那么这样:
$ symfony sync production go
Ignoring irrelevant files
忽略不相关文件
If you synchronize your symfony project with a production host, there are a few files and directories that should not be transferred:
如果你想给服务器传输文件,只有几个文件和目录需要传送:
All the .svn directories and their content: They contain source version control information, only necessary for development and integration
所有的.svn目录和内容:源代码版本控制信息,开发和整合的必须信息
askeet/web/fronted_dev.php: The web front controller for the development environment must not be available to the final users. The debugging and logging tools available when using the application through this front controller slow down the application, and give information about the core variables of your actions. It is something to keep off of the host server.
askeet/web/frontend_dev.php:开发环境下的前台控制不能在最后版本显示。调试工具条会减缓程序运行,暴露程序核心部分。必须在服务器上避免。
The cache/ and log/ directories of a project must not be erased in the host server each time you do a synchronization. These directories must be ignored as well. If you have a stats/ directory, it should probably be treated the same.
项目的cache/和log/目录必须在每次传输文件完毕后从服务器上清除。目录不用删除,里面的文件全部清除即可。如果你有stats/目录,也要这么干。
The files uploaded by users: one of the good practices of symfony projects is to store the uploaded files in the web/uploads/ directory. This allows us to exclude all these files by pointing to only one directory.
用户上传的文件:好的解决方法是把文件储存在web/uploads/目录下。我们设置为不对这个目录操作。
To exclude files from rsync synchronizations, open and edit the rsync_exclude.txt file under the askeet/config/ directory. Each line can contain either a file, a directory, or a pattern:
从rsync传输上设置不操作某些文件,打开编辑rsync_exclude.txt,在askeet/config/下。每一行要么包含一个文件,要么是一个目录,要么是一个格式:
.svn
web/frontend_dev.php
cache
log
stats
web/uploads
Thanks to the symfony file structure, you don’t have too many files or directories to exclude manually from the synchronization. If you want to learn more about the way the files are organized in a symfony project, read the file structure chapter of the symfony book.
因为有symfony固定的目录结构,你不会有太多的文件或目录来设置忽略。如果你想看看更多的信息,看看file structure章节。
The cache/ and log/ directories must not be synchronized with the development server, but they must at least exist in the production server. Create them by hand if the askeet project tree structure doesn’t contain them.
cache/和log/目录不必在开发服务器上存在,但至少在服务器上应该有。如果没有就手动创建。
Production server configuration
发布服务器配置
For your project to work in the production server, the symfony framework has to be installed in the host.
为了你的项目运行在发布服务器上,symfony必须安装在服务器上。
Installing symfony in a production server
在发布服务器上安装symfony
There are several ways to install symfony on a server, but they are not all adapted to a production environment. For instance, doing a PEAR install requires administrator rights on directories that might not be open to you if you share a web server.
在服务器上安装symfony有很多方法,但不一定都适合发布服务器环境。例如,用PEAR安装需要administrator权限,如果你有一个web服务器,不一定你肯定会有那个权限。
Based on the principle that you will probably host several projects using symfony on the production web server, the recommended symfony installation is to uncompress the archive of the framework in a specific directory. Only the lib/ and data/ directories are necessary in a production server, so you can get rid of the other files (bin/, doc/, test/ and the files from the root directory).
你可能需要有很多项目使用symfony,在一台服务器上,推荐的symfony安装模式是解压缩框架档案到一个特殊目录里。只有lib/和data/目录是发布服务器必须的,其他目录都可以不要了(bin/,doc/,test/和其他目录)。
You should end up with a file structure looking like:
最后的文件结构数是这样的:
/home/myaccount/
–symfony/
—-lib/
—-data/
–askeet/
—-apps/
——frontend/
—-batch/
—-cache/
—-config/
—-data/
—-doc/
—-lib/
—-log/
—-test/
—-web/
For the askeet project to use the symfony classes, you have to set up two symbolic links between the application lib/symfony and data/symfony, and the related directories in the symfony installation:
askeet项目使用了symfony类库,需要设置两个symbolic连接在lib/和data/之间,相关目录见symfony安装:
$ cd /home/myaccount/askeet
$ ln -sf /home/myaccount/symfony/lib lib/symfony
$ ln -sf /home/myaccount/symfony/data data/symfony
Alternatively, if you don’t have command line access, the files of the framework can be copied directly into the project lib/ and data/ directories:
非此即彼,如果你无法使用命令行入口,你可以直接拷贝文件到lib/和data/目录:
copy /home/myaccount/symfony/lib/* into /home/myaccount/askeet/lib/symfony
copy /home/myaccount/symfony/data/* into /home/myaccount/askeet/data/symfony
Beware that in this case, each time you update the framework, you have to do it in all your projects.
这里要小心,每次你更新框架,你就要重复一次。
For more information, all the possible ways to install symfony are described in the installation chapter of the symfony book.
更多安装symfony信息见symfony book。
Access to the symfony commands in production
发布服务器上的symfony命令行入口
While developing, you took the good habit of using:
在开发中要养成好习惯清除缓存:
$ symfony clear-cache
…each time you change the configuration or the object model of the project. When you upload a new version of your project in production, the cache also needs to be cleared if you want the application to work. You can easily do it by deleting the full content of the askeet/cache/ directory (by ftp or with a ssh console). Alternatively, you can have the power of the symfony command line at the price of a slightly longer installation.
… …每次你改变项目的配置或改变模型对象。当在发布服务器上更新项目版本后,都需要清除缓存。你可以删除askeet/cache/目录里的内容(通过FTP或SSH)。非此即彼,命令行执行好,但是需要略微花费点安装时间。
To use the command line, you need to install the pake utility. Pake is a PHP tool similar to the make command. It automates some administration tasks according to a specific configuration file called pakefile.php. The symfony command line uses the pake utility, and each time you type symfony, you actually call pake with a special pakefile.php located in the symfony/bin/ directory (find more about pake in symfony in the project creation chapter of the symfony book). If you install symfony via PEAR, pake is installed as a requirement, so you usually don’t see it at all and don’t need to bother about what comes next. But if you do a manual installation, you have to uncompress the pake directory (get it from your symfony pear installation or download it from the pake website) into your directory in the production server. Just like for the symfony libs, you also have to add a symlink in order to enable symfony to use pake:
用命令行,你需要安装pake utility包。pake是一个PHP工具包,类似命令行工具。根据一个叫做pakefile.php的特殊配置文件自动载入。symonfy命令行就用的这个包,每次你输入symfony命令,事实上你是调用了symfony/bin/目录下的pakefile.php(具体见symfony book里的相关章节)。如果你用PEAR安装了symfony,包就是选择安装,所以你通常一点也看不到而且不需要关心下面会有什么。但是如果你手动安装,你需要解压缩包(从symfony pear安装获取或从pake网站下载)到服务器目录下。像symfony类库,你也需要加个symlink来使用symfony的包:
$ ln -sf /home/myaccount/pake/lib lib/pake
You should end up with something like this:
最后剩下的是这样:
/home/myaccount/
–pake/
—-lib/
–symfony/
—-lib/
—-data/
–askeet/
—-apps/
——frontend/
—-batch/
—-cache/
—-config/
—-data/
——symfony/ -> /home/myaccount/symfony/data
—-doc/
—-lib/
——symfony/ -> /home/myaccount/symfony/lib
——pake -> /home/myaccount/pake/data
—-log/
—-test/
—-web/
To call the symfony command to do a clear-cache, you need to do:
使用symfony命令行来清除缓存,你需要做的是:
$ cd /home/myaccount/askeet/
$ php lib/pake/bin/pake.php -f lib/symfony/data/symfony/bin/pakefile.php clear-cache
Alternatively, you can create a file called symfony in the home/myaccount/askeet/ with:
非此即彼,在home/myaccount/askeet/下创建一个文件,叫symfony:
#!/bin/sh
php lib/pake/bin/pake.php -f lib/symfony/data/symfony/bin/pakefile.php $@
Then, all you need to do in order to clear the cache is that good old
然后,就可以这样清除缓存了
$ symfony clear-cache
Web command
web命令行
If you want to have the power of the pake utility but without command line access, you can also create a web access for the clear-cache command.
如果你想更好得不用命令行使用pake utility,可以给清除缓存命令加个web接口。
For instance, you could save the following webpake.php in your /home/myaccount/askeet/web/ directory:
例如,在/home/myaccount/askeet/web/下放一个webpake.php文件:
<?php
// as we are in the web/ dir, we need to go up one level to get to the project root
chdir(dirname(__FILE__).DIRECTORY_SEPARATOR.’..’);
include_once(’/lib/symfony/pake/bin/pake.php’);
$pake = pakeApp::get_instance();
try
{
$ret = $pake->run(’/data/symfony/bin/pakefile.php’, ‘clear-cache’);
}
catch (pakeException $e)
{
print “<strong>ERROR</strong>: “.$e->getMessage();
}
?>
Then, clearing the cache could be done by navigating to:
那么,清除缓存可以这么实现:
http://myaskeetprodserver.com/webpake.php
Beware that by letting web access to administration tools, you can compromise the security of your website.
小心使用administrator工具,你需要小心处理网站安全问题。
Upgrading your application
升级你的程序
There will be times in the life of your project when you need to switch between two versions of an application. It can be in order to correct bugs, or to upload new features. You can also be faced with the problem of switching between two versions of the database. If you follow a few good practices, these actions will prove easy and harmless.
当你需要在两个版本之间转换时,程序升级会在你的项目周期里占用一段时间。为了修正bug,增加新功能。你需要面对版本升级后数据库带来的问题。如果你用了好的办法,action会很简单而且无恙。
Show unavailability notice
网站暂停公告页面
Between the moment when you start the data transfer and the moment you clear the cache (if you modify the configuration or the data model), there are sometimes more than a few seconds of delay. You must plan to display an unavailability notice for users trying to browse the site at that very moment.
在你开始数据传输和清除缓存(如果你修改了配置或是model),有时会有几秒的延迟。你必须准备准备一个通知页来让用户知道这个时候网站在非常时期不能访问。
In the application settings.yml, define the unavailable_module and unavailable_action settings:
在settings.yml里,定义unavailable_module和unavailable_action配置:
all:
.settings:
unavailable_module: content
unavailable_action: unavailable
Create an empty content/unavailable action and a unavailableSuccess.php template:
创建一个空的content/unavailable动作和一个unavailableSuccess.php模板:
// askeet/apps/frontend/modules/content/actions/actions.class.php
public function executeUnavailable()
{
$this->setTitle('askeet! » maintenance');
}
// askeet/apps/frontend/modules/content/templates/unavailableSuccess.php
<h1>Askeet: Site maintenance</h1>
<p>The askeet website is currently being updated.</p>
<p>Please try again in a few minutes.</p>
<p><i>The askeet team</i></p>
Now each time that you want to make your application unavailable, just change the available setting:
现在每次你想让程序不能访问时,只需要修改设置即可:
all:
.settings:
available: off
Don’t forget that for a configuration change to be taken into account in production, you need to clear the cache.
记得配置修改放到发布服务器上后,清除缓存。
The fact that the whole application can be turned off with only a single parameter is possible because symfony applications use a single entry point, the front web controller. You will find more information about it in the controller page of the symfony book.
整个程序的关闭都可以靠一个参数控制即可,是因为symfony程序用了简单是登入点,前台web控制。symfony book里有更多介绍。
Use two versions of your application
给你的程序使用两个版本
A good way to avoid unavailability is to have the project root folder configured as a symlink. For instance, imagine that you are currently using the version 123 of your application, and that you want to switch to the version 134. If your web server root is set to /home/myaccount/askeet/web/ and that the production folder looks like that:
解决避免不能正常访问的方法是配置项目root目录为一个symlink。例如,想象一下你现在在用123版本程序,现在你想把版本换成134。如果你的web服务器目录被设置在/home/myaccount/askeet/web/下,那么服务器文件看起来像:
/home/myaccount/
–pake/
—-lib/
–symfony/
—-lib/
—-data/
–askeet/ -> /home/production/askeet.123/
–askeet.123/
–askeet.134/
Then you can instantly switch between the two versions by changing the symlink:
然后你可以靠改变symlink立即实现转换版本:
$ ln -sf /home/myaccount/askeet/ /home/myaccount/askeet.134/
The users will see no interruption, and yet all the files used after the change of the symlink will be the ones of the new release. If, in addition, you emptied the cache/ folder of your release 134, you don’t even need to launch a clear-cache after switching applications.
网站访问者看不到中断,然而所有的文件在改变symlink后被当作新版本发布。另外,你使用清空缓存版本134的cache/文件夹,你甚至不需要载入清除缓存操作。
Switching databases
换数据库
You can extrapolate that technique to switching databases. Remember that the address of the database used by your application is defined in the databases.yml configuration file. If you create a copy of the database with a new name, say askeet.134, you just need to write in the askeet.134/apps/frontend/config/databases.yml:
你可以使用这个技术来换数据库。记得数据库地址定义在databases.yml配置文件。如果你有一个数据库拷贝,用了个新名字,叫askeet.134,你需要在askeet.134/apps/frontend/config/databases.yml写上:
all:
propel:
class: sfPropelDatabase
param:
phptype: mysql
hostspec: localhost
database: askeet.134
username: myuser
password: mypassword
compat_assoc_lower: true
compat_rtrim_string: true
As the databases.yml will be switched as the same time as the application itself, your askeet will instantly start querying the new database.
databases.yml的转换速度和程序那边是一样的,你的askeet会立即使用新数据库。
This technique is especially useful if your application has a big traffic and if you can’t afford any service interruption.
如果你的网站有很大访问量,如果你的用户无法接受服务器中断,那么这个技术很实用的。