Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | Github | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

1.9. 多维度架构之网站HTML

	
                                       .---> media [mp3, wma, wmv, rmvb, asf, divx]-\
                                      /                                       +------------+
                                     .-----> photo [gif, jpg, png, swf] ----> | Raid Array | <--.
    /------------------- <---------\/                                         +------------+     \
user -> dns -> load balancing -> squid -> [cache] <----[html]----\                  /            |
                 \ \ \______<______/\                      +-------------+         /             |
                  \ \                \-----> web app ----> | html        |--------^              |
                   \ \____________________________/\       | php,jsp,cgi |                       |
                    \                               \      +-------------+                       |
                     \                               `-----> memcached [node1, node2, node(n)]   |
                      \__________________________________________/\                              |
                                                                   `------> Database cluster     |
    +--------------------------------------+                                      \              |
    | Author: neo chen <openunix#163.com>  |                                       `-------------+
    | Nickname: netkiller                  |
    | Homepage: http://netkiller.github.io |
    +--------------------------------------+
	
	

1.9.1. 网站的历史演变

1.9.1.1. 常用软硬件组成

一个网站由下面几部分组成:

网站组成

  1. 硬件 hardware

  2. 操作系统 operation system

  3. 应用软件 application software

  4. 网站程序以及开发语言 web program and script

硬件包括

  1. 网络硬件(路由器 route, 交换机 switch)

  2. 服务器 server

  3. KVM over IP

  4. 其他包括,机柜等

操作系统包括

  1. Windows Server

  2. Linux

  3. FreeBSD

  4. Other(Sun,Novell,Sco...)

其中应用软件按平台分类

Windows 应用软件包括

  1. dns (dns)

  2. web (IIS)

  3. ftp (IIS)

  4. mail (Exchange)

  5. database (SQL Server)

  6. ldap (Active Directory)

Unix like 应用软件包括

  1. dns (bind)

  2. web (apache, lighttpd, tomcat)

  3. ftp (proftpd, pureftpd, wu-ftp, vsftpd)

  4. mail (sendmail,postfix, qmail)

  5. database (PostgreSQL, MySQL)

  6. ldap (OpenLDAP)

其他应用软件包括

  1. cache (squid, nginx, memcached...)

  2. web (jboss, weblogic...)

  3. database (Oracle, DB2...)

网站程序以及开发语言

  1. php

  2. java (jsp)

  3. .net (aspx)

  4. fastcgi (python,perl,rubby,c/c++ ...)

怎样定义多大的网站叫大型网站呢?我也不知道,但凡大型网站都具备本文所提的几点。

门户网站的需求

  1. 海量用户访问

  2. 海量用户存储

  3. 国内外互通及南北互通

  4. 快速响应

  5. 7×24不间断运行

  6. 易于维护

门户网站的几个技术要点

  1. 智能域名服务器 Smart DNS

  2. 集群负载均衡 Cluster

  3. 缓存技术 Cache

  4. 静态化

  5. 图片服务器分离

  6. 压缩数据传输

  7. 时间同步

  8. 数据存储

1.9.1.2. 第一代纯静态网站

ftp/rsync 同步

1.9.1.3. 第二代纯文本文件采用分隔符做数据存储网站

这是出现了cgi/isapi/nsapi技术,perl 成为主流

1.9.1.4. 第三代数据库存储网站

出现动态脚本语言如php,asp,coldfusion,这个时期 php成为主流

出现所见即所得网页工具

256色gif 动画

1.9.1.5. 第四代DNS负载均衡加反向代理

开发语言则百花齐放php,asp.net,java,三大主流三足鼎立。perl慢慢没落。

flash 动画

1.9.1.6. 第五代负载均衡集群

ajax, css+div, xhtml

1.9.2. 集群(Cluster)

集群有很多实现方法,分为硬件和软件,集群可以在不同网络层面上实现

  1. 实现IP轮循(Bind DNS)

  2. 硬件四层交换(硬件负载均衡设备 F5 BIG IP)

  3. 软件四层交换(linux virtual server)

  4. 应用层上实现(tomcat)

越是低层性能越好,越是上层功能更强

集群的分类

  1. 高可用性集群

  2. 负载均衡集群

  3. 超级计算集群

网站一般用到两种集群分别是高可用性集群和负载均衡集群

1.9.2.1. 负载均衡

1.9.2.1.1. DNS负载均衡

这是早期出现的负载均衡技术,直到现在,很多网站仍然使用DNS负载均衡。

你可通过ping命令观看它是如何工作的,例如你可反复ping个网域名。

			
C:\>ping www.163.com

Pinging www.cache.split.netease.com [220.181.28.52] with 32 bytes of data:

Reply from 220.181.28.52: bytes=32 time=226ms TTL=53
Reply from 220.181.28.52: bytes=32 time=225ms TTL=53
Reply from 220.181.28.52: bytes=32 time=226ms TTL=53
Reply from 220.181.28.52: bytes=32 time=226ms TTL=53

Ping statistics for 220.181.28.52:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 225ms, Maximum = 226ms, Average = 225ms

C:\>ping www.163.com

Pinging www.cache.split.netease.com [220.181.28.53] with 32 bytes of data:

Reply from 220.181.28.53: bytes=32 time=52ms TTL=52
Reply from 220.181.28.53: bytes=32 time=53ms TTL=52
Reply from 220.181.28.53: bytes=32 time=52ms TTL=52
Reply from 220.181.28.53: bytes=32 time=52ms TTL=52

