大型網站概念及解決方案

1、判斷大型網站的標準

一、pv(page views)網頁的瀏覽量

概念:一個網站全部的頁面,在24小時內被訪問的總的次數。千萬級別,百萬級別,javascript

二、uv值(unique vistor)獨立訪客

概念:一個網站,在24小時內,有多少個用戶來訪問咱們的網站。達到10萬php

三、獨立ip

概念:一個網站,在24小時內,有多少個ip來訪問咱們的網站。css

uv值約等於獨立ip.若是要考慮局域網,uv值略大於獨立iphtml

2、大型網站帶來的一些問題

一、大的併發

併發量:在同一時間點(1秒內),有多少個用戶同時訪問咱們的網站。對同一個網址,同時刷新瀏覽器。達到500,就很是大了。java

假如併發量是500,pv值是多少。500*3600*10mysql

二、大流量

網站須要的大的帶寬。10G.linux

三、大的存儲

網站中的數據庫,表的容量成海量趨勢,GT級別,如何快速的查找出想要的數據。nginx

3、大併發的解決方案

要對網站的服務器從新架構,採用分層,負載均衡的架構。web

一、負載均衡器

硬件:f5-bigip  性能比較好,立竿見影,價格昂貴,通常適合於大型網站公司,網遊公司。正則表達式

軟件:

lvs(linux virtual server)linux虛擬服務,加入到linux的內核中。

nginx:能夠作web服務器(apache),還能夠作負載均衡。

二、負載均衡實現的方式

輪詢技術:客戶端請求服務器輪流轉發。

ip哈希:同一ip地址的客戶端,始終請求同一臺服務器。

最少鏈接:把請求轉發給最空閒的服務器。

三、集羣

主要是解決計算機單點故障,在一個集羣中的計算機,只有一臺計算機工做,其餘計算機處於休眠狀態,監視正在工做的計算機,當正在工做的計算機出現問題,則休眠的計算機馬上接替工做。

4、大流量解決方案

一、防止咱們的網站資源被盜鏈

能夠採用一些非技術手段防止被盜鏈,在圖片上添加水印

二、減小http請求

主要手段就是合併js文件,css文件,背景圖片的文件。將瀏覽器須要的樣式文件或者js文件,合併成一個樣式文件或js文件。好比經過背景圖片舉個例子。

具體的代碼:

三、啓用壓縮

減小數據傳輸的數據量,常見的壓縮格式是:gzip,deflate,compress以及google、chrome正在推的sdcn

原理:

(1)在httpd.conf中開啓壓縮配置:LoadModule deflate_module modules/mod_deflate.so。apache中默認是deflate壓縮

(2)在虛擬主機裏面配置以下:

    

四、經過瀏覽器緩存數據內容

在網站中有一些資源,好比js文件,css文件,一些圖片文件,更新的頻率比較少。經過設置http的cache-control expires屬性來進行設置緩存,能夠設置緩存的文件類型,設置緩存的緩存週期

(1)打開apache的主配置文件(httpd.conf)開啓緩存模塊

    打開apache的expires擴展:LoadModule expires_module modules/mod_expires.so

    利用該擴展控制圖片,css,html等文件控制緩存是否緩存,及緩存聲明週期。

(2)配置選項設置

    ExpiresActive On     //開啓緩存設置

    //具體的針對文件類型設置緩存規則

    ExpiresDefault "<base> [plus] {<num> <type>}*"//默認設置
    ExpiresByType type/encoding "<base> [plus] {<num> <type>}*"//針對不一樣文件類型進行設置

    

(3)針對jpeg格式圖片緩存配置步驟:

    ①新建一個虛擬主機:②查看緩存效果:

 

(4)針對js文件配置緩存週期

    只須要把上圖中虛擬主機配置image/jpeg換成application/javascript

(5)針對某些文件,不讓他緩存,始終從服務器中獲取內容。好比不緩存gif文件。

    思路:打開apache主配置文件中header模塊,配置該選項:cache-control:no-store,must-revalidate

    具體步驟:

        ①在httpd.conf中開啓header模塊:LoadModule headers_module modules/mod_headers.so

        ②在虛擬主機裏面經過正則進行以下配置:

            

五、能夠把比較佔用流量的一些資源,單獨組建一個服務器

好比圖片服務器,視頻服務器等。

