网站静态内容出版解决方案
目录
- 1. 架构总览
- 2. cdn
- 3. www 服务器
- 4. cms 服务器
- 5. img
- 6. Ajax 局部更新与缓存
1. 架构总览
www 负责静态文件浏览, 台数不定, 可以采用零成本的DNS轮询, 或者4层LVS, 或者7层HAProxy, 还可以用F5, Array 等负载均衡设备.
cms 负责静态文件生成. 生成后的文件要同步到www中, 或者采用网络共享, 再者使用分布式文件系统, 总之将生成的文件交给www服务器, 根据你压力横向扩展即可
img 负责图片文件浏览. 通过给图片加版本号, 结局图片更新问题, 这样更新网站不用频繁刷新 CDN
这里不谈论负载均衡, 以及存储方案, 有情绪可以延伸阅读: http://netkiller.github.com/architect/index.html
你掌握了这个方案, 你可以很容易实现 向"京东商城", "VANCL凡客诚品", "走秀网" 这样的网站
这些网站的特点是: 浏览量大, 数据存储主要是图片, 登录/注册与购物车,用户中心 访问量只占到 5% 使用负责均衡很容易解决.
静态化网站可不避免的使用ajax做局部更新, ajax请求也要考虑缓存问题
首次访问服务器
- 访问www服务器
- nginx 判断文件是否存在,如果存在将文件显示出来
- 如果文件不存在,去cms服务器上查找, 如果存在便返回给www服务器,并显示出来
- 如果cms上文件不存在,cms服务器便使用rewrite生成该文件, 同时将内容返回给www服务器,www将内容缓存在自己的服务器上,并将内容显示出来
第二次访问
- 访问www服务器
- nginx 判断文件是否存在,如果存在将文件显示出来
- 如果文件不存在,去cms服务器上查找, 如果存在便返回给www服务器,并显示出来
- 如果cms上文件不存在,cms服务器便使用rewrite生成该文件, 同时将内容返回给www服务器,www将内容缓存在自己的服务器上,并将内容显示出来
2. cdn
如何使用 cdn 来缓存你的网站内容
让你的网页缓存在 cdn 节点上的方式有下面几种
- 让cdn的客服帮你配置缓存的规则, 他们很喜欢一刀切, 例如所有html都缓存2小时
- 在他们管理后台自行使用正则配置缓存的时间, 这个他们一般不会提供, 某些公司的CDN会提供这个功能. 非常方便.
- 通过HTTP头自行控制缓存时间, 一般是使用 max-age / s-maxage / Last-Modified 判断缓存时间
我比较喜欢最后一种, 通常我们使用max-age 与 s-maxage 同时使用, 这样我可以按照我的意向来决定文件的缓存时.
3. www 服务器
下面给出一个精简后的配置例子
如果文件不存在就会连接后端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;
#}
}
4. cms 服务器
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;
}
}
5. img
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页面即可, 不用去理睬图片, 你的浏览器会用新的地址下载图片. 这样就解决了烦琐的刷新工作.
6. Ajax 局部更新与缓存
例如我的新闻评论页面,需要使用ajax技术, 将用户回复的品论显示来, ajax 载入json数据然后局部更新, 我对他做了1分钟的缓存
if ($request_uri ~* ".(xml|json)$") {
expires 1m;
}
如果有新的提交我们可以为json增加版本是控制例如: http://api.mydomain.com/news.json?1.0