首頁自動生成靜態化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.csdn.net/jetxt/article/details/44563145#0-tsina-1-16123-397232819ff9a47a7b7e80a40613cfe1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM