在大型的網站架構中,通常會使用上多部網頁伺服器來組成server farm,並在前面架設負載平衡交換器,以便隨時因應訪客量及伺服器負載而增減伺服器,達到高可用性的架構。
在只有一部網頁伺服器(假設包含應用伺服器,例如Apache+Tomcat)時,我們的網頁應用程式只要上傳一次到網頁伺服器指定目錄下即可,如果變成兩部時,那就得傳兩次,加到三部時,就傳三次,照這樣的邏輯推論下去,當主機成長到N部時,我們就得傳N次,N>=1。
不知道大家對上傳網頁程式這件事的看法為何,尤其在上線後,還要修修改改時,如有哪部主機忘了傳,就會造成網頁資料不同步,其實是滿繁瑣的一件事。
如果可以上傳一次到主要的伺服器,然後由這部主機自動再傳到其他主機器去,則管他N等於多少,我們都只需要手動上傳一次。而且如果有刪除檔案還會自動擴散到其他主機,省去到各部主機找檔案並刪除的時間。這麼棒的東西,難道只能是作夢嗎?不,科技始終來自於人性,想偷懶,其實還是推動進步的原動力之一啊。老早就有人做出來了,而且還是免費的,我們只要學會怎麼用就可以了。
這裡我們推薦一個工具--
rsync,可透過ssh將有差異部分的檔案備份到遠端主機去的方式,只要再設定crontab定時自動執行一個shell script,即可達到網站間安全同步的功能。
首先讓主要伺服器可以不需要輸入密碼透過ssh登入到備份伺服器:
1.在主要伺服器產生public/private dsa key pair檔案
[root@www ~]# cd /root/.ssh
[root@www .ssh]# ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/root/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_dsa.
Your public key has been saved in /root/.ssh/id_dsa.pub.
The key fingerprint is:
8f:f7:45:87:a0:11:a2:a7:ec:88:45:e8:33:21:35:3f root@www.andowson.com
產生兩個檔案:id_dsa和id_dsa.pub
[root@www .ssh]# ls -la
總計 24
drwx------ 2 root root 4096 11月 10 11:39 .
drwxr-x--- 7 root root 4096 10月 20 14:13 ..
-rw------- 1 root root 668 11月 10 11:39 id_dsa
-rw-r--r-- 1 root root 611 11月 10 11:39 id_dsa.pub
-rw-r--r-- 1 root root 2794 10月 9 22:41 known_hosts
2.將id_dsa.pub傳到備份伺服器的/root/.ssh目錄下,且更名為authorized_keys2
[root@www .ssh]# scp id_dsa.pub 192.168.1.4:/root/.ssh/authorized_keys2
The authenticity of host '192.168.1.4 (192.168.1.4)' can't be established.
RSA key fingerprint is e2:61:f0:78:31:21:72:ce:06:dd:da:02:f1:41:05:ec.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.4' (RSA) to the list of known hosts.
root@192.168.1.4's password:
id_dsa.pub 100% 611 0.6KB/s 00:00
3.測試是否可以不用輸入密碼登入備份伺服器
[root@www .ssh]# ssh 192.168.1.4
Last login: Sat Nov 10 11:37:58 2007 from 192.168.1.2
接下來就是將主要伺服器的檔案備份過去即可,
4.編輯一個shell script /root/admin/autosync.sh來做這件事:
#! /bin/bash
hosts="192.168.1.4"
for siteuser in `cat /root/admin/sites.txt`
do
if [ -d /home/${siteuser} ]
then
for host in $hosts
do
echo "sending $siteuser files to $host ..."
rsync -avlR --delete -e ssh /home/${siteuser}/ ${host}:/
done
fi
done
echo "done"

注意到接收端的目錄要設為/,否則會在備份伺服器上多開一層home目錄。
如果有兩部以上備份主機則用空白隔開,例如hosts="192.168.1.4 192.168.1.5"
另外我採用另外編輯一個檔案/root/admin/sites.txt來控制要備份的目錄,如果全部都要備份可以用
ls /home即可。
/root/admin/sites.txt內容如下:
andowson
30elite
ezmatch
我們可以將上面的檔案存檔為/root/admin/autosync.sh,並設定為可執行
chmod 755 /root/admin/autosync.sh
參數意義如下﹕
-a, --archive
It is a quick way of saying you want recursion and want to preserve almost everything.
-v, --verbose
This option increases the amount of information you are given during the transfer.
-l, --links
When symlinks are encountered, recreate the symlink on the destination.
-R, --relative
Use relative paths. 保留相對路徑...才不會讓子目錄跟 parent 擠在同一層...
--delete
是指如果Server端刪除了一文件,那客戶端也相應把這一文件刪除,保持真正的一致。
-e ssh
建立起加密的連接。
參數的使用因人而異...您可以man rsync來使用更多的參數...
5.測試autosync.sh
/root/admin/autosync.sh
第一次會把全部的檔案都加入複製清單,如果到備份伺服器上有看到檔案被複製過來,就差不多了,可以順便測試看看在主要伺服器上刪除一些檔案,然後再執行一次,看會不會同步刪除,就大致測試完成了。
最後,將autosync.sh加到crontab去,可設定每兩分鐘同步一次
6. 編輯 /etc/crontab
*/2 * * * * /root/admin/autosync.sh
大功告成,以後便只需要上傳一次到主要伺服器,後續就由主要伺服器去同步複製到備份伺服器了。
問題討論:
1.如果有開放讓使用者上傳檔案,例如個人頭像(avatar)或是附件(attachment),則上傳到哪部主機是由負載平衡交換器動態決定,這部分要如何處理,才能讓使用者不管連到哪部伺服器都看得到檔案?
2.如果讓系統管理者新增最新消息或系統公告之類的東西,由於內容每次看都一樣,可於儲存內容到資料庫後,由系統自動寫成靜態網頁(省去每次都要連接資料庫撈取資料再轉成網頁的處理時間),這時寫到哪部主機也是不一定的,應該如何處理,才能讓使用者不管連到哪部伺服器都看得到檔案?(同樣也可適用於由系統跑出來的統計報表)
參考資料:
http://www.adj.idv.tw/server/linux_rsync.php