知乎專欄 | 多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者” |
www 負責靜態檔案瀏覽, 台數不定, 可以採用零成本的DNS輪詢, 或者4層LVS, 或者7層HAProxy, 還可以用F5, Array 等負載均衡設備.
cms 負責靜態檔案生成. 生成後的檔案要同步到www中, 或者採用網絡共享, 再者使用分散式檔案系統, 總之將生成的檔案交給www伺服器, 根據你壓力橫向擴展即可
img 負責圖片檔案瀏覽. 通過給圖片加版本號, 結局圖片更新問題, 這樣更新網站不用頻繁刷新 CDN
這裡不談論負載均衡, 以及存儲方案, 有情緒可以延伸閲讀: http://netkiller.github.com/architect/index.html
你掌握了這個方案, 你可以很容易實現 向"京東商城", "VANCL凡客誠品", "走秀網" 這樣的網站
這些網站的特點是: 瀏覽量大, 數據存儲主要是圖片, 登錄/註冊與購物車,用戶中心 訪問量只占到 5% 使用負責均衡很容易解決.
靜態化網站可不避免的使用ajax做局部更新, ajax請求也要考慮緩存問題
靜態化另一個目的是改善SEO
首次訪問伺服器
訪問www伺服器
nginx 判斷檔案是否存在,如果存在將檔案顯示出來
如果檔案不存在,去cms伺服器上查找, 如果存在便返回給www伺服器,並顯示出來
如果cms上檔案不存在,cms伺服器便使用rewrite生成該檔案, 同時將內容返回給www伺服器,www將內容緩存在自己的伺服器上,並將內容顯示出來
第二次訪問
訪問www伺服器
nginx 判斷檔案是否存在,如果存在將檔案顯示出來
如果檔案不存在,去cms伺服器上查找, 如果存在便返回給www伺服器,並顯示出來
如果cms上檔案不存在,cms伺服器便使用rewrite生成該檔案, 同時將內容返回給www伺服器,www將內容緩存在自己的伺服器上,並將內容顯示出來
靜態化方法包括:
生成方式
抓取方式
偽靜態化
混合方式
主要由程序實現
例如
content = "<html><title>my static</title><body>hello world</body></html>" file = open( your static file) file.write(content) file.close()
主要由程序實現
程序中抓取
content = get_url('http://netkiller.8800.org/index.php') file = open( index.html) file.write(content) file.close()
使用軟件抓取,不僅限于wget。
wget http://netkiller.8800.org/index.php -O index.html
這時只給出簡單例子,使用複雜參數實現更複雜的拾取,然後將腳本加入crontab中可。
偽靜態化是主要是通過在URL上做一些手腳,使你看去是靜態的,實質上它是動態腳本。
偽靜態化實現主要包括兩種方法:
Rewrite rule
path_info
下面是一個PATH_INFO例子
http://netkiller.8800.org/zh-cn/photography/browse/2009.html
根本就不存在這個目錄'zh-cn/photography/browse/'和檔案'2009.html'
下面是一個Rewrite例子
http://example.org/bbs/thread-1003872-1-1.html
其實目前網站使用的基本上都是上面幾種方法混合方式。
例如首先將動態url(example.org/news.php?cid=1&id=1) 通過rewrite轉換為 (example.org/new_1_1.html)
接下來就比較容易解決了,一種方法是使用wget example.org/new_1_1.html,另一種方法你無需靜態化,直接使用squid規則配置讓他永不過期
如何使用 cdn 來緩存你的網站內容
讓你的網頁緩存在 cdn 節點上的方式有下面幾種
讓cdn的客服幫你配置緩存的規則, 他們很喜歡一刀切, 例如所有html都緩存2小時
在他們管理後台自行使用正則配置緩存的時間, 這個他們一般不會提供, 某些公司的CDN會提供這個功能. 非常方便.
通過HTTP頭自行控制緩存時間, 一般是使用 max-age / s-maxage / Last-Modified 判斷緩存時間
我比較喜歡最後一種, 通常我們使用max-age 與 s-maxage 同時使用, 這樣我可以按照我的意向來決定檔案的緩存時間 這裡有更詳細的解釋說明.
下面給出一個精簡後的配置例子
如果檔案不存在就會連接後端cms伺服器生成檔案,並且顯示出來,同時加上緩存. 生成的檔案會從cms中同步到www伺服器上.
你可以採用
rsync同步方案
nfs/samba/gluster 共享方案
iscsi 共享存儲方案
分散式檔案系統方案
參考閲讀: 分散式檔案系統 , Netkiller Linux Storage 手札
upstream cms.mydomain.com { server 192.168.2.11 weight=5 max_fails=3 fail_timeout=30s; server 192.168.2.21 weight=5 max_fails=3 fail_timeout=30s; server 192.168.2.23 backup; server 192.168.2.23 down; } server { listen 80; server_name www.mydomain.com; charset utf-8; access_log /var/log/nginx/www.mydomain.com.access.log main; location / { root /www/mydomain.com/www.mydomain.com; index index.html index.htm; if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png|html)$") { expires 1d; } if ($request_uri ~* "\.(xml|json)$") { expires 1m; } valid_referers none blocked *.mydomain.com; if ($invalid_referer) { #rewrite ^(.*)$ http://www.mydomain.com/cn/$1; return 403; } proxy_intercept_errors on; if (!-f $request_filename) { proxy_pass http://cms.mydomain.com; break; } } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
CMS 內容管理系統的主要功能
內容分類管理
內容模板管理
內容編輯與發佈
內容生成
服務應該實現
當發現目錄中檔案不存, 通過rewrite生成html, 這樣可能根據需要生成html頁面
當頁面更新的時候,應該通過api 刷新cdn的緩存, 圖片的版本好應該加一
將頁面分成多個模組, 通過SSI拼裝頁面, 避免有重大改版時, 整站生成HTML.
避免使用seesion技術, 這樣在負載均衡的時候可以使用最小連接數算法
例如:
rewrite ^/product/(phone|notebook)/(\d+).html /product/$1.php?id=$2 last;
URL 唯一, url設計要考慮唯一性, 不要出現同一個url處理兩個任務, 例如下面的例子, 每個用戶的profile一個URL, 當被訪問的時候便可以緩存在CDN或者用戶瀏覽器上.
http://www.mydomain.com/profile/neo.html http://www.mydomain.com/profile/jam.html
server { listen 80; server_name www.mydomain.com; #charset koi8-r; access_log /var/log/nginx/www.mydomain.com.access.log main; location / { root /www/mydomain.com/www.mydomain.com; index index.html; } } server { listen 80; server_name cms.mydomain.com; charset utf-8; access_log /var/log/nginx/cms.mydomain.com.access.log main; location / { root /www/mydomain.com/cms.mydomain.com; index index.html index.php; } location ~ ^/(cn|tw)/(comment|affiche)/.*\.html { root /www/mydomain.com/www.mydomain.com; if (!-f $request_filename) { rewrite ^/(cn|tw)/(comment|affiche)/(\d+).html /publish/$2.php?id=$3&lang=$1 last; } } location /xml/ { root /www/mydomain.com/www.mydomain.com/xml; } location ~ ^/(config|include|crontab)/ { deny all; break; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { root /www/mydomain.com/cms.mydomain.com; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /www/mydomain.com/cms.mydomain.com$fastcgi_script_name; include fastcgi_params; fastcgi_param DOCUMENT_ROOT /www/mydomain.com/cms.mydomain.com; fastcgi_param HOSTNAME cms.mydomain.com; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # location ~ /\.ht { deny all; } }
img.mydomain.com
server { listen 80; server_name img.mydomain.com; charset utf-8; access_log /var/log/nginx/img.mydomain.com.access.log main; location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico)$ { expires 7d; } location ~ .*\.(js|css)$ { expires 1d; } location ~ .*\.(html|htm)$ { expires 15m; } location / { root /img/mydomain.com/img.mydomain.com; index index.html; rewrite "/theme/([0-9] {4})([0-9] {2})([0-9] {2})/(.+)\.(.+)\.(.+)" /theme/$1/$2/$3/$4.$6; rewrite "/news/([0-9] {4})([0-9] {2})([0-9] {2})/(.+)\.(.+)\.(.+)" /news/$1/$2/$3/$4.$6; rewrite "/product/([0-9] {4})([0-9] {2})([0-9] {2})/(.+)\.(.+)\.(.+)" /product/$1/$2/$3/$4.$6; } }
/theme/2012/08/15/images.1.jpg 實際上就是 /theme/2012/08/15/images.jpg 檔案
/theme/2012/08/15/images.2.jpg 也是 /theme/2012/08/15/images.jpg
/theme/2012/08/15/images.3.jpg 也是 /theme/2012/08/15/images.jpg
但CDN與你的瀏覽器會每次下載新的檔案, 這樣只要更新CDN中的html頁面即可, 不用去理睬圖片, 你的瀏覽器會用新的地址下載圖片. 這樣就解決了煩瑣的刷新工作.