Ping statistics for 220.181.28.53:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 52ms, Maximum = 53ms, Average = 52ms

C:\>ping www.163.com

Pinging www.cache.split.netease.com [220.181.28.50] with 32 bytes of data:

Reply from 220.181.28.50: bytes=32 time=51ms TTL=53
Reply from 220.181.28.50: bytes=32 time=52ms TTL=53
Reply from 220.181.28.50: bytes=32 time=52ms TTL=53
Reply from 220.181.28.50: bytes=32 time=51ms TTL=53

Ping statistics for 220.181.28.50:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 51ms, Maximum = 52ms, Average = 51ms

C:\>
			
				

DNS负载均衡主要优点

  1. 技术简单,容易实现,灵活,方便,成本低

  2. Web服务器可以位于互联网的任意位置上,无地理限制。

  3. DNS的主从结构非常稳定

  4. 可以有效的分散DDOS攻击。

  5. 你甚至可以在DNS服务商那里实现,自己不需要添加设备。而且没有带宽开销。

DNS负载均衡主要缺点

  1. DNS负载均衡采用的是简单的轮循负载算法,不能够按照服务器节点的处理能力分配负载。

  2. 不支持故障转移(failover)和自动恢复failback ,如果某台服务器拓机,DNS仍会将用户解析到这台故障服务器上,导致不能响应客户端。

  3. 如果添加节点或撤出节点,不能即时更新到省市级DNS,可导致部分地区不能访问。

  4. 占用大量静态IP。

1.9.2.1.2. 软件四层交换负载均衡

软件四层交换负载均衡为我们解决了几个问题

  1. 能够按照服务器节点的处理能力分配负载。

  2. 支持故障转移(failover)和自动恢复failback ,如果某节点拓机,调度器自动将它剔除,不响应客户端访问,当节点故障排除调度器立即恢复节点。

  3. 可以随时添加节点或撤出节点,即时生效,方便网站扩容。

软件四层交换负载均衡优点

  1. 仅仅需要一个静态IP。

  2. 节点位于私有网络上与WAN隔离,用户面对的只是调度器。

  3. 可以随时添加节点或撤出节点。

  4. 通过端口可以组建多个集群。

1.9.2.1.3. 应用层负载均衡

Tomcat balancer

mod_proxy_balancer.so ,tomcat mod_jk.so

MySQL proxy / MySQL-LB

1.9.2.2. 高可用性集群

俗称:双机热备份

关键词:心跳线

两部服务器,或多部服务器,形成一个集群,当主服务器崩溃是,立即切换到其它节点上。

两部服务器要做到,内容实时同步,保持数据一直。

一般用 heartbeat + DRBD 实现。heartbeat负责切换服务器,DRBD用于同步数据。

1.9.2.3. 负载均衡设备

负载均衡成熟产品

  1. F5 Big IP

  2. Array

这些设备可提供3,4,7层负载均衡HA,硬件已经压缩,HTTP头改写,URL改写...

其中3层交换部分多采用硬件实现。

更多关于F5 与 Array 资料点击进入

1.9.2.4. 会话保持

1.9.2.5. 健康状态检查

1.9.3. 缓存技术

首先要说明,很多缓存技术依赖静态化。下面展示了缓存可能出现的位置。

用户user -> 浏览器缓存 IE/Firefox Cache -> 逆向代理缓存 Reverse proxy Cache -> WEB服务器缓存 Apache cache -> 应用程序缓存 php cache -> 数据库缓存 database cache

当然交换机,网络适配器,硬盘上也有Cache 但这不是我们要讨论的范围。

缓存存储方式主要是内存和文件两种,后者是存于硬盘中。

网站上使用的缓存主要包括五种:

  1. 浏览器 缓存

  2. 逆向代理/CDN缓存

  3. WEB服务器缓存

  4. 应用程序缓存

  5. 数据库缓存

将上面的缓存合理地,有选择性的使用可大大提高网站的访问能力。

总之,想让你的网站更快,更多并发,答案是cache,cache 再 cache

1.9.3.1. 浏览器缓存

1.9.3.1.1. Cache-Control

通过 Cache-Control 设置页面缓存时间

max-age
max-age 格式写为:max-age=n,n是以秒为单位, 这个值是告知客户端GMT + N 后页面过期,缓存服务器在s-maxage值为空的时候也会使用这个参数的值。

s-maxage
s-maxage的格式跟max-age一样,只不过他是给缓存服务器使用的。

must-revalidate
这个参数用来告知客户端和缓存服务器,在GET请求的时候必须与源服务器验证实体是否为最新版本。

Cache-Control:max-age=1200,s-maxage=3600
			
Last-Modified
这个参数提供了实体最近一次被修改的时间。这个名字起得不错,当实体被修改了之后,这个参数也就会被修改.
			

ETag

ETag
ETag是根据内容生成的一段hash字符串,采用信息摘要算法,保证每一个页面有一个唯一字串。
			

expires

expires 是HTTP 1.0 中定义的,已经不能满足用户的需要在 HTTP 1.1 加入了max-age,建议使用 max-age替代expires

指令					含义
public				可以在任何地方缓存
private				只能被浏览器缓存
no-cache			不能在任何地方缓存
must-revalidate		缓存必须检查更新版本
proxy-revalidate	代理缓存必须检查更新版本
max-age				内容能够被缓存的时期,以秒表示
s-maxage			覆盖共享缓存的max-age设置
			

在Squid, Varnish, Apache, Lighttpd, Nginx 中都可是实现HTTP Cache-Control推送,每次修改都需要重新加载,不太灵活。