要注意:資源服務器的配置:

存儲資源的服務器:主要要求是硬盤的容量,讀寫速度。

能夠組建磁盤陣列。

raid0

raid1

磁盤陣列的存儲技術:

分佈存儲:至少是兩塊硬盤

複製存儲:至少是兩塊硬盤

六、花錢買帶寬

5、大存儲解決方案

一、緩存技術

經過緩存技術,達到不查詢數據庫或者少查詢數據庫的目的。

計算機的訪問速度,內存》硬盤文件》數據庫

緩存技術主要有:

磁盤緩存(頁面靜態化),把一個查詢數據庫的頁面變成一個不查詢數據庫的頁面

內存緩存:把常常查詢的數據保存到內存裏面,下次查詢數據時候直接在 內存裏面查詢。

(memcache/redis/mysql的memory引擎)

二、在設計表的時候,要知足3範式

第一範式是:原子性,字段不能再分割了。只要是關係型數據庫就自動知足第一範式:

數據庫的分類:

關係型數據庫:有行和 列的概念,二維表格。常見的關係型數據庫:mysql,sql server,oracle,db2,

非關係型數據庫(nosql)面向集合和 文檔的,沒有行和列的概念常見的有redis/mongodb等。

第二範式:在一個表中不能有徹底相同的記錄。能夠經過設置一個主鍵。

第三範式:表中的字段不能冗餘存儲。

三、要給表添加適當的索引:索引很是重要的,能夠提升查詢速度

常見索引有:主鍵索引,惟一索引,普通索引,全文索引,

四、要建立適當的存儲過程,函數,觸發器等

五、讀寫分離(主從服務器)

六、分表技術(垂直分割和水平分割)

垂直分割:

水平分割:

七、分區技術

把一個表的數據內容,在不一樣的 區域存儲

八、升級mysql服務器(添加配置:加大內容,64位)

九、要對sql語句進行調優

select * from tablename   該語句不要使用,要按需查詢。須要哪一個字段的數據,就查詢哪一個字段的數據。

十、對配置文件進行優化配置

好比配置mysql數據庫的併發量:

6、網頁靜態化的內容

主要有兩種:

真靜態:就是把一個動態(查詢數據庫)的頁面,轉換成一個靜態的頁面html頁面

    優勢: 1. 速度快 2. 安全性高 3. 利於seo

    缺點:就是佔有磁盤空間., 若是過大,對磁盤響應速度有影響

    在什麼狀況下,建議不要使用真靜態

  1. 頁面的數據更新頻繁,最好不要使用真靜態(好比股票,基金,等實時報價系統)
  2. 會生成海量頁面(好比大型論壇 bbs ,csdn)
  3. 查詢該頁面一次後,之後不再查詢該頁面.
  4. 不肯意被搜索引擎抓取的頁面.
  5. 訪問量小的頁面.

僞靜態:從形式上看url地址是一個靜態的頁面,實際上仍是要查詢數據庫的。

    好比http://www.abc.com/news-soprt-id100.html實際上對應http://www.abc.com/news.php?type=sport&id=100

一、網頁靜態化的使用原理

二、瞭解幾個概念

動態的網址:通常來講,該頁面有查詢數據庫的功能,好比後綴是:(php|asp|aspx|jsp)

特色:查詢數據庫,訪問速度慢,可能sql注入,不是很安全,不是利於seo

靜態的網址:通常來講就是html頁面。

特色:不查詢數據庫,訪問速度快,安全,利於seo

僞靜態網址:從形式上看是一個靜態網址,其實是一個動態頁面,

特色:查詢數據庫,安全,利於seo

好比:http://localhost/1028/demo.php/goods_id100.html

三、實現靜態化的方式

真靜態實現方式:

