Professional Documents
Culture Documents
1-1 页面静态化技术
1-1 页面静态化技术
1 页面静态化的对象:
针对的是那些修改很少,但反复查询量大的数据。
2 页面静态化的技术:
2.1 Php 自带的 ob 缓存来实现页面静态化(用于将对数据库的高访问量转变成去访问 html 静态页面,
从而实现减小数据库负担并提速,但如果更新数据后在新访问该数据时可能会产生滞后) :在
需要 echo 的内容之前开启 php 缓存,然后将缓存的内容输出存入到一个 html 文件:缺点是
(1)当更新数据后,html 不会变化,只能通过每过一段时间更新一下 html 文件,这样 html 文
件会有延时;(2)查询某个页面时,是通过 php 动态网址去访问的页面的(.php?id=…)。
2.2 真静态技术(用于将对数据库的高访问量转变成去访问 html 静态页面,从而实现减小数据库负
担并提速,且保证数据实时性,但可能会产生海量 html 文件):真静态可以解决 php 自带缓存
实现静态化中的延时问题,它的技术和 php 缓存完全不同。它在数据第一次 INSERT 到数据库时
同时创造 html 文件,当再次访问数据时,就直接访问相同 id 的 html 文件,而不再访问数据库。
所以,真静态即解决了服务器对数据库高并发访问的问题,同时也实时更新了 html 静态文件
(即解决了 php 缓存实现静态化所带来的延迟问题),它解决了访问量大或访问频繁的问题。
但如果该应用程序有海量数据(海量 id),真静态就会产生问题,因为会造成创建大量的 html
文件,就会(1)占用大量磁盘,(2)查询海量 html 文件同样有速度问题。相对好一些的做法
是,可以按照某种规则,比如将 html 文件按日期存入不同文件夹,这样也可以相对环节查询的
速度,但是磁盘占用大是无法解决的。
2.3 伪静态技术(用于优化 seo):伪静态技术只是把动态页面的动态网址(.php)改写成静态网址
的形式(.html),伪静态网址并不是让动态网页静态化,对网页访问时还是和原来一样会访问
数据库。所以,并不能解决高并发访问数据库的问题,但它适合 seo。如果只是为了 seo,就只
是用伪静态技术就可以了。如果网站要 seo,数据量(id)也非常海量,但一般只会查询少部分
的 id,比如电话费查询系统,数据库存储并可以查询用户所有月份的电话费(比如 10 年),这
样就会产生海量 id,显然用真静态不太合适,而根据实际情况,用户一般都只会查询近 3 个月
的电话费,这样实际上并不产生海量 id,所以可以使用“伪静态技术(seo 好)+php 自带 ob 缓
存(在查询时创建 html 文件)”。但是,随着时间和访问量的推移,数据会越来越庞大,最终
会趋向于海量 id,变成真静态的海量 html 文件的结果。
3 基本概念
3.1 静态页面:是不操作数据库的 html 文件。
3.2 动 态 页 面 : php 网 址 如 : http://localhost/news.php , 或 : http://localhost/news.php?
lang=cn&class=1&id=2。
3.3 伪静态:是把动态页面的动态网址改写成静态网址的形式,但文件的内容还是和原来一样会操
作数据库。如:http://localhost/news-cn-class1-id2.html。
4 为什么要进行页面静态化的三个好处:
4.1 访问速度:内存>文件>数据库。由于数据库访问速度最慢,且如果过高并发访问数据库会使数
据库崩溃,所以在有可能的情况下应尽量减少对数据库的读取,特别是哪些不太修改单会反复
去读取的数据,可以将数据存到文件中,每次去读取文件,来代替读取数据库。这就是页面静
态化技术。
4.2 访问 php 的速度比 html 慢:
4.2.1 在 apache/bin 的 ab.exe 工具,可以做压力测试,可以模拟多人并发访问某个页面。
4.2.2 测试将返回的指标:
文件大小
平均每秒执行的访问次数 Requests per second
平均每次访问的响应时间 Time per request
4.2.3 测试:
1) 在 cmd 中进入到 apache/bin 下。
2) 执行语句:(ab.exe -n 执行次数 -c 并发数 访问页面地址)
说明:c 表示用户并发数,n 表示每个用户执行访问次数。
比如:ab.exe -n 10000 -c 10 http://text.php
3) 比如:
test.php
<?php
for($i=0,$i<100,$i++) {echo $i;}
?>
测试:ab.exe -n 10000 -c 10 http://text.php
test.html
01234……99
测试:ab.exe -n 10000 -c 10 http://text.html
测试结果会证明,访问 php 的速度比 html 慢。
5 Php 自带 ob 缓存技术实现页面静态化
5.1 思路:
5.1.1 有一个 news_list.php 新闻列表中,可以点击某条新闻的详细内容连接查看详细内容<a
href="newsAcction.php?id=$id">)。当第一次点击某条新闻的详细内容时,即第一次从数据
库 SELECT 时,将需要计划 echo 到浏览器的内容进行缓存(开启缓存 ob_start();),然后
$content = ob_get_contents()来获取缓存内容,并保存到一个 html 静态文件中,文件名包含
该 数 据 的 id , 如 $html_filename="news_id".$id.".html"; file_put_contents($html_filename,
$content)。在该 newsAcction.php 脚本结束后便会自动输出新闻的详细内容。在实际代码中 ,
当希望访问某条新闻的详细内容时,先查看是否存在该条新闻的 html 文件,如果存在,直
接 echo file_get_contents($html_filename); exit(); 打印出该 html 中的内容,并退出脚本(如
果不退出,则会继续往下执行,即还是去读了数据库),如果不存在,则采用第一次访问
的方法访问数据库并创建 html 文件。
5.1.2 所以,这种方法是在第一次 SELECT 时创建 html 文件的,而不是在 INSERT 时创建 html 文件
的,这意味着不会像 INSERT 时创建 html 那样产生那么多的可能不会访问的 html 文件。但
问题是:当新闻内容被修改后,html 并不会被修改,一个解决方法是,设置一个过期时间,
比 如 30 秒 , 如 果 html 文 件 存 在 且 没 有 过 期 ( if(file_exits($html_filename) &&
filetime($html_filename)+30>time()){echo file_get_contents($html_filename); exit(); } ) , 一
旦过期,就删除该 html 文件,而当用户再次访问某条新闻时,如果文件从未被访问过(不
存在 html 文件),或者已经过期被删除(同样不存在 html 文件),就会像第一次访问某条
新闻一样,去查询数据库并创建一个 html 文件。
6 真静态技术实现页面静态化
6.1 思路:
6.1.1 对于那些不太变化,且会被很多用户读取的数据,应尽量避免反复去数据库 SELECT,且当
不会生产海量 html 文件的情况下,就可以考虑使用真静态技术实现页面静态化。其思路为
在添加 INSERT 这些数据的后可获得该条数据的 id,然后通过该 id 就同时创建对应的 html
静态文件,当下次有用户访问该数据时便可以直接 echo 出 html 文件中的内容,这些就是真
静态技术。
6.2 步骤:
6.2.1 数据列表页面 new_list.php:
当需要读取数据时,因为在 INSERT 环节就已经创建了 html 文件,所以根据数据的 id,
直接<a href=$html_filename>到对应的$html_filename="news_id".$id.".html";的静态文
件上。
当需要添加数据时,通过<a href="add_news.html">连接到 add_news.html 表单文件,
然后提交表单到 newsAction.php,进行数据库添加数据并创建对应 id 的 html 静态文件。
当需要修改数据时,通过<a href="update_news.php?id=$id">连接到表单文件,并把 id
传 给 表 单 页 面 , 然 后 提 交 表 单 到 newsAction.php ( 该 $id 通 过 隐 藏 域 来 传 到
newsAction.php),进行数据库更新数据、和对应 html 静态文件的更新。
当需要删除数据时,通过<a href="newsAction.php?id=$id">连接到 newsAction.php,进
行删除对应 id 的 html 静态文件和数据库中的数据。
6.2.2 数据处理页面 newsAction.php:
6.2.2.1 当需要添加数据到数据库时,
执行 INSERT,存入数据库。
INSERT 成功后会产生该条数据的 id($id=mysql_insert_id();),就可以设计 html
静态页面的文件名($html_filename="news_id".$id.".html";)。
将会展现到浏览器的数据存入 html 文件,以便其他用户直接访问对应 id 的 html
文件。具体创建 html 文件的过程和代码见下面举例。
6.2.2.2 当需要 UPDATE 数据时,
UPDATE 数据库中的数据。
删除该 id 的 html 文件(unlink($html_filename);)。
根据 INSERT 方法重新创建 html 文件。
6.2.2.3 当需要 DELETE 数据时,
删除该 id 的 html 文件(unlink($html_filename);)。
DELETE 数据库中的数据。
7 伪静态技术
7.1 对于诸如 http://localhost/content.php/2,111,345.html 这样的网址,会认为 content.php 是一个页
面,后面的内容(2,111,345)会被认为是带有的参数,所以还是会访问 content.php 页面。但带
有.html 这种形式的参数在 seo 中会更优于?id=value 这样形式去带参数。所以,通常我们可以把
动态网址:http://localhost/content.php?a=2&b=111&c=345,伪静态化,变为:http://localhost/
content.php/2,111,345.html。可以通过正则表达式获取参数,或也可以通过 apache 的 rewrite 机
制来获取参数。
7.2 通过正则表达式获取参数(通过$_SERVER['PATH_INFO']):
//$_SERVER 里有一个:
$para=$_SERVER['PATH_INFO'];
if(preg_match('/^\/(\d+),(\d+),(\d+)\.html/si',$para,$arr)){ //$arr[0]= /2,111,345.html; $arr[1]=2;
$arr[2]=111; $arr[3]=345.
//进一步代码
} else {
//地址有误
}
我们涉及到:
(1)在首标签<Diretory>中指定一个根目录(包括该目录以及其子目录和文
件),接下来的配置针对该目录有效;
(2)配置是否允许用户访问该根目录;
(3)是否对该根目录下的内容进行重写。
重要的一点是:如果下面有一个相同的配置,则下面的配置会覆盖上面的配置 。
即 如 果 下 面 还 有 <Directory></Directory> , 则 覆 盖 该 上 面 的 <Directory></
Directory> 配置。 在该文件的下一段<Directory></Directory>中可以对相关配置进
行修改。
指定将会配置权限的根目录:在首<Directory>标签内设置根目录,以便下面
对 该 根 目 录 的 访 问 呢 权 限 进 行 设 置 。 如 这 里 的
,设置这个根目录是因为默认将
Web 服务器的根目录设置为 htdocs 下,所以需要对该根目录的访问权限进
行设置。如果没有对哪个根目录进行允许访问的设置,那么 Web 浏览器是
无 法 访 问 的 ( 403 Forbidden 无 权 限 访 问 错 误 提 醒 ) , 因 为 在 第 一 段 的
<Directory>中已经严格地拒绝了所有的访问。
是否允许重写 AllowOverride(只针对<Directory>中指定的根目录生效):
None 表示不允许,All 表示允许所有。
配置是否允许用户访问该 Web 服务器根目录(只针对<Directory>中指定的
根目录生效):
默认情况下是关闭的,即前面有一个#号,删除它,便可以开启它。即:
7.3.2.3 关联 ip 和域名:
打开 c:\windows\system32\drivers\etc 下的 hosts 文件。
添 加 虚 拟 主 机 中 添 加 你 的 ip 和 域 名 对 应 关 系 , 如 下 可 以 添 加 127.0.0.1
www.hsp.com,这样就配置了一个 ip 为 127.0.0.1 和域名为 www.hsp.com 的对应
关 系 的 虚 拟 主 机 。 这 样 就 可 以 使 用 域 名 了 , 而 不 用 总 是 使 用 localhost 或
127.0.0.1。即网址可变为:http://www.hsp.com/。备注:如果要访问局域网中其
他机器,则改成其他机器的 ip。
7.3.2.4 启用虚拟主机:
在 apache/conf/extra 下打开 httpd.conf 文件,去掉前面的#号:
重启 apache。
7.3.2.5 配置虚拟主机---httpd-vhosts.conf 文件:
在 apache/conf/extra 下打开 httpd-vhosts.conf 文件。
找到<VirtualHost *:80></VirtualHost >这段话:
在这段话下面写一段<VirtualHost *:80></VirtualHost>来覆盖上面这段话,或者直
接将这段话复制沾粘到下一面直接进行修改:
DocumentRoot:用来配置虚拟主机的根目录,可自行修改。比如这里设置
为 C:/myeenv/apache/htdocs/static3,也可以设置任何的目录,比如:d:/
static3。
ServerName : 用 来 设 置 虚 拟 主 机 所 使 用 的 服 务 器 名 字 , 在 c:\windows\
system32\drivers\etc 的 hosts 文件中找到已经存在的 ip 和域名,比如之前我
们配置的 www.hsp.com,所以,就在这里 ServerName 处写 www.hsp.com。
经 过 这 样 的 配 置 , 那 么 , 网 址 虚 拟 主 机 服 务 器 名 字 ( http://
www.hsp.com/ )将对应到虚拟主机的根目录( C:/myeenv/apache/htdocs/
static3/)。
再来配置虚拟主机所设置根目录的 Web 浏览器的访问权限:在<VirtualHost
*:80></VirtualHost> 段 最 后 , </VirtualHost> 尾 标 签 之 前 , 添 加 一 段
<Directory></Directory> , 这 样 可 以 覆 盖 apache/conf/httpd.conf 文 件 中 的
<Directory></Directory>,但仅限于该域名(ServerName),这意味着进一
步限制了指定用户的权限,即对于指定的域名只能访问指定的根目录,而
不能访问其他根目录。
#告诉<Directory>将要配置的虚拟主机的根目录,即上面 DocumentRoot 设置
的根目录。
<Directory "C:/myeenv/apache/htdocs/static3">
# 允许 所有用户访问 Web 服务器根 目录 ( 备注 :由于 DocumentRoot 和
ServerName 的设置,允许用户通过域名来访问对应的根目录)
Allow from all
# Options+indexes 当根目录不在 htdocs 下,即不放在 apache 目录下(比如
将上面的根目录配成 d:/static3),则该语句表示当访问 www.hsp.com 时,
将显示根目录下的所有文件列表,如果不写该句话,则不显示并出现 403
Forbidden 的没有权限的错误提示。但如果根目录在 htdocs 下,则不管是否
写这句话,都会显示根目录下的所有文件列表。在发布项目后一般是需要
禁用的,因为不希望别人看到目录下的列表,即不写该语句,或在该语句
前加上#号注释掉。
#Options+indexes
#启用 apache 的 rewrite。
AllowOverride all
</Directory>
然后重启 apache,如配置错了,重启时会报错。
,就会连到 http://www.hsp.com/
8 自动定期删除文件(如果产生海量文件):
8.1 针对 windows 系统:
在应用程序根目录下建立一个 php 文件(这里比如是 c:\myenv\apache\htdocs\static3\),
比如:clear.php,并编写如下代码来指定需要删除哪些文件:
<?php
//代码:遍历指定的某些目录,找出已经过期的文件。
//unlink("news-id100.html"); //删除这些文件
?>
在 apache/bin/下创建一个.bat 文件,比如:mybat.bat,并在该文件中写入如下内容:
"C://myenv\\apache\\bin\\ab.exe" -n 1 - c 1 http://www.hsp.com/clear.php
备 注 : 以 上 语 句 代 表 当 执 行 mybat.bat 时 , 会 用 ab.exe 模 拟 执 行 访 问 clear.php 。 其 中 ,
apache\bin\ab.exe 的路径根据实际来写。
此时,如果双击该 bat 文件,就可以删除在 clear.php 中指定的文件。但我们按照如下方法,
可以自动定期产生设置的文件:控制面板->任务计划->添加任务计划->点击下一步->点击浏
览->选择创建的 mybat.bat->可以修改任务名称,在执行这个计划中选择希望按照什么频率
执行该任务,比如每天->选择执行该任务的开始时间以及开始日期->输入密码(用户的登录
密码,以确保系统可以自动执行任务)->点击完成。这样,系统就会按照设置的频率自动
定期删除设置的文件。备注:该文件也可以在属性中修改定期时间等相关选项。
8.2 针对 linux 系统:
Linux 有 crontab。通过.sh 文件(shell 编程)来实现。
9 真静态实现页面静态化实例—新闻管理系统
建立数据库
/*创建表格*/
CREATE DATABASE spdb1;
USE spdb1;
CREATE TABLE news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL,
content VARCHAR(256) NOT NULL,
filename VARCHAR(32)) /*记录静态页面的名字*/
ENGINE=MyISAM;
/*创建一些测试数据*/
INSERT INTO news(title,content) VALUES('hello1','beijing nihao');
INSERT INTO news(title,content) VALUES('hello2','sichuan nihao');
new_list.php
<?php
//查询数据库,一般使用 SqlHelper.class.php,这里自己写一下代码
$conn = mysql_connect("localhost","root","root") OR die("MySQL connet Falure!");
mysql_select_db("spdb1",$conn); //如果不使用$conn,则 php 会使用最后一个连接,好习惯是加上自
己需要的连接,而且速度也相对更快一些,因为 php 不用去往上找最近的那个连接。
//mysql_query("set names uft8");
$sql = "SELECT * FROM news";
$res = mysql_query($sql);
header("content-type:text/html; charset=utf-8");
echo "<h1>News List</h1>";
echo "<a href='add_news.html'>add news</a><hr/>";
echo "<table><tr><td>id</td><td>title</td><td>see details</td></tr>";
while($row = mysql_fetch_assoc($res)){
echo "<tr><td>{$row['id']}</td><td>{$row['title']}</td><td><a href='news_id{$row['id']}.html'>see
details</a></td><td><a href='news_update. php?id={$row['id']}'>update</a></td><td><a
href='news_delete.php?id={$row['id']}'>delete</a></td></tr>";
echo "</table>";
}
mysql_free_result($res);
mysql_close($conn);
?>
add_news.html
表单文件
action 到 newsAction.php
update_news.html
表单文件
action 到 newsAction.php
template.tpl
<html>
<head>
<title>%title%</title>
</head>
<body>
<h1>%title%</h1>
<hr />
<pre>%content%</pre>
</body>
</html>
newsAction.php
<?php
header("content-type:text/html; charset=utf-8");
//设计一个替换的函数
function replace($row,$title,$content){
$row=str_replace("%title%",$title,$row);
$row=str_replace("%content%",$content,$row);
return $row;
}
if($oper=='add'){
$sql="INSERT INTO news (title,content) VALUES ('$title','$content')";
if(mysql_query($sql,$conn)){ //如果 insert 成功,则可以获得该条数据的 id,这样就可以设计 html 页
面的文件名了。
$id=mysql_insert_id();
$html_filename="news_id".$id.".html";
$fp_tmp=fopen("template.tpl","r"); //不能以 w 方式打开,不然文件内容会被清空。
$fp_html_file=fopen("$html_filename","w");
} elseif($oper=='update'){
$id=$_POST['id'];
$sql="update news set title='$title', content='$content' where id=$id";
if(mysql_query($sql, $conn)){
$html_filename="news_id".$id.".html";
unlink($html_filename); //删除该 html 文件,再重新通过 insert 的方法创建 html 文件。
$sql="INSERT INTO news (title,content) VALUES ('$title','$content')";
if(mysql_query($sql,$conn)){ //如果 insert 成功,则可以获得该条数据的 id,这样就可以设计 html
页面的文件名了。
$id=mysql_insert_id();
$html_filename="news_id".$id.".html";
$fp_tmp=fopen("template.tpl","r"); //不能以 w 方式打开,不然文件内容会被清空。
$fp_html_file=fopen("$html_filename","w");
} elseif($oper=='delete'){
}
?>
总结:
为了减少对数据库的访问量,且希望静态页面的数据可以实时性,我们会选择使用真静态技术,
真静态技术也利于 seo。对于有海量 id 的网站,会产生海量的 html 文件,因为它是在 INSERT 时
同时产生 html 文件的,需要注意的是真静态还是会在 insert 和创建 html 间产生一些延时。带来
的问题就是(1)磁盘占用多,(2)查询海量文件同样有速度问题。对于(2)一个解决方法是
根据 id 产生的时间存入不同的文件夹中,这样可以有针对的访问不同的文件夹来加快查询文件的
速度,但是无法解决磁盘占用多的问题。
为了减少对数据库的访问量,也可以使用 php 自带 ob 缓存技术,但是它会产生被更新数据的时
间滞后,因为它是在 SELECT 时产生 html 文件的,数据在数据库更新后无法改变和 html 文件,所
以只能通过设置一个过期时间来解决。但也正是由于它在 SELECT 时而不是在 INSERT 时产生 html
文件,所以它产生的 html 文件更符合实际需求,不会产生访问量少的 html 文件,但是需要注意
的是,随着时间和访问量的推进,最终它还是会产生海量 html 文件。
伪静态技术的目的是为了利于 seo,但还是要访问数据库,所以我们可以结合 php 自带 ob 缓存技
术和伪静态技术。
而为了解决海量 html 的问题,特别是那些对早期数据访问量很低的情况,比如新闻、对账单等,
用户一般只会查询最近的信息,我们可以定期手动,或通过编程来定期自动删除较早的 html 文件,
具体手动还是自动,取决于实际应用情况。
一些建议:
如果网站数据的实时性要求很高,UPDATE 很平凡,比如股票价格,就不适合使用页面静态
化技术。
如果网站访问量较小,也没有必要使用页面静态化技术。
如果数据项目(id)不多,但访问频率很高,就要使用真静态技术,比如新浪新闻,一天没
有多少新闻,但新闻访问量会非常高。
如果数据项目(id)海量,如果使用真静态技术就会产生海量 html,建议使用伪静态技术。
设计方案 1 – 真静态:
对象:以查询 SELECT 为主,修改 UPDATE 较少的数据,且用户更关心近期的数据。
方案:(1)首先使用真静态以实现减少数据库访问以及 html 文件内容的实时性。(2)如果
会产生海量文件,就定期删除较早的文件,文件按照数据本身的新旧日期(也可以按照 id 的
数量分文件夹)存放在不同的文件夹内以加快访问速度。( 3)和真静态方案不同的是,此
时在查询时需要先要判断 html 文件是否存在,如果不存在则使用 insert 时的方法创建。
设计方案 2—php 自带 ob 缓存:
对象:以查询 SELECT 为主,修改 UPDATE 较少的数据,且用户更关心近期的数据。
方案:(1)首先使用 php 自带缓存技术在 SELECT 时创建 html 文件。(2)当发生 update 时,
查询 html 文件是否存在,如果存在则更新该 html 文件。(3)如果会产生海量文件,就定期
删除较早的文件,文件按照数据本身的新旧日期(也可以按照 id 的数量分文件夹)存放在不
同的文件夹内以加快访问速度。