ExpiresActive On
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"


server.modules = (
...
"mod_expire",
...
)

$HTTP["url"] =~ "^/images/" {
expire.url = ( "" => "access 30 days" )
}
			

我喜欢自己控制TTL时间,且每个页面单独设置,可以随时调整设置。

1.9.3.1.1.1. 在程序中灵活操作 Cache-Control

在MVC框架中每个控制器下的方法都可以单独操作Cache

Class blog extend Controller{
	blog(){
		header('Cache-Control: max-age=28800');
	}
	list(){
		header('Cache-Control: max-age=3600');
	}
	details(){
		header('Cache-Control: max-age=160');
	}
}
				

你还可以封装到Controller中

Class blog extend Controller{
	blog(){
		this->cache('28800');
	}
	list(){
		this->cache('3600');
	}
	details(){
		this->cache('160');
	}
}
				
1.9.3.1.1.2. 非程序文件缓存处理

首先做一个Rewrite让程序接管所有图片请求

url.rewrite = ( "^/(.+)" => "/index.php/$1" )
				

然后程序通过PATHINFO取出图片URL

http://images.example.com/your/dir/test.jpg => http://images.example.com/index.php/your/dir/test.jpg
				

程序取出 /your/dir/test.jpg 设置 Content-type 并输出二进制流

详细参考

				
<?php
    // Test image.
    $images = '/test/foo.png';

    $headers = apache_request_headers();

    if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($images))) {
        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($images)).' GMT', true, 304);
    } else {
        header('Content-Type: image/png');
        print file_get_contents($fn);
		if (file_exists($images)) {
			header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($images)).' GMT', true, 200);
			header("Cache-Control: max-age=3600, must-revalidate");
			header('Content-Length: '.filesize($images));
			header('Content-type: ' .mime_content_type($images));
			flush();
			readfile($images);
			exit;
		}
    }
				
					

javascript 文件也可以使用类似方法处理

				
	private function js($file){
		if (file_exists($file)) {
			header("Cache-Control: max-age=3600, must-revalidate");
			header('Content-type: text/javascript');
			flush();
			readfile($file);
			exit;
		}
	}
				
					
1.9.3.1.2. Expires

只要向浏览器输出过期时间HTTP协议头,不论是html还是动态脚本,都能被缓存。

HTML META

				
<meta http-equive="Expires" content=" Mon, 10 Jan 2000 00:00:00 GMT"/>
<meta http-equive="Cache-Control" content="max-age=300"/>
<meta http-equive="Cache-Control" content="no-cache"/>
				
				

动态脚本

				
Expires: Mon, 10 Jan 2000 00:00:00 GMT
Cache-Control: max-age=300
Cache-Control: no-cache

header("Expires: " .gmdate ("D, d M Y H:i:s", time() + 3600 * 24 * 7). " GMT");
header("Cache-Control: max-age=300");
header("Cache-Control: no-cache");
				
				

很多web server都提供 Expires 模块

[提示]提示

有些浏览器可能不支持。

1.9.3.1.3. If-Modified-Since / Last-Modified

If-Modified-Since 小于 Last-Modified 返回 200

				
neo@neo-OptiPlex-780:/tmp$ curl -I http://www.163.com/
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=GBK
Transfer-Encoding: chunked
Vary: Accept-Encoding
Expires: Mon, 16 May 2011 08:12:05 GMT
Cache-Control: max-age=80
Vary: User-Agent
Vary: Accept
Age: 38
X-Via: 1.1 ls100:8106 (Cdn Cache Server V2.0), 1.1 lydx156:8106 (Cdn Cache Server V2.0)
Connection: keep-alive
Date: Mon, 16 May 2011 08:11:23 GMT
				
				

If-Modified-Since 大于 Last-Modified 返回 304

				
neo@neo-OptiPlex-780:/tmp$ curl -H "If-Modified-Since: Fri, 12 May 2012 18:53:33 GMT" -I http://www.163.com/
HTTP/1.0 304 Not Modified
Content-Type: text/html; charset=GBK
Cache-Control: max-age=80
Age: 41
X-Via: 1.0 ls119:80 (Cdn Cache Server V2.0), 1.0 lydx154:8106 (Cdn Cache Server V2.0)
Connection: keep-alive
Date: Mon, 16 May 2011 08:11:14 GMT
Expires: Mon, 16 May 2011 08:11:14 GMT
				
				
1.9.3.1.4. ETag / If-None-Match
				
neo@neo-OptiPlex-780:/tmp$ curl -I http://images.example.com/test/test.html
HTTP/1.1 200 OK
Cache-Control: s-maxage=7200, max-age=900
Expires: Mon, 16 May 2011 09:48:45 GMT
Content-Type: text/html
Accept-Ranges: bytes
ETag: "1984705864"
Last-Modified: Mon, 16 May 2011 09:01:07 GMT
Content-Length: 22
Date: Mon, 16 May 2011 09:33:45 GMT
Server: lighttpd/1.4.26
				
				
				
neo@neo-OptiPlex-780:/tmp$ curl -H 'If-None-Match: "1984705864"' -I http://images.example.com/test/test.html
HTTP/1.1 304 Not Modified
Cache-Control: s-maxage=7200, max-age=900
Expires: Mon, 16 May 2011 09:48:32 GMT
Content-Type: text/html
Accept-Ranges: bytes
ETag: "1984705864"
Last-Modified: Mon, 16 May 2011 09:01:07 GMT
Date: Mon, 16 May 2011 09:33:32 GMT
Server: lighttpd/1.4.26
				
				