(1)經過ob緩存技術來實現

    ①概念:什麼是ob緩存:

        ob緩存:output_buffering:輸出緩存,咱們請求一個php頁面,其實是經過三個緩存的。

        ob緩存(若是開啓)---》程序緩存------》瀏覽器緩存,要注意:程序緩存和瀏覽器緩存必須存在的。

        

    ②如何開啓ob緩存:

        第一種方式:經過ob_start()函數,只對當前頁面有效

        第二種方式:經過php.ini文件中:

    ③學習幾個函數來說解

        ob_clean();清除ob緩存裏面的數據,並不關閉ob緩存

        ob_end_clean():清除ob緩存裏面的數據,並關閉ob緩存

        ob_flush();把ob緩存裏面的數據刷新到程序緩存,並不關閉ob緩存。

        ob_end_flush():把ob緩存裏面 的數據移動到程序緩存,並關閉ob緩存

        ob_get_contents();獲取ob緩存裏面數據

        

    ④利用ob緩存完成一個真靜態案例

        思路:判斷該頁面對應的靜態頁面,是否存在,若存在的直接訪問靜態頁面,不存在則經過數據庫查詢出數據,並生成一個靜態頁面。

        具體的代碼:

        <?php

        header("content-type:text/html;charset=utf-8");

        $filename="index.html";

        //思路:判斷該頁面對應的靜態頁面,是否存在,

        if(file_exists($filename)){

            include $filename;exit;

        }

        //鏈接數據庫的操做:

        $conn = mysql_connect("localhost",'root','root');

        mysql_query("use itdede");

        mysql_query("set names utf8");

        $sql="select title from dede_archives limit 10";

        $res = mysql_query($sql,$conn);

        $list=array();

        while($row=mysql_fetch_assoc($res)){

            $list[]=$row;

        }

        ob_start();

        //echo 'ok';

        ?>

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

        <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">

        <head>

        <title>新建網頁</title>

        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <meta name="description" content="" />

        <meta name="keywords" content="" />

        <script type="text/javascript"></script>

        <style type="text/css"></style>

        </head>

        <body>

            <table width="500" border="1" >

                <tr><td>電影名稱</td><td>操做</td></tr>

                <?php foreach($list as $v){?>

                  <tr><td><?php echo $v['title']?></td><td>電影 詳情</td></tr>

                <?php }?>

            </table>

        </body>

        </html>

        <?PHP

        $contents = ob_get_contents();

        file_put_contents($filename,$contents);

        ?>

    ⑤案例擴展,要給生成對應的靜態頁面一個有效期

    判斷條件:對應的靜態頁面要存在,並且在有效期內,就能夠直接讀取靜態頁面。

    如何計算在有效期內:對應靜態頁面的修改的時間戳+有效期>當前的時間戳

    filemtime($filename)+300>time();

    假如一個網站併發是1000,不緩存的話。60秒以內查詢數據庫多少次。        60000次

    假如一個網站併發是1000,緩存60秒的話,60秒以內查詢數據庫多少次。    1次

    具體的代碼:

    <?php

    header("content-type:text/html;charset=utf-8");

    $filename="index.html";

    //思路:判斷該頁面對應的靜態頁面,是否存在,

    if(file_exists($filename) &&  filemtime($filename)+10>time()){

        include $filename;exit;

    }

    //鏈接數據庫的操做:

    $conn = mysql_connect("localhost",'root','root');

    mysql_query("use itdede");

    mysql_query("set names utf8");

    $sql="select title from dede_archives limit 10";

    $res = mysql_query($sql,$conn);

    $list=array();

    while($row=mysql_fetch_assoc($res)){

        $list[]=$row;

    }

    ob_start();

    echo time();

    ?>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">

    <head>

    <title>新建網頁</title>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <meta name="description" content="" />

    <meta name="keywords" content="" />

    <script type="text/javascript"></script>

    <style type="text/css"></style>

    </head>

    <body>

        <table width="500" border="1" >

            <tr><td>電影名稱</td><td>操做</td></tr>

            <?php foreach($list as $v){?>

              <tr><td><?php echo $v['title']?></td><td>電影 詳情</td></tr>

            <?php }?>

        </table>

    </body>

    </html>

    <?PHP

    $contents = ob_get_contents();

    file_put_contents($filename,$contents);

    ?>

    該案例重點是:理清以下思路便可

    //思路:判斷該頁面對應的靜態頁面,是否存在,

    if(file_exists($filename) &&  filemtime($filename)+10>time()){

        include $filename;exit;

    }

