簡述 SiteStates 開發規劃

我最近寫了一隻小程式,原本是今年學期末就要寫好的,因為早就答應人家了,不過我暑假(暑修)實在太忙加上想說既然要寫,就寫的完整一點,所以拖到現在才完成這隻程式。

SiteStates 是個 多功能 簡單的計數器, 也可以稱為探測器 或是 間諜,程式部份大概幾百行而已,所以只能算是小玩具,它主要是可以統計 訪客人數線上人數 以及顯示 到訪紀錄

其實要寫一個會動的訪客記錄器,對一般會寫的人來說,大概是一小時或是幾十分鐘的事情。因為寫出這類的東西並不困難,但是週邊一堆困擾的事情,倒是很麻煩,從介面的修改,資料庫的規劃(和以後的可擴充性)..等等。

不過在寫這隻程式的時候,我還是遇到了一些瓶頸,主要是牽扯到效能的問題,這邊和大家分享一下。

取得同時在線人數的方法?
建立一個 table ,裡面設定三個欄位, id 、 ip 以及 lastvisit 。id 是使用者的代號,ip 則是訪客來源, lastvisit 則是 unix 的 timestamp 。如此遇到訪客的時候,先檢查有沒有存在,如果沒有,就 INSERT 一筆資料進去,如果存在,就把原本的那筆資料 UPDATE ,然後每次跑這個 script ,都先把 timestamp 過期的 records 刪除。

我曾經在 PTT 的 PHP 板提出作法如下

建立一個 table 叫做 online 然後以下欄位:

serial - 序號.自動增加
id - 屬於哪個站台的紀錄
ip - 進入的使用者來源
lastvisit - 進入時間

首先刪除所有逾時的人 (假設 300 秒逾時)
$sql = "DELETE FROM online WHERE unix_timestamp() - lastvisit >= 300 AND id = '$id'";

使用者是否造訪過
$sql = "SELECT id FROM online WHERE ip = '$ip' AND id = '$id'";

計算 mysql_query($sql) 是為 0

如果是 0 的話,插入一筆新的資料:
$sql = "INSERT INTO online (id, ip, lastvisit) VALUES ('$id','$ip',unix_timestamp())";

如果不是 0 的話,把 time stamp 延後
$sql = "UPDATE users_online SET lastvisit = unix_timestamp() WHERE id = '$id' AND ip = '$ip'";

最後計算該站台有多少人
$sql = "SELECT count(id) FROM online WHERE id='$id'";

另外有位 allanshen 兄,回覆了一個更好的作法:

建立一個 table - online 有3個欄位 id、ip、lastvisit,id 跟 ip 合併設定為 unique key
刪除所有逾時的人跟您的方式一樣
然後使用者到訪時用
$sql = "REPLACE INTO online (id,ip,lastvisit) VALUES ('$id','$ip',unix_timestamp())";

計算人數一樣用 $sql = "select count(id) FROM online where id='$id'";

這樣跟您原來的方式省了一次 select
儘在此再次謝謝他的意見。

取得 PageRank 的方法?
Google Code 裡面有一個叫做 Popstats 的函式庫,目前是可以動的,根據 Wildcat 哥的可靠消息, PHP Google PageRank Calculator 已經無法運作了。

到訪紀錄的 Maintain?
這是我最頭痛的事情,不過還好也是迎刃而解。原本我想了複雜的方法,但是 wildcat 哥和我說了個比較簡單的作法:

wildcat 說:

喔,我會建議你把來源用 text or blob 存,反正一百筆大概也才 15x100 = 1600 , + 100(分隔號) = 1600 bytes,這種大小的字串給 php 處理其實非常非常迅速…(大概就長這樣 192.168.100.100|192.168.200.200|.... ) 要讀出來的時候再把它 split or explode 就好了。

實際作法大致如下:

/*
建立一個叫做 users 的 table :
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL auto_increment,
  `url` text NOT NULL,
  `password` varchar(32) NOT NULL,
  `from_ip` text,
  UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
*/

function add_ip_to_user($id, $ip) /* 新增一筆 ip 紀錄 */
{
    require('database.php');
    $sql = "SELECT from_ip FROM users WHERE id = $id";
    $result = lab3_query($sql);
    list($from_ip) = mysql_fetch_row($result);

    $array = array();
    $array = unserialize($from_ip);

    $size  = count($array);

    if($from_ip == '')
    {
        $array[0][0] = gethostbyaddr($ip);
        $array[0][1] = date('Y-m-d H:i:s');
        $array[0][2] = $ip;
    }
    else
    {
        $array[$size][0] = gethostbyaddr($ip);
        $array[$size][1] = date('Y-m-d H:i:s');
        $array[$size][2] = $ip;
    }

    if($size >= 500) /* 最多幾筆 */
        array_shift($array);

    $from_ip = serialize($array);

    $sql = "UPDATE users SET from_ip = '$from_ip' WHERE id = $id";
    lab3_query($sql);
}

用 serialize()、unserialize() 或是 implode()、 explode() 來搭配存取 from_ip 這個 text 欄位。以上大概是比較需要討論的地方,其他需要具備的條件就是對於繪圖函式的使用、陣列處理、以及一般字串處理和網路函式(像是取得 IP 和 DNS 反解)的應用,另外 CSS 和 HTML 的技術則是基本必須具備的,這邊著重於 PHP 和資料庫處理的部份,所以使用者介面的部份我就不提了。

如果有建議或是問題也很歡迎在此提出,非常感謝! 😮

Posted in computers
7 comments on “簡述 SiteStates 開發規劃
  1. wildcat says:

    其實我會建議不要在寫入資料庫時就做gethostbyaddr,
    遇到沒辦法反查的ip時寫入的動作就被lock在那邊 XD
    應該是讀出來要顯示的時候再去作就好了 :p

  2. roga says:

    還OK啦..

    查不出來它就直接 return IP 囉 😛

  3. 雖然我不會寫這個程序,
    直接去你計算器網頁拿來用了。
    我們馬來西亞整個“衣服部落格”的使用者都非常感謝你!!

  4. roga says:

    衣服部落格的管理者您好:

    不用客氣,很高興有這個機會能幫上忙,如果有程式上的問題或是系統方面的心得,也很歡迎討論交流,我對這些都相當有興趣 😛

  5. 野貓 says:

    重點是等他 reuturn 是要時間的 XD

  6. roga says:

    之前 PageRank = 0 的時候沒有 cache 的才慘。她會先去跟 Google 問三次,如果都 fail 才 return FALSE 。

    一整個速度被拖下來,還好我把程式改寫一下,才解決這問題.. :mrgreen:

  7. roga says:

    我發現在

    if($size >= 500) /* 最多幾筆 */
    array_shift($array);

    這邊有問題.. = =

1 Pings/Trackbacks for "簡述 SiteStates 開發規劃"
  1. […] 1. SiteStates 網站 2. SiteStates 計數器 探測器 間諜 小玩具 訪客人數 in roga’s blog. « 新電腦 […]

Leave a Reply

Your email address will not be published.