1.9.3.2. CDN (Content Delivery Network) 与反向代理缓存

具有代表性的逆向代理服务器:

  1. Squid

  2. Nginx

  3. Varnish

  4. Apache cache module

其它逆向代理服务器

  1. 一些提供cache的硬件设备

  2. 最近几年出现了的 China Cache 服务商,也称CDN

很多CDN厂商使用Squid 二次开发做为CDN节点,通过全球负载均衡使用分发

这些CDN厂商主要做了一下二次开发

  1. logs 日志集中

  2. 流量限制

  3. push,pull操作

  4. url 刷新

s-maxage 与 max-age用法类似,s-maxage针对代理服务器缓存。同样适用于CDN

s-maxage 与 max-age 组合使用可以提高CDN性能

1.9.3.2.1. CDN接口API

与CDN有关的开发工作

CDN 内容更新,一般厂商会提供一个SOAP接口,你可以通过接口刷新你的内容。但接口有限制,不能随意使用,一般是多少秒可以刷新一次,或者一天可以刷新几次

1.9.3.2.2. 方向代理页面过期处理

方向代理一般都支持PURGE协议,Squid,Varnish等等向管理端口发送 PURGE 即可是使用页面刷新

PURGE http://netkiller.github.net/index.html
				

有些方向代理如:Varnish 可以使用正则表达式

同时这些代理服务器都承受管理命令

squid: squidclient

varnish: varnishadm

1.9.3.2.3. 内容版本化

例如这样的URL

http://images.example.com/logo.gif
http://images.example.com/product.jpg
				

我们可以通过Rewrite或PATHINFO等技术做为静态化。例如首次版本

http://images.example.com/logo.1.gif		=> logo.gif
http://images.example.com/product.1.jpg		=> product.jpg
				

原图发生变化后,版本递增

http://images.example.com/logo.2.gif		=> logo.gif
http://images.example.com/product.2.jpg		=> product.jpg
				

就的URL将丢弃

http://images.example.com/logo.1.gif
http://images.example.com/product.1.jpg
				

CDN 就回源去下面的URL,并且取到的是新图

http://images.example.com/logo.2.gif
http://images.example.com/product.2.jpg
				

1.9.3.3. 负载均衡设备

F5 Big-IP, Array 等设备都提供硬件加速,其原理与squid, apache提供的功能大同小异

其中Array 页面压缩采用硬件压缩卡实现,SSL加速也采用硬件实现

1.9.3.4. WEB服务器缓存

例如,通过配置apache实现自身 cache

1.9.3.5. 应用程序缓存

在这个领域百花齐放,相信你一定能找到适合你的。这些cache会为你提供一些api,来访问它。

代表性的 memcached 据我所是sina广泛使用,腾讯也曾经使用过后来开发了TC(Tencent Cache),台湾雅虎则使用APC Cache。

另外模板引擎也有自己的缓存系统

1.9.3.6. 数据库缓存

数据库本身就有这个配置选项,如果需要你仍然可以在数据库前面加一道Cache。

例如PostgreSQL, MySQL 都提供参数可以将memcached编译到它内部

1.9.4. 网站静态内容出版

1.9.4.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请求也要考虑缓存问题

静态化另一个目的是改善SEO

首次访问服务器

  1. 访问www服务器

  2. nginx 判断文件是否存在,如果存在将文件显示出来

  3. 如果文件不存在,去cms服务器上查找, 如果存在便返回给www服务器,并显示出来

  4. 如果cms上文件不存在,cms服务器便使用rewrite生成该文件, 同时将内容返回给www服务器,www将内容缓存在自己的服务器上,并将内容显示出来

第二次访问

  1. 访问www服务器

  2. nginx 判断文件是否存在,如果存在将文件显示出来

  3. 如果文件不存在,去cms服务器上查找, 如果存在便返回给www服务器,并显示出来

  4. 如果cms上文件不存在,cms服务器便使用rewrite生成该文件, 同时将内容返回给www服务器,www将内容缓存在自己的服务器上,并将内容显示出来

1.9.4.2. 静态化实现手段有哪些?

静态化方法包括:

  1. 生成方式

  2. 抓取方式

  3. 伪静态化

  4. 混合方式

1.9.4.2.1. 生成方式

主要由程序实现

例如

			
content = "<html><title>my static</title><body>hello world</body></html>"
file = open( your static file)
file.write(content)
file.close()
			
			
1.9.4.2.2. 抓取方式

主要由程序实现

程序中抓取

			
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中可。

1.9.4.2.3. 伪静态化

伪静态化是主要是通过在URL上做一些手脚,使你看去是静态的,实质上它是动态脚本。

伪静态化实现主要包括两种方法:

  1. Rewrite rule

  2. 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

1.9.4.2.4. 混合方式

其实目前网站使用的基本上都是上面几种方法混合方式。

例如首先将动态url(example.org/news.php?cid=1&id=1) 通过rewrite转换为 (example.org/new_1_1.html)

接下来就比较容易解决了,一种方法是使用wget example.org/new_1_1.html,另一种方法你无需静态化,直接使用squid规则配置让他永不过期

1.9.4.2.5. 静态化中的动态内容

在静态化页面中有一些内容是无法实现静态的。像登录信息,用户评论等等

我们用三种方法实现静态中嵌入动态内容:

  1. iframe - 灵活性差

  2. SSI - 消耗web服务器资源

  3. Ajax - 依赖浏览器,稳定性差