(2)經過模板替換技術來實現

    ①新建一個模板文件,tpl.html:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">

    <head>

    <title>新建網頁</title>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <meta name="description" content="" />

    <meta name="keywords" content="" />

    <script type="text/javascript"></script>

    <style type="text/css"></style>

    </head>

    <body>

        <h1>新聞的詳情頁面</h1>

        <h3>%title%</h3>

        <hr>

        <div>%content%</div>

    </body>

    </html>

    ②建立生成的靜態頁面的路徑,建立數據庫中filename字段的存儲路徑

    <?php

    $act = isset($_GET['act'])?trim($_GET['act']):"";

    $conn = mysql_connect("localhost",'root','root');

    mysql_query("use php");

    mysql_query("set names utf8");

    //添加新聞

    if($act=='add'){

        //接收表單提交過來數據

        $title = $_POST['title'];

        $content = $_POST['content'];

        $sql="insert into news(title,content) values('$title','$content')";

        $res = mysql_query($sql,$conn);

        $id = mysql_insert_id($conn);

        if(!$id){

            die("添加失敗");

        }

       $dir = date("Ym/d");

       $file="news_id".$id.'.html';//表示生成的靜態文件的名稱

       $dir_path="../a/".$dir;

       //要判斷$dir_path目錄是否存在,若是不存在則建立。

       if(!is_dir($dir_path)){

            mkdir($dir_path,0777,true);

       }

      $filename =$dir_path.'/'.$file; //生成的靜態文件的完整路徑;

      $filename_path="./a/".$dir.'/'.$file;//存儲到數據庫filename字段中的靜態頁面的路徑: 

        //打開模板文件

        $tpl_ph=fopen('tpl.html','r');

        //建立對應的靜態頁面。

        $file_ph=fopen($filename,'w');

        //完成替換

        //feof()函數,返回文件指針是否到文件的末尾,若是到則返回的真。

        while(!feof($tpl_ph)){

            $row=fgets($tpl_ph);//fgets()函數是讀取一行內容

            $row=str_replace('%title%',$title,$row);//str_replace()該函數返回替換以後的結果

            $row=str_replace('%content%',$content,$row);

            fwrite($file_ph,$row);//把替換以後的內容,寫入到$filename文件中。

        }

        fclose($tpl_ph);//關閉文件指針

        fclose($file_ph);//關閉文件指針

        //把生成的對應靜態頁面的路徑存儲到數據庫裏面的filename字段

       $sql="update news set filename='$filename_path' where id=$id";

       $res =  mysql_query($sql);

       $num = mysql_affected_rows($conn);

       if(!$num){

            die("失敗");

       }

        echo '添加成功';

        echo "<a href='index.php'>返回首頁</a>";

    }

    ?>

    ③新建一個makehtml.php頁面完成,前臺首頁的生成。

    <?php

    $conn = mysql_connect("localhost",'root','root');

    mysql_query("use php");

    mysql_query("set names utf8");

    $sql="select id,title,filename from news";

    $list=array();

    $res = mysql_query($sql,$conn);

    while($row=mysql_fetch_assoc($res)){

        $list[]=$row;

    }

    ob_start();

    ?>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">

    <head>

    <title>新建網頁</title>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <meta name="description" content="" />

    <meta name="keywords" content="" />

    <script type="text/javascript"></script>

    <style type="text/css"></style>

    </head>

    <body>

        <h1>新聞列表頁面</h1>

        <table width="500" border="1">

            <tr><td>新聞標題</td><td>新聞詳情</td><td>操做</td></tr>

            <?php foreach($list as $v){?>

            <tr><td><?php echo $v['title']?></td><td><a href="<?php echo $v['filename']?>">新聞詳情</a></td><td>操做</td></tr>

            <?php }?>

            </table>

    </body>

    </html>

    <?php

    $str = ob_get_contents();

    file_put_contents("../index.html",$str);

    ob_clean();

    echo "首頁已經已經生成  <a href='../index.html'>返回前臺首頁</a>";

    ?>

僞靜態實現方式:

(1)經過正則表達式,匹配替換   

    <?php

    $path_info = $_SERVER['PATH_INFO'];//獲取到 地址中:news_id1.html

    $patt = '/news_id(\d{1,3})\.html$/';

    preg_match($patt,$path_info,$a);//$a用於存儲匹配到的內容。

    $id = $a[1];

    $conn = mysql_connect("localhost",'root','root');

    mysql_query("use php");

    mysql_query("set names utf8");

    $sql="select title,content from news where id = $id";

    $res = mysql_query($sql,$conn);

    $row=mysql_fetch_assoc($res);

    ?>

