首页自动生成静态化html

时间:2023-03-08 23:49:41
首页自动生成静态化html

由于平台老是出现间歇性502。排查发现,php死进程过多耗费大量系统资源。

除了优化代码之外,静态化可以减少php进程。缓解一下服务器压力。

把首页生成html后,出现问题频率下降。所以需要做首页静态化,并自动按规定时间更新。

1,在模板引入生成脚本,k的值随便定,只是为了防止没参数时,直接访问脚本static.php的触发。

 <script type="text/javascript" src="/static.php?k=XXXXXX"></script>

2,脚本

$k = trim($_GET['k']);
if (!is_string($k) || strlen($k) < 32 || $k !== md5("XXXXX")) {
return false;
}
//首页1分钟更新一次
if (!file_exists("index.html") || time() - filemtime("index.html") > 60) {
create_html();
} //生成静态
function create_html()
{
//开启output buffer 缓冲区,如果php已经开启,则不需要。
// php.ini 中,output_buffering = 4096
// if (!ini_get('output_buffering')) {
ob_start();
// }
//调用模板组织成页面
require "index.php";
//获取缓冲区中的页面,并清除缓冲区
$content = ob_get_clean();
//将页面保存成为静态文件
$s=file_put_contents("index.html", $content);
if($s){
echo $s;
}else{
echo 0;
}
}

 如果写入失败,考虑写入权限问题   chmod -R 777 XXX 

出现问题:

1,因为首页上面有登陆后,出现欢迎你,XXX的,东西,会出现,登陆用户如果更新缓存会把这些字符给抓下来,写入index.html

屏蔽ob缓存,采用file_get_content或者curl,或者用了ob之后phpquery来处理文档也可以。

2,超时问题

如果本身由于各种问题,index.php访问过慢。有可能会写入失败或者不完整。做了3套方案。

并且做了超时,和内容长度判断

以下是修改后代码

<?php
/**
* 静态化
* User: lee
* Date: 2015/12/7
* Time: 17:40
*/
//自定义验证
$k = trim($_GET['k']);
if (!is_string($k) || strlen($k) < 32 || $k !== md5("XXX")) {
die('{"status":0,"info":"k is error"}');
}
//首页1分钟更新一次
if (!file_exists("index.html") || time() - filemtime("index.html") > 60) {
  //刷新缓存
ob_flush();
flush();
$obj = new StaticPage();
$obj->create_html();
} else {
die('{"status":0,"info":"file exists"}');
} //静态类
class StaticPage
{
//生成静态
public function create_html()
{
$ob = json_decode($this->P(1), 1);//优先ob缓存
if ($ob['status'] == 0) {
$file_get_content = json_decode($this->P(2), 1);
//失败,采用http
if ($file_get_content['status'] == 0) {
          //采用curl
$curl = json_decode($this->P(3), 1);
if ($curl['status'] == 0) {
die('{"status":0,"info":"server error"}');
} else {
echo json_encode($curl);
}
} else {
echo json_encode($file_get_content);
}
} else {
echo json_encode($ob);
} } /**
* http get请求
* @param string $url
* @param mixed $param
* @param int $time
* @return mixed
*/
private function httpGet($url, $param = null, $time = 1000)
{
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//不验证证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//不验证host
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 500);//设置时间
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1); //注意,毫秒超时一定要设置这个
curl_setopt($ch, CURLOPT_TIMEOUT_MS, $time);
//curl_setopt($ch, CURLOPT_TIMEOUT, $time);//设置时间
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//不直接输出
// grab URL and pass it to the browser
$result = curl_exec($ch);
if (curl_errno($ch)) {
//echo 'Errno2'.curl_error($ch);//捕抓异常
return false;
}
// close cURL resource, and free up system resources
curl_close($ch);
return $result;
} /**
* 获取页面
*/
private function P($type = 1)
{
$url = "http://" . $_SERVER['HTTP_HOST'] . "/index.php";
//ob缓存
if ($type == 1) {
//由于首页有登陆状态,使用ob缓存会记录登陆者名字进入缓存文件。
// if (!ini_get('output_buffering')) {
ob_start();
// }
require "index.php";
$content = ob_get_clean();
//把登陆欢迎信息替换,不能缓存用户名,phpQuery是一个dom处理的类,详细可以看我另外的文章 http://www.cnblogs.com/findgor/p/4955321.html
require "../App/Common/phpQuery.php";
phpQuery::newDocument($content);
$str = <<<STR
<a href="http://{$_SERVER['HTTP_HOST']}/XXXXX" rel="nofollow">立即登录</a>
<a href="http://{$_SERVER['HTTP_HOST']}/XXXXX" style="background:#A3A3A3;font-size:16px;font-weight:bold;color:#fff;" rel="nofollow">免费注册</a>
<a href="http://{$_SERVER['HTTP_HOST']}/XXXX/" style="color:#cccccc">帮助中心</a>|
<a href="http://{$_SERVER['HTTP_HOST']}/XXXX/" style="color:#cccccc" rel="nofollow">关于我们</a>|
<a href="XXXXX" style="color:#cccccc" rel="nofollow">VIP中心</a>
STR;
pq("#head #head_nav .right")->html($str);
$dom = pq()->html();
return $this->W($dom, 1);
}
//file_get_contents
if ($type == 2) {
$opts = array(
'http' => array(
'method' => "GET",
'timeout' => 1, //设置超时
)
);
$context = stream_context_create($opts);
$content = @file_get_contents($url, false, $context);
return $this->W($content, 2);
}
//curl
if ($type == 3) {
$content = $this->httpGet($url);
return $this->W($content, 3);
}
} /**
* 写入
* @param null $content 数据
* @param int $type 类型
* @return json
*/
private function W($content = null, $type = 1)
{
//大于1W字符写入
if (strlen($content) > 10000) {
$index = @file_put_contents("index.html", $content);
if ($index) {
return json_encode(array("status" => 1, "data" => $index, "info" => "write ok!", "type" => $type));
} else {
return json_encode(array("status" => 0, "data" => $index, "info" => "write false!", "type" => $type));
}
} else {
return json_encode(array("data" => 0, "info" => "<10000", "type" => $type));
}
}
} ?>

===================

考虑到其他页面的静态化。有2种想法

1,同样在这个static.php脚本里面触发,增加批量检测更新

2,后台按钮手动触发。

这两种方式那种最好。待我测试之后再行更新此文章。

补充:

过了2年了,再看这篇文章,技术显然不太符合现在的开发规范。目前采用的是redis缓存,所有首页数据都存到redis里面,定时cron更新

目标都是减少数据库开销,而redis是基于内存的,比磁盘读写速度要快,比较符合当前的开发概念。

参考:http://blog.****.net/jetxt/article/details/44563145#0-tsina-1-16123-397232819ff9a47a7b7e80a40613cfe1