1.9.4.3. cdn

如何使用 cdn 来缓存你的网站内容

让你的网页缓存在 cdn 节点上的方式有下面几种

  1. 让cdn的客服帮你配置缓存的规则, 他们很喜欢一刀切, 例如所有html都缓存2小时

  2. 在他们管理后台自行使用正则配置缓存的时间, 这个他们一般不会提供, 某些公司的CDN会提供这个功能. 非常方便.

  3. 通过HTTP头自行控制缓存时间, 一般是使用 max-age / s-maxage / Last-Modified 判断缓存时间

我比较喜欢最后一种, 通常我们使用max-age 与 s-maxage 同时使用, 这样我可以按照我的意向来决定文件的缓存时间 这里有更详细的解释说明.

1.9.4.4. www 服务器

下面给出一个精简后的配置例子

如果文件不存在就会连接后端cms服务器生成文件,并且显示出来,同时加上缓存. 生成的文件会从cms中同步到www服务器上.

你可以采用

  1. rsync同步方案

  2. nfs/samba/gluster 共享方案

  3. iscsi 共享存储方案

  4. 分布式文件系统方案

参考阅读: 分布式文件系统 , 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;
    #}
}
		
		

1.9.4.5. cms 服务器

CMS 内容管理系统的主要功能

  1. 内容分类管理

  2. 内容模板管理

  3. 内容编辑与发布

  4. 内容生成

服务应该实现

  1. 当发现目录中文件不存, 通过rewrite生成html, 这样可能根据需要生成html页面

  2. 当页面更新的时候,应该通过api 刷新cdn的缓存, 图片的版本好应该加一

  3. 将页面分成多个模块, 通过SSI拼装页面, 避免有重大改版时, 整站生成HTML.

  4. 避免使用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;
    }
}
		
		

1.9.4.6. 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页面即可, 不用去理睬图片, 你的浏览器会用新的地址下载图片. 这样就解决了烦琐的刷新工作.

1.9.4.7. Ajax 局部更新与缓存

例如我的新闻评论页面,需要使用ajax技术, 将用户回复的品论显示来, ajax 载入json数据然后局部更新, 我对他做了1分钟的缓存

		
if ($request_uri ~* "\.(xml|json)$") {
	expires 1m;
}
		
		

如果有新的提交我们可以为json增加版本是控制例如: http://api.mydomain.com/news.json?1.0

1.9.5. 多媒体数据分离

1.9.5.1. 图片服务器分离

为什么要将图片服务器分离出来?

  1. 图片通常比较大,下载需要更长的时间,而web容器并发数也是相当宝贵的仅次于数据库。

  2. 传统浏览器一个窗口只占用一个链接数,目前主流浏览器都支持多线程下载,下载HTML页面同时,采用多线程下载其它多媒体数据。

我们举一个例子,你的服务器并发能力只用1000,早期浏览器不支持多线程,所以同一时刻,你的服务器可以承受1000个人同时访问。 但现在不同了,基本所有的浏览器都支持多线程,假如你的页面中有9张小图片,同一时刻你的服务器仅仅能应付1000/10 = 100个用户。

所以我们要将图片和其他多媒体文件分离出来,单独使用一台服务器处理请求。

[提示]提示

图片服务器建议使用lighttpd与squid缓存配合使用效果更好或购买CDN的服务。

1.9.5.2. 目录层次规划

日期有利于归档

			
/www/images
/www/images/2008
/www/images/2008/01
/www/images/2008/01/01
			
			

分类不同用途的文件

			
/www/images
/www/images/theme/2009

# article id 000001
/www/images/article/2009/01/000001

# product id 00001
/www/images/product/2009/01/01/00001

# member name neo
/www/images/member/2009/01/01/neo
			
			

根据你的数据量,创建目录深度, 并且目录深度有规律可循。

虽然64bit 文件系统不限制文件数量与目录深度,但是我还是建议按我的方式规划目录。

这样规划目录便于缓存控制,如:

images/2008/* 永久缓存

images/2009/* 缓存一个月

images/2010/* 缓存一小时

images/2010/06/* 缓存5分钟

1.9.5.3. 多域名访问

部分浏览器(IE)相同域名只能创建2个线程,在页面中使用多个域名可以解决这个限制

			
img1.example.com IN CNAME images.example.com.
img2.example.com IN CNAME images.example.com.
img3.example.com IN CNAME images.example.com.
...
imgN.example.com IN CNAME images.example.com.
			
			

1.9.6. 图片尺寸优化与自动裁剪

http://netkiller.github.io/journal/image.html

1.9.6.1. 背景

某天我的前同事给我打电话,说他们的负载很高,经查发现网站首页有20M,原因是首页直接引用高清图片,没有安装分辨率生成缩图。于是我便想出了下面的方案。

我认为方案需求有如下几个要素:

  1. 图片压缩

  2. 尺寸修改

  3. 图片缓存

  4. 带宽因素

例如用户使用手机访问网站,手机屏幕尺寸非常多样化,常见的有QVGA(320×240)、HGVA(480×320)、WVGA(800×480)、QCIF(176×144)、SVGA(640x480)、WXGA(1280×800)。如果一个用户的手机屏幕是320×240,打开网站后显示1027*768图片很不切合实际。同时用户也多出不少带宽开销。

我们需要给用户更好的体验,就要多从用户的角度去考虑,如根据用户网速,带宽,分辨率,为用户提供更适合他终端的多媒体资源。

1.9.6.2. 实现思路

1.9.6.2.1. 尺寸动态变化

B/S结构应用程序无法获取客户端的分辨率等信息,我们将采用Javascript取出参数,然后告知服务器端。

有下面几种实现方式:

  1. 通过cookie

  2. post传递给服务器,然后存储在session中

  3. get 传递给服务器,然后存储在session中

仅举一个例子

			
<script type="text/javascript">
$(function(){
    var width=window.screen.height;
    var height=window.screen.width;
    $.post('http://www.example.com/screen/resize.html',{w:width,h:height});
});
</script>
			
			

HTML页面中的图片的引用路径

			
<img src="http://img.example.com/sample.jpg" />		
			
			

图片服务器rewrite处理

			
http://img.example.com/sample.jpg => http://img.example.com/index.php/sample.jpg		
			
			

index.php会首先载入sample.jpg文件,然后综合网速,带宽,分辨率等因素,重新压缩图片,修改尺寸,发送mime头,输出正文。

1.9.6.2.2. 实时裁剪并静态化

为了防止图片地址冲突,我们首先需要URL唯一化,这样每访问一次会生成一张符合你需求尺寸的图片。

http://img.example.com/sample_(width)x(height)_(quality).jpg

			
<img src="http://img.example.com/sample_1980x1080_100.jpg" />	
<img src="http://img.example.com/sample_800x600_80.jpg" />
<img src="http://img.example.com/sample_640x480_50.jpg" />
			
			

配置nginx通过try_files配置项可以实现检查静态文件是否存在,如果不存在边调用index.php生成图片,当再次访问时会直接读取静态文件,不会再重新生成。

			
server {
    listen       80;
    server_name  inf.example.com;

    charset utf-8;
    access_log  /var/log/nginx/inf.example.com.access.log  main;
    error_log  /var/log/nginx/inf.example.com.error.log;

    location / {
        root   /www/example.com/inf.example.com/images;
        index  index.html;
		try_files $uri $uri/ /index.php?_url=$request_uri;
    }

    #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 ~ /index\.php$ {
        root           html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /www/example.com/inf.example.com/frontend/public$fastcgi_script_name;
        include        fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny  all;
    }
}			
			
			

通过这种方法还可以实现更复杂的需求,例如调整亮度,对比度,饱和度,色阶,图层叠加等等......

1.9.6.3. web或代理服务器插件实现方案

首先我们要将分辨率参数放到cookie中,因为web服务器是可以跟踪cookie数据的

通过 web 扩展实现,例如我们开发一个apache插件,编译后是".so"文件,配置httpd.conf载入插件,插件具体功能是综合网速,带宽,分辨率等因素,重新压缩图片,修改尺寸,最后展现图片。

反向代理与web服务器实现原理相同

1.9.7. 压缩数据传输

服务器将html或脚本输出压缩,用户从服务器取得数据后由浏览器解压

压缩数据传输实现方法:

  1. apache mod_deflate

  2. lighttpd compress module

1.9.7.1. Minify JS

最小化js文件

1.9.7.1.1. jsmin

http://crockford.com/javascript/jsmin

				
jsmin <fulljslint.js >jslint.js
				
				
1.9.7.1.2. yuicompressor

http://developer.yahoo.com/yui/compressor/

				
Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
				
				
1.9.7.1.3. shrinksafe

http://dojotoolkit.org/docs/shrinksafe

1.9.8. SSL

SSL 加密传输,为电子商务提供交易安全保护,什么时候该使用 SSL呢:

使用SSL

  1. 用户登录

  2. 购物流程

  3. 支付

什么时候不使用SSL? 经过SSL加密后,你就失去了很多功能,你不能在对页面做Cache/CDN,SSL加密与解密需要耗费你的服务器CPU与内存资源,能不使用尽量不使用。

对于SSL消耗你服务器资源这方面有两个方案解决

  1. 将SSL证书安装到CDN上,目前蓝讯,网宿等等CDN厂商都提供SSL服务。我与上两家技术人员沟通过,也安装了证书实际测试一下,你可以放心是使用。

  2. 将SSL证书安装到负载均衡设备,这些设备都采用专用硬件处理SSL请求,我测试过F5,Array,Banggoo

采用上面两种方案,无需改变你目前的服务器配置,他们的原理是

		
user (https://www.example.com) --> CDN or SLB (SSL) --> http://www.example.com
		
		

用户访问https,到达CDN或者负载均衡,CDN/SLB 通过http://请求源站,然后将内容SSL加密,返回给用户,这样用户得到的是加密内容。

用户提交数据,交给CDN/SLB,CDN/SLB将SSL加密数据卸载证书,然后将解密后数据发回源站。

CDN与SLB加载卸载证书原理很简单,不难理解。

我来教你DIY一个,你可以使用Squid,Nginx,Apache等等反向代理服务器,将证书安装在反向代理上,请求源站仍然采用http。

[提示]SSL注意事项

你如果认为把SSL挂载到网站前端就,大功告成,完事了,那你错了。

幸运的话你会成功,但有时的时候你发现你的证书不被信任。如果你是个细心的人,你会发现单个图片,或者你创建换成测试文件 echo helloworld > index.html 证书都是OK的。

这个问题出在你的html页面中,安装有SSL证书的网站,不能有外链js,flash等等不安全内容。

1.9.9. 搜索引擎相关优化

1.9.9.1. 搜索结果静态化

每个搜索关键字都应该有一个惟一的URL,例如

		
https://www.google.com.hk/search?sourceid=chrome&ie=UTF-8&q=netkiller&sei=9v-QT_q1L6SZiAel2bGnBA&gbv=2
https://www.google.com.hk/search?aq=f&sourceid=chrome&ie=UTF-8&q=neo
https://www.google.com.hk/search?sourceid=chrome&ie=UTF-8&q=bg7nyt
		
		

每搜索一次新的关键字就会产生一条唯一的URL,这样就可以实现反向代理缓存,甚者通过HTTP头,实现浏览器段的缓存。

1.9.9.2. robots.txt

			
<meta name="robots" content="noarchive">
			
		

例 1.1. example robots.txt

http://www.google.com/robots.txt

				
User-agent: *
Disallow: /search
Disallow: /groups
Disallow: /images
Disallow: /catalogs
Disallow: /catalogues
Disallow: /news
Allow: /news/directory
Disallow: /nwshp
Disallow: /setnewsprefs?
Disallow: /index.html?
Disallow: /?
Disallow: /addurl/image?
Disallow: /pagead/
Disallow: /relpage/
Disallow: /relcontent
Disallow: /imgres
Disallow: /imglanding
Disallow: /keyword/
Disallow: /u/
Disallow: /univ/
Disallow: /cobrand
Disallow: /custom
Disallow: /advanced_group_search
Disallow: /googlesite
Disallow: /preferencessection
Disallow: /setprefs
Disallow: /swr
Disallow: /url
Disallow: /default
Disallow: /m?
Disallow: /m/?
Disallow: /m/blogs?
Disallow: /m/ig
Disallow: /m/images?
Disallow: /m/local?
Disallow: /m/movies?
Disallow: /m/news?
Disallow: /m/news/i?
Disallow: /m/place?
Disallow: /m/setnewsprefs?
Disallow: /m/search?
Disallow: /m/swmloptin?
Disallow: /m/trends
Disallow: /wml?
Disallow: /wml/?
Disallow: /wml/search?
Disallow: /xhtml?
Disallow: /xhtml/?
Disallow: /xhtml/search?
Disallow: /xml?
Disallow: /imode?
Disallow: /imode/?
Disallow: /imode/search?
Disallow: /jsky?
Disallow: /jsky/?
Disallow: /jsky/search?
Disallow: /pda?
Disallow: /pda/?
Disallow: /pda/search?
Disallow: /sprint_xhtml
Disallow: /sprint_wml
Disallow: /pqa
Disallow: /palm
Disallow: /gwt/
Disallow: /purchases
Disallow: /hws
Disallow: /bsd?
Disallow: /linux?
Disallow: /mac?
Disallow: /microsoft?
Disallow: /unclesam?
Disallow: /answers/search?q=
Disallow: /local?
Disallow: /local_url
Disallow: /froogle?
Disallow: /products?
Disallow: /products/
Disallow: /froogle_
Disallow: /product_
Disallow: /products_
Disallow: /print
Disallow: /books
Disallow: /bkshp?q=
Allow: /booksrightsholders
Disallow: /patents?
Disallow: /patents/
Allow: /patents/about
Disallow: /scholar
Disallow: /complete
Disallow: /sponsoredlinks
Disallow: /videosearch?
Disallow: /videopreview?
Disallow: /videoprograminfo?
Disallow: /maps?
Disallow: /mapstt?
Disallow: /mapslt?
Disallow: /maps/stk/
Disallow: /maps/br?
Disallow: /mapabcpoi?
Disallow: /maphp?
Disallow: /places/
Disallow: /maps/place
Disallow: /help/maps/streetview/partners/welcome/
Disallow: /lochp?
Disallow: /center
Disallow: /ie?
Disallow: /sms/demo?
Disallow: /katrina?
Disallow: /blogsearch?
Disallow: /blogsearch/
Disallow: /blogsearch_feeds
Disallow: /advanced_blog_search
Disallow: /reader/
Allow: /reader/play
Disallow: /uds/
Disallow: /chart?
Disallow: /transit?
Disallow: /mbd?
Disallow: /extern_js/
Disallow: /calendar/feeds/
Disallow: /calendar/ical/
Disallow: /cl2/feeds/
Disallow: /cl2/ical/
Disallow: /coop/directory
Disallow: /coop/manage
Disallow: /trends?
Disallow: /trends/music?
Disallow: /trends/hottrends?
Disallow: /trends/viz?
Disallow: /notebook/search?
Disallow: /musica
Disallow: /musicad
Disallow: /musicas
Disallow: /musicl
Disallow: /musics
Disallow: /musicsearch
Disallow: /musicsp
Disallow: /musiclp
Disallow: /browsersync
Disallow: /call
Disallow: /archivesearch?
Disallow: /archivesearch/url
Disallow: /archivesearch/advanced_search
Disallow: /base/search?
Disallow: /base/reportbadoffer
Disallow: /base/s2
Disallow: /urchin_test/
Disallow: /movies?
Disallow: /codesearch?
Disallow: /codesearch/feeds/search?
Disallow: /wapsearch?
Disallow: /safebrowsing
Allow: /safebrowsing/diagnostic
Allow: /safebrowsing/report_error/
Allow: /safebrowsing/report_phish/
Disallow: /reviews/search?
Disallow: /orkut/albums
Disallow: /jsapi
Disallow: /views?
Disallow: /c/
Disallow: /cbk
Disallow: /recharge/dashboard/car
Disallow: /recharge/dashboard/static/
Disallow: /translate_a/
Disallow: /translate_c
Disallow: /translate_f
Disallow: /translate_static/
Disallow: /translate_suggestion
Disallow: /profiles/me
Allow: /profiles
Disallow: /s2/profiles/me
Allow: /s2/profiles
Allow: /s2/photos
Allow: /s2/static
Disallow: /s2
Disallow: /transconsole/portal/
Disallow: /gcc/
Disallow: /aclk
Disallow: /cse?
Disallow: /cse/panel
Disallow: /cse/manage
Disallow: /tbproxy/
Disallow: /comparisonads/
Disallow: /imesync/
Disallow: /shenghuo/search?
Disallow: /support/forum/search?
Disallow: /reviews/polls/
Disallow: /hosted/images/
Disallow: /hosted/life/
Disallow: /ppob/?
Disallow: /ppob?
Disallow: /ig/add?
Disallow: /adwordsresellers
Disallow: /accounts/o8
Allow: /accounts/o8/id
Disallow: /topicsearch?q=
Disallow: /xfx7/
Disallow: /squared/api
Disallow: /squared/search
Disallow: /squared/table
Disallow: /toolkit/
Allow: /toolkit/*.html
Disallow: /qnasearch?
Disallow: /errors/
Disallow: /app/updates
Disallow: /sidewiki/entry/
Disallow: /quality_form?
Disallow: /labs/popgadget/search
Disallow: /buzz/post
Sitemap: http://www.gstatic.com/s2/sitemaps/profiles-sitemap.xml
Sitemap: http://www.google.com/hostednews/sitemap_index.xml
Sitemap: http://www.google.com/ventures/sitemap_ventures.xml
Sitemap: http://www.google.com/sitemaps_webmasters.xml
Sitemap: http://www.gstatic.com/trends/websites/sitemaps/sitemapindex.xml
Sitemap: http://www.gstatic.com/dictionary/static/sitemaps/sitemap_index.xml
				
			

1.9.9.3. sitemaps

http://www.sitemaps.org/

sitemap.xml

1.9.9.4. Sitemap in robots.txt

				
User-agent: *
Allow: *
Disallow: /management/
Sitemap: http://netkiller.sourceforge.net/sitemaps.xml.gz			
				
		

1.9.9.5. sitemap 静态内容生成工具

		
#!/bin/bash
DOMAIN="http://www.netkiller.cn"
PUBLIC_HTML=~/public_html
if [ ! -z $1 ]; then
	DOMAIN=$1
fi
lastmod=`date "+%Y-%m-%d"`

echo '<?xml version="1.0" encoding="UTF-8"?>'
echo '<?xml-stylesheet type="text/xsl" href="gss.xsl"?>'
echo '<urlset xmlns="http://www.google.com/schemas/sitemap/0.84" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84 http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">'
#echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'

for htmlfile in $(find $PUBLIC_HTML/ -type f -name "*.html")
do
	url=`echo $htmlfile | sed -e "s:$PUBLIC_HTML/::"`
	echo '   <url>'
	echo '      <loc>'${DOMAIN}'/'${url}'</loc>'
	echo '      <lastmod>'${lastmod}'</lastmod>'
	echo '      <changefreq>daily</changefreq>'
	echo '      <priority>0.5</priority>'
	echo '   </url>'
done

for htmlfile in $(find $PUBLIC_HTML/ -type f -name "*.epub")
do
        url=`echo $htmlfile | sed -e "s:$PUBLIC_HTML/::"`
        echo '   <url>'
        echo '      <loc>'${DOMAIN}'/'${url}'</loc>'
        echo '      <lastmod>'${lastmod}'</lastmod>'
        echo '      <changefreq>daily</changefreq>'
        echo '      <priority>0.5</priority>'
        echo '   </url>'
done

for htmlfile in $(find $PUBLIC_HTML/ -type f -name "*.mobi")
do
        url=`echo $htmlfile | sed -e "s:$PUBLIC_HTML/::"`
        echo '   <url>'
        echo '      <loc>'${DOMAIN}'/'${url}'</loc>'
        echo '      <lastmod>'${lastmod}'</lastmod>'
        echo '      <changefreq>daily</changefreq>'
        echo '      <priority>0.5</priority>'
        echo '   </url>'
done

for htmlfile in $(find $PUBLIC_HTML/ -type f -name "*.chm")
do
        url=`echo $htmlfile | sed -e "s:$PUBLIC_HTML/::"`
        echo '   <url>'
        echo '      <loc>'${DOMAIN}'/'${url}'</loc>'
        echo '      <lastmod>'${lastmod}'</lastmod>'
        echo '      <changefreq>daily</changefreq>'
        echo '      <priority>0.5</priority>'
        echo '   </url>'
done

for htmlfile in $(find $PUBLIC_HTML/ -type f -name *.pdf)
do
	url=`echo $htmlfile | sed -e "s:$PUBLIC_HTML/::"`
	echo '   <url>'
	echo '      <loc>'${DOMAIN}'/'${url}'</loc>'
	echo '      <lastmod>'${lastmod}'</lastmod>'
	echo '      <changefreq>daily</changefreq>'
	echo '      <priority>0.5</priority>'
	echo '   </url>'
done

echo "</urlset>"		
		
		

1.9.10. 静态网站繁简转换

方案1: User -> Squid ->Web Server

修改squid源码,加入iconv(big5,gb2312,html page)

		
e.g.1 user (gb.example.org) -> Squid (big5->gb2312) -> web server
e.g.2 user (big5.example.org) -> Squid (gb2312->big5) -> web server