(2)經過服務器的rewrite機制

    ①打開apahce的主配置文件(httpd.conf),開啓rewrite模塊:

        LoadModule rewrite_module modules/mod_rewrite.so

    ②請求abc.html轉換成請求123.php,虛擬機配置以下:

        方法一: 

        方法二:新建一個.htaccess文件配置重寫規則,要注意:要使該文件有效,則必須在虛擬主機裏面設置。AllowOverride All

        

    ③虛擬機中經常使用配置

        #配置是否顯示文件目錄:[indexes|none]

            Options indexes FollowSymLinks  //配置顯示文件目錄,若是沒有配置歡迎頁面 

            若是配置成 options  none

        #配置錯誤跳轉頁面。主要防止用戶請求的頁面不存在,若是用戶訪問的頁面不存在,則給一個友好的提示

          

        #配置網站的歡迎頁面:DirectoryIndex abc.html

    ④使用rewrite機制利用referer頭信息完成防盜鏈

        

7、apache併發工具測試

一、ab.exe測試

咱們作好一個網站後,要測一下當前網站架構,可以支持併發狀況。

測試工具:

可使用apache自帶的一個工具

併發測試的工具備不少,經常使用的壓力測試軟件:

ab                 : 優勢:能夠模擬各類請求    缺點:最大隻能支撐1000的併發

webbench:   優勢:30000萬的 併發   缺點:只能模擬GET請求

loadrunner :  很是專業的壓力測試軟件

winrunner:專業的壓力測試軟件。

ab.exe  -n訪問的總的次數  -c用戶併發數量(有多少人同時訪問)網站的地址。

測試結果:

請求的時間越短越好。

把同時請求的人數調整到600則出現了問題。實際上,在默認狀況下,apahce最高支持150併發。

二、要調整apache的併發配置,要清楚處理多併發的方式

首先搞清楚當前apache是什麼MPM(多路處理模塊), 通俗講就是apache處理多併發的方式,

常見的有三種

(1)perfork(預派生模式)

(2)worker(工做者模式)

(3)winnt模式(windows下默認的模式)

三、如何知道,當前apache服務器是使用哪種方式處理併發

四、如何配置MPM(多路處理模塊)的問題,調整最大的併發量。

(1)打開apache的配置文件 httpd.conf,開啓多路處理模型

(2)打開extra目錄下面的httpd-mpm.conf輔助配置文件。

(3)根據當前apache的mpm的方式進行調整以下:

測試以下:

還要注意:雖然調整成了1000可是測試沒法完成,緣由是,還要和當前服務器的環境配置有關係,並非說調整成1000,就能支持到1000.

五、通常在linux系統下面,apache的mpm方式是預派生模式。有一個推薦的配置

在linux下通常是perfor模式

給你們一個合理的建議配置. 對大部分網站,中型網站,配置:

<IfModule mpm_prefork_module>
              StartServers         5      #
預先啓動
              MinSpareServers      5
              MaxSpareServers      10  #
最大空閒進程
              ServerLimit          1500   #
用於修改apache編程參數
              MaxClients           1000   #
最大併發數
              MaxRequestsPerChild  0  #
一個進程對應的線程數,對worker    更有效果。若是是0則不讓進程死掉。

</IfModule>

若是你的網站pv值  百萬

ServerLimit          2500   #用於修改apache編程參數
MaxClients           2000   #
最大併發數

總結:

1大型網站的標準(pv,uv,獨立ip)

二、帶來的問題:大併發,大流量,大的存儲

三、大併發解決。網站服務器架構調整(負載均衡,集羣,數據庫的讀寫分離)

四、大流量的解決:防止被盜鏈,啓用壓縮,啓用緩存,減小http請求,增長帶寬。

五、大存儲的解決:緩存,表要符合三範式,添加索引,存儲過程,對sql語句調優,分表和分區,服務器的配置增強。

六、靜態化,真靜態,僞靜態,

真靜態實現方式:ob緩存,模板替換技術

僞靜態:正則替換,rewrite機制。

七、ab.exe 工具使用。

ab.exe –n 訪問的總的次數  -c併發量   頁面地址。

mpm(多路 處理模塊)併發的處理方式

常見的有:預派生,工做者,winnt,

如何查看本身的mpm是哪一種模式:httpd.exe –l

相關文章
相關標籤/搜索