Shoutcast radio status
ปัญหาเกิดมาจาก script สำหรับตรวจสอบสถานะและแสดงชื่อเพลงที่กำลังเปิดอยู่นั้นกิน CPU time เยอะมาก และ script นั้นยังถูกกำหนดให้ refresh ทุก 30 วินาที เมื่อมีคนเปิดฟังวิทยุพร้อมกับดูสถานะเป็นจำนวนมาก จะทำให้เกิดปัญหากับ CPU load
เลยศึกษา script นั้นดูและเปลี่ยนวิธีการเพื่อไม่ให้เกิด CPU load
แนวทางการทำงานของ script เดิมที่เป็นอยู่
- จะดึงข้อมูลของ Shoutcast จาก host ด้วย fsocket method GET จำนวน 2 ครั้ง คือ ชื่อเพลง กับจำนวนคนฟัง โดยกำหนด timeout ไว้ที่ 6 วินาที
- ตัดข้อความที่ไม่ต้องการออกและแยกแยะเอาข้อความที่ต้องการออกมา
- แสดงผลในหน้าเว็บโดยให้ refresh ทุก ๆ 30 วินาที
ปัญหาที่เกิดขึ้นคือ
- การดึงข้อมูลผ่าน fsocket แต่ละครั้งใช้เวลาพอสมควรเนื่องจาก script อยู่คนละที่กับ Shoutcast server
- เกิด CPU load ในกระบวนการไหนไม่แน่ใจ
- จำนวน request ที่เยอะมากเกิดจาก จำนวนคนฟังหรือหน้าเว็บที่เปิดดูสถานะ x 2 คร้ง/นาที เช่น 150x2=300 ครั้ง/นาที = 5 ครั้ง/วินาที ทำ script ทำงานไม่ทัน
แนวทางใหม่ที่คิดคือ
แทนที่จะให้ทุกคน request แล้วต้องอ่านข้อมูลทุกครั้ง ก็ให้ script ทำงานอัตโนมัติทุก ๆ 30 วินาที ไปดึงข้อมูลจาก Shoutcast แล้วบันทึกเก็บไว้ในไฟล์ แล้วให้ทุกคนอ่านจากไฟล์นี้แทน
ดูตัวอย่าง script ได้จากด้านในนะครับ
ผมเลยปรับแก้โปรแกรมเป็นตามนี้
<?php
/**
* Radio configuration
*
*/
//include ("shoutcast_stat_config.php");
$radiohost= 'xxx.xxx.xxx.xxx'; // server ip address
$radioport= '8006'; // server port
$radioofflinemsg='Offline';
$radiopassword='password here'; // password
$output_file='/{path/to/public_html}/radiostatus.html';
$ret='';
$timeout='6';
$listenlink='http://'.$radiohost.':'.$radioport.'/listen.pls';
$radio= @fsockopen($radiohost, $radioport, &$errno, &$errstr, $timeout);
if (!$radio) {
$success='2';
$ret.=$radioofflinemsg; // Radio is offline, so display message
die();
}
//Connect to the server
if ($success!='2') { //If Connection
fputs($radio,"Get /7.html HTTP/1.0\r\nUser-Agent: XML Getter (Mozilla Compatible)\r\n\r\n"); //Get 7.HTML
while (!feof($radio)) {
$page.=fgets($radio, 1000);
}
$page=ereg_replace('.*<body>', '', $page);
$page=ereg_replace('</body>.*', ',', $page);
$numbers=explode(',',$page);
$currentlisteners=$numbers[0];
$connected=$numbers[1];
//Open Connection
$fp=fsockopen($radiohost, $radioport, &$errno, &$errstr, 3);
if (!$fp) { //If Connection
$success2='2';
$ret.='The Radio Server Is Currently Offline';
}
if ($success2!='2') { //If Connected
fputs($fp,"Get /admin.cgi?pass=$radiopassword&mode=viewxml HTTP/1.0\r\nUser-Agent: XML Getter (Mozilla Compatible)\r\n\r\n");
while(!feof($fp)) {
$page.= fgets($fp, 1000);
}
$security=explode(',',$page);
$security=explode('401',$security[7]);
$u='0';
while ($security[$u]!='') {
if ($security[1]!='') {
$ret.='Incorrect Server Password';
die;
}
$u++;
}
//Array
$loop=array('AVERAGETIME', 'SERVERGENRE', 'SERVERURL', 'SERVERTITLE', 'SONGTITLE', 'SONGURL', 'IRC', 'ICQ', 'AIM', 'WEBHITS', 'STREAMHITS', 'INDEX','LISTEN', 'PALM7', 'LOGIN', 'LOGINFAIL', 'PLAYED', 'COOKIE', 'ADMIN', 'UPDINFO', 'KICKSRC', 'KICKDST', 'UNBANDST', 'BANDST', 'VIEWBAN', 'UNRIPDST', 'VIEWRIP', 'VIEWXML', 'VIEWLOG', 'INVALID'); //Define All The Variables To Get (Delete Any Ones You Don't Want)
$y='0';
while ($loop[$y]!='') {
$pageed=ereg_replace(".*<$loop[$y]>", "", $page); //Extract Data
$phpname=strtolower($loop[$y]);
$$phpname=ereg_replace("</$loop[$y]>.*", "", $pageed); //Finish Extracting Data
if($loop[$y]==SERVERGENRE || $loop[$y]==SERVERTITLE || $loop[$y]==SONGTITLE)
$$phpname=urldecode($$phpname);
$phpname = $phpname;
$y++;
}
}
$wordconnected=$connected=='1'?'yes':'no';
$peaklisteners=$numbers[2];
$maxlisteners=$numbers[3];
$reportedlisteners=$numbers[4];
$song=$numbers[6];
$bitrate=$numbers[5];
$site=explode(' ', $servertitle);
$title=explode('DJ',$servertitle);
if ($wordconnected=='no' && $connected=='0') {
$ret.=$radioofflinemsg;
} else {
$ret.='<div align="center">'.$reportedlisteners.'/'.$maxlisteners.' Listeners<br />Song: '.$numbers[6].'<a href="'.$listenlink.'"></a></div>';
//Close Connection
fclose($radio);
}
}
$body='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-EN">
<head profile="http://gmpg.org/xfn/11">
<title>Shoutcast Stat</title>
<meta http-equiv="Content-Type" content="text/html; charset=tis-620" />
<meta http-equiv="refresh" content="30" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
</head>
<body style="background-color:#FB803F;">
'.$ret.'
</body>
</html>';
$fh=fopen($output_file,'w');
fwrite($fh, $body);
fclose($fh);
?>
ผลลัพที่ได้มาจะอยู่ในไฟล์ radiostatus.html ซึ่งต้องบันทึกไว้ในโฟลเดอร์ที่สามารถเปิดผ่าน url ได้
ขั้นตอนต่อไป คือ ทำให้ script นี้ทำงาน auto ทุก ๆ 30 วินาที จึงใช้ crontab เข้ามาช่วย ปัญหาคือ crontab มีหน่วยเล็กที่สุดในการทำงานคือ นาที ข้อมูลจาก อาจารย์กู ได้ Slicehost Forum - Is It Possible To Run A Cron Task Every 30 Seconds มาว่า ให้ทำ script ตัวหนึ่งที่จะเรียก script ที่ต้องการ run แล้วให้ sleep 30 วินาที แล้วเรียก script ที่ต้องการ run อีกครั้ง แล้วกำหนดให้ crontab ทำงาน script ทุก 1 นาที
ก็เลยสร้างไฟล์ radiofetch.sh ให้มีคำสั่งดังนี้
#!/bin/sh
/usr/local/bin/php /{path/to/public_html}/radiofetch.php &
sleep 30
/usr/local/bin/php /{path/to/public_html}/radiofetch.php &
แล้วสร้าง crontab
crontab -e
ป้อนค่า
* * * * * /{path/to/script}/radiofetch.sh
ผลลัพท์ที่ได้จะอยู่ที่ไฟล์ radiostatus.html คราวนี้ก็ให้เรียกไฟล์ radiostatus.html ไปแสดงผลแทน
!!!! โย่ CPU load หายเกลี้ยงเลย.....
หมายเหตุ - script นี้ผมไม่ได้เขียนเอง แต่เป็น script ที่มีแจกกันอยู่ในอินเตอร์เน็ต แต่ไม่ไม่รู้ว่าใครเขียนเพราะ script ที่ผมได้มานั้นไม่มีส่วนหมายเหตุของชื่อคนเขียน หากใครมีข้อมูลเกี่ยวกับผู้เขียน ช่วยบอกด้วยนะครับ จะได้ใส่ไว้ในเครดิตและอ้างอิงกลับให้
Relate topics
- nginx - ถึงเวลาซะที
- PHP PDO using
- การเก็บ JSON ใน MySQL ด้วย PHP
- macOS 12 Monterey: Web Server Setup/Apache/MariaDB/PHP Multiple Versions
- Ubuntu Server Installation
- Bug : isset($body['location']) ดันเป็นจริงเมื่อ $body ไม่ใช่ array
- MVC - แนวคิดเกี่ยวกับ MVC
- FTP chmod
- Hash & Salt
- Regular Expression - ยังไง ยังไง ก็ใช้ไม่ถูกสักที
- PHP : How to show Adsense on web
- PHP : Send SMS by smsgateway.com
- Directadmin PHP path
- Application Programming Interface (API)
- IP Camera snapshot
- Enable Exif
- Make Ubuntu to be a web server (LAMP)
- SELECT - OnChange
- Class fpdf กับภาษาไทย
- มาแล้ว PHP 5.3 พร้อมกับ error ที่ไม่คาดฝัน
Mike (Not Member)