웹마스터 팁
page_full_width" class="col-xs-12" |cond="$__Context->page_full_width">
cron을 이용해 윈앰프 방송정보를 빠르게 분석.
2002.01.15 01:32
http://www.topcj.com탑시제이 http://topcj.com 방송국 기획을 맡고 있는 Romeo입니다.
금번 홈피 개발을 하면서 윈앰방송 정보를 소켓을 열어 가져오는 소스에 속도의 문제를 발견했지요.
우리 홈피는 모든 페이지에 위 함수를 이용해 방송정보를 업어왔는데, 이놈의 소켓 접속때문에 페이지가 늦게 뜨거나 가끔 타임아웃 걸려버리는 사고가 발생하고 했지요.
그래서 계정에서 사용하는 cron을 이용해 샤웃캐스트의 정보를 1분에 한번씩 받아와 파일로 저장하고 홈피에서는 이때 생성된 파일을 분석하여 속도를 극대화시키는 기법을 소개합니다.
적용결과 확실히 빨라짐을 느껴 광분했습니다.
물론 운이 없으면 최고 1분간의 오차가 있기는 하지만 버벅대는 홈피 보는것보다는 나을 수도 있다는 생각입니다. ㅡ,.ㅡ
1. 계정에서 cron, lynx 사용가능한지 알아보기
cron은 유닉스환경에서 특정 명령을 주기적으로 실행시키는 명령입니다.
[topcj@ns share]$ ps -ax |grep crond -> 크론데몬 확인
800 ? S 0:00 crond -> 이부분이 있으면 OK! 없으면 crond실행이 선행되어야 함(여기서는 다루지 않음)
19844 pts/2 S 0:00 grep crond
lynx는 텍스트기반의 쉘 부라우자입니다. -_-
[topcj@ns share]$ lynx --help -> 머라고 나오면 준비 OK! 아니면 깔아야함(이것도 다루지 않음)
위 두가지가 정상적으로 준비 되었다면 환경은 OK입니다.
그럼 주기적으로 윈앰정보를 받아올 cron셋업을 해보죠.
[topcj@ns share]vi schedule.cron
* * * * * lynx -source http://cast.topcj.com:2880/ > /home/topcj/public_html/cast_status.cron.html
http://cast.topcj.com:2880 에서 보이는 방송정보를 1분마다 한번씩 html소스로 받아 지정 경로/파일에 지정합니다.
간격은 얼마든지 지정 가능하나 방송국에선 1분 말고는 선택의여지가 없겠네요. 자세한건 각종 cron사용법 참조.
[topcj@ns share]crontab schedule.cron
위 명령으로 지정한 스케줄을 실행시킵니다.
1분에 한번씩 위에서 지정한 /home/topcj/public_html/cast_status.cron.html 파일이 업뎃 되는것을 볼 수 있습니다. (처음 1분은 암것도 없습닭 -_-)
성공적이라면 어떻게 해야하는지 아실겁니다.
소켓 접속대신 이 파일을 받아서 분석하면 되는것이죠. 순식간입니닭.
변경된 정보 분석 함수를 써보까요?
급하게 수정한터라 엉성하기 그지 없습니다. 변경의 여지 다분합니다. ㅡ,.ㅡ
참고로 crond에 문제가 생겨 업뎃이 되지 않고 있을때는 자동으로 원래의 소켓 접속으로 전환됩니다. 걍 생각없이 쓰시다가 cron이 잘 대나 확인해 주시면 대게찌욤~
두번째 참고로 기본 소스는 이곳에 올려진 어느 분의 작품중 하나인데요.
생성된 파일의 경로를 담는 $STAT_CRON변수와 처음으로 나오는 if문 부터 else 나오기 직전의 블럭까지 추가된 것 말고는 원래 그대로입니다.
http://topcj.com 널러 오시묜 방가이 맞이하겠슴닭!!
m(__)m
[쏘쓰]
$STAT_CRON = "/home/topcj/public_html/cast_status.cron.html";
function get_scinfo($address) {
global $STAT_CRON;
if(filemtime($STAT_CRON)>=time()-60) { // 1분전에 정보파일이 업뎃 되었으면 파일 읽기 아니면 소켓접속
$fp = fopen($STAT_CRON,'r');
while(!feof($fp)) // 쩝.. 모하러 이걸썼나.. readfile()이 있는데.. _-_
$temp .= fgets($fp, 1024);
fclose($fp);
} else {
$url_temp = explode(":",$address); // 콜론(:) 기준 분리해 배열에 저장
$url = $url_temp[0]; // 주소 분리
$port = $url_temp[1]; // 포트 분리
$fp = fsockopen($url, $port, &$errno, &$errstr, 5); // 소켓 연결
if($fp) { // 연결 성공시
fputs($fp,"GET /index.html HTTP/1.0nUser-Agent: Mozilla/4.0nn"); // 헤더 보냄
while(!feof($fp)) $temp .= fgets($fp,1024); // 파일이 끝날때까지 1024바이트씩 가져옴
fclose($fp);
}
}
// 접속 해제
//------------------------------------------------------------------------------// 가공시작
$keyword = array( // 찾을 값 (2차원 배열)
array("version" => "SHOUTcast Server Version"),
array("server" => "Server Status:"),
array("stream" => "Stream Status:"),
array("peak" => "Listener Peak:"),
array("time" => "Average Listen Time:"),
array("title" => "Stream Title:"),
array("genre" => "Stream Genre:"),
array("url" => "Stream URL:"),
array("icq" => "Stream ICQ:"),
array("aim" => "Stream AIM:"),
array("irc" => "Stream IRC:"),
array("song" => "Current Song:"),
);
$size = sizeof($keyword); // 배열의 크기 구함
$temp = strip_tags( // 4) 모든 태그 제거
implode("n<tr", // 3) n<tr 문자열로 다시 결합
explode("<tr", // 2) <tr 기준으로 분리 -> 배열값
str_replace(" "," ",$temp)))); // 1) 를 공백으로 바꿈
for ($i=0; $i<$size; $i++) { // 배열의 크기만큼 반복
$t_key = array_keys($keyword[$i]); // 키값을 가져옴
$t_key1 = $t_key[0]; // 처음키
$t_key2 = $keyword[$i][$t_key1]; // 키에 해당하는 값을 가져옴
$address = strpos($temp,$t_key2); // 키에 해당하는 위치값 구함
if ($address) { // 위치값이 있을 경우
$start = $address+strlen($t_key2); // 시작위치값 저장 (+길이)
$end = $start; // 시작위치값 저장 (증가치)
while(substr($temp,$end,1)!="n") $end++; // 다음줄 찾기 전까지 반복
$temp2[$t_key1] = trim(substr($temp,$start,$end-$start)); // 찾은 결과값 출력
if ($t_key1=="aim") $temp2[$t_key1] = urldecode($temp2[$t_key1]); // AIM은 디코드
}
}
//------------------------------------------------------------------------------// 가공끝
$stream = explode(" ",$temp2[stream]); // stream 문자열 공백 기준 분리
$temp2[speed] = trim($stream[4])." ".trim($stream[5]); // 방송속도 : 4,5번째 요소 가져옴
$temp2[listen] = trim($stream[7]); // 청취자 : 7번째 요소
$temp2[maxlisten] = trim($stream[9]); // 최대청취인원 : 9번째 요소
$temp2[unique] = str_replace("(","",trim($stream[11])); // 청취자 : 11번째 요소 (동일 IP 제외)
$temp2[time] = str_replace("h","시간",str_replace("m","분",str_replace("s","초",$temp2[time]))); // 시간,분,초 변환
if ($temp2[server]=="Server is currently up and public.") $temp2[air] = 1; // 방송중
elseif ($temp2[server]=="Server is currently down.") $temp2[air] = 0; // 방송안함
else $temp2[air] = -1; // 찾지 못함
return $temp2; // 값 반환
}
금번 홈피 개발을 하면서 윈앰방송 정보를 소켓을 열어 가져오는 소스에 속도의 문제를 발견했지요.
우리 홈피는 모든 페이지에 위 함수를 이용해 방송정보를 업어왔는데, 이놈의 소켓 접속때문에 페이지가 늦게 뜨거나 가끔 타임아웃 걸려버리는 사고가 발생하고 했지요.
그래서 계정에서 사용하는 cron을 이용해 샤웃캐스트의 정보를 1분에 한번씩 받아와 파일로 저장하고 홈피에서는 이때 생성된 파일을 분석하여 속도를 극대화시키는 기법을 소개합니다.
적용결과 확실히 빨라짐을 느껴 광분했습니다.
물론 운이 없으면 최고 1분간의 오차가 있기는 하지만 버벅대는 홈피 보는것보다는 나을 수도 있다는 생각입니다. ㅡ,.ㅡ
1. 계정에서 cron, lynx 사용가능한지 알아보기
cron은 유닉스환경에서 특정 명령을 주기적으로 실행시키는 명령입니다.
[topcj@ns share]$ ps -ax |grep crond -> 크론데몬 확인
800 ? S 0:00 crond -> 이부분이 있으면 OK! 없으면 crond실행이 선행되어야 함(여기서는 다루지 않음)
19844 pts/2 S 0:00 grep crond
lynx는 텍스트기반의 쉘 부라우자입니다. -_-
[topcj@ns share]$ lynx --help -> 머라고 나오면 준비 OK! 아니면 깔아야함(이것도 다루지 않음)
위 두가지가 정상적으로 준비 되었다면 환경은 OK입니다.
그럼 주기적으로 윈앰정보를 받아올 cron셋업을 해보죠.
[topcj@ns share]vi schedule.cron
* * * * * lynx -source http://cast.topcj.com:2880/ > /home/topcj/public_html/cast_status.cron.html
http://cast.topcj.com:2880 에서 보이는 방송정보를 1분마다 한번씩 html소스로 받아 지정 경로/파일에 지정합니다.
간격은 얼마든지 지정 가능하나 방송국에선 1분 말고는 선택의여지가 없겠네요. 자세한건 각종 cron사용법 참조.
[topcj@ns share]crontab schedule.cron
위 명령으로 지정한 스케줄을 실행시킵니다.
1분에 한번씩 위에서 지정한 /home/topcj/public_html/cast_status.cron.html 파일이 업뎃 되는것을 볼 수 있습니다. (처음 1분은 암것도 없습닭 -_-)
성공적이라면 어떻게 해야하는지 아실겁니다.
소켓 접속대신 이 파일을 받아서 분석하면 되는것이죠. 순식간입니닭.
변경된 정보 분석 함수를 써보까요?
급하게 수정한터라 엉성하기 그지 없습니다. 변경의 여지 다분합니다. ㅡ,.ㅡ
참고로 crond에 문제가 생겨 업뎃이 되지 않고 있을때는 자동으로 원래의 소켓 접속으로 전환됩니다. 걍 생각없이 쓰시다가 cron이 잘 대나 확인해 주시면 대게찌욤~
두번째 참고로 기본 소스는 이곳에 올려진 어느 분의 작품중 하나인데요.
생성된 파일의 경로를 담는 $STAT_CRON변수와 처음으로 나오는 if문 부터 else 나오기 직전의 블럭까지 추가된 것 말고는 원래 그대로입니다.
http://topcj.com 널러 오시묜 방가이 맞이하겠슴닭!!
m(__)m
[쏘쓰]
$STAT_CRON = "/home/topcj/public_html/cast_status.cron.html";
function get_scinfo($address) {
global $STAT_CRON;
if(filemtime($STAT_CRON)>=time()-60) { // 1분전에 정보파일이 업뎃 되었으면 파일 읽기 아니면 소켓접속
$fp = fopen($STAT_CRON,'r');
while(!feof($fp)) // 쩝.. 모하러 이걸썼나.. readfile()이 있는데.. _-_
$temp .= fgets($fp, 1024);
fclose($fp);
} else {
$url_temp = explode(":",$address); // 콜론(:) 기준 분리해 배열에 저장
$url = $url_temp[0]; // 주소 분리
$port = $url_temp[1]; // 포트 분리
$fp = fsockopen($url, $port, &$errno, &$errstr, 5); // 소켓 연결
if($fp) { // 연결 성공시
fputs($fp,"GET /index.html HTTP/1.0nUser-Agent: Mozilla/4.0nn"); // 헤더 보냄
while(!feof($fp)) $temp .= fgets($fp,1024); // 파일이 끝날때까지 1024바이트씩 가져옴
fclose($fp);
}
}
// 접속 해제
//------------------------------------------------------------------------------// 가공시작
$keyword = array( // 찾을 값 (2차원 배열)
array("version" => "SHOUTcast Server Version"),
array("server" => "Server Status:"),
array("stream" => "Stream Status:"),
array("peak" => "Listener Peak:"),
array("time" => "Average Listen Time:"),
array("title" => "Stream Title:"),
array("genre" => "Stream Genre:"),
array("url" => "Stream URL:"),
array("icq" => "Stream ICQ:"),
array("aim" => "Stream AIM:"),
array("irc" => "Stream IRC:"),
array("song" => "Current Song:"),
);
$size = sizeof($keyword); // 배열의 크기 구함
$temp = strip_tags( // 4) 모든 태그 제거
implode("n<tr", // 3) n<tr 문자열로 다시 결합
explode("<tr", // 2) <tr 기준으로 분리 -> 배열값
str_replace(" "," ",$temp)))); // 1) 를 공백으로 바꿈
for ($i=0; $i<$size; $i++) { // 배열의 크기만큼 반복
$t_key = array_keys($keyword[$i]); // 키값을 가져옴
$t_key1 = $t_key[0]; // 처음키
$t_key2 = $keyword[$i][$t_key1]; // 키에 해당하는 값을 가져옴
$address = strpos($temp,$t_key2); // 키에 해당하는 위치값 구함
if ($address) { // 위치값이 있을 경우
$start = $address+strlen($t_key2); // 시작위치값 저장 (+길이)
$end = $start; // 시작위치값 저장 (증가치)
while(substr($temp,$end,1)!="n") $end++; // 다음줄 찾기 전까지 반복
$temp2[$t_key1] = trim(substr($temp,$start,$end-$start)); // 찾은 결과값 출력
if ($t_key1=="aim") $temp2[$t_key1] = urldecode($temp2[$t_key1]); // AIM은 디코드
}
}
//------------------------------------------------------------------------------// 가공끝
$stream = explode(" ",$temp2[stream]); // stream 문자열 공백 기준 분리
$temp2[speed] = trim($stream[4])." ".trim($stream[5]); // 방송속도 : 4,5번째 요소 가져옴
$temp2[listen] = trim($stream[7]); // 청취자 : 7번째 요소
$temp2[maxlisten] = trim($stream[9]); // 최대청취인원 : 9번째 요소
$temp2[unique] = str_replace("(","",trim($stream[11])); // 청취자 : 11번째 요소 (동일 IP 제외)
$temp2[time] = str_replace("h","시간",str_replace("m","분",str_replace("s","초",$temp2[time]))); // 시간,분,초 변환
if ($temp2[server]=="Server is currently up and public.") $temp2[air] = 1; // 방송중
elseif ($temp2[server]=="Server is currently down.") $temp2[air] = 0; // 방송안함
else $temp2[air] = -1; // 찾지 못함
return $temp2; // 값 반환
}
댓글 9
-
Romeo
2002.01.15 01:36
-
아르코~
2002.01.16 07:27
서버를 가지고 있지 아니하면.. 힘들겠죠.. 후훗.. 크론이 생각보다 부하를 또 주지요 후훗...
방송 서버 는.. 이런식으로 갱신을 해줘야할뜻.. . 아니면 ㅡㅡ;;;;; PHP 쉘을 쓰던지.. -
수지니^^
2002.01.16 08:09
비혼님꺼 같네요 ^^; -
양창민
2002.01.16 10:26
부하를 준다...
왜 cron을 쓰나요?
어렵게시리..^^
php 프로그램밍하구 메타태그로 리프레쉬 1분단위로 하게끔 하고서
그걸 로컬에서 열면 간단하잖아요.
부하두 안주고.
~ Written date/time: 2002-01-16 10:26:45
~ http://myhome.hananet.net/~changminyang/
~ Powerful PHP programmed by YangChangMin
~ Time to say goodbye... -
Romeo
2002.01.17 17:27
방송서버와 홈피서버가 분리되어 있는경우에 유용한 것이지요.
리프레시를 하게되면 수시로 곡명 업뎃이 가능하지만 홈피 접속자가 많은 경우에 httpd프로세스 생성과 소켓접속이 그에 비례해 끊임없이 일어나지요.
참고로 httpd 프로세스가 항상 70여개 이상 떠있는 호스팅업체의 서버에 crond는 각각 0%의 CPU사용률과 메모리 사용률을 보여주네요. (물론 스케줄 등록이 밸루 없어서 이럴수도 있지만)
반면 리프레쉬와 관계있는 httpd프로세스는 개당0.x~1.x대의 리소스를 점유하고 있습니다.
중요한건 소켓접속이 생략된 이후에 홈피가 눈에 띄게 빨라졌다는 것입니다. ^-^ -
양창민
2002.01.18 06:52
크...
역쉬 쉽게 생각하는 사람과 어렵게 생각하는 사람과의 차이군요.
제가 말하는건 무지 쉬운건데 님은 어렵게 구현하려 하시네요.
쉽게 말해서 님 방송서버로 쓰는 컴퓨터에 아래 파일을 만듭니다.
serverinfo.php (경로는 http 루트에 둔다고 하구)
이 파일은 메타태그 리프레쉬 1분(편한대루) 동작을 합니다.
내용은 방송서버 관련된 정보 맹글어내겠죠?
이 파일의 접속경로는 당근 http://127.0.0.1/serverinfo.php
이 서버컴퓨터에서 실행되므로 프로세스는 당연히 하나죠?
serverinfo.php 에선 sql db 테이블에 정보를 넣건 임의 경로에 파일로 남기건 서버방송정보를 뱉어내겠죠?
이제 방송서버에 접속하는 사람들이 얻을 서버방송정보는 저 serverinfo.php가 뱉어낸 방송정보만 참조하면 되죠?
웬 프로세스가... 접속한 사람마다 나올 것이라구... 생각하시는지.
~ Written date/time: 2002-01-18 06:53:44
~ http://myhome.hananet.net/~changminyang/
~ Powerful PHP programmed by YangChangMin
~ Time to say goodbye... -
Romeo
2002.01.18 11:53
으흐흠.. 홈피서버와 방송서버가 분리된 상황이라고는 말씀 드렸었고..
전제가 생락되어 혼동이 오는것 같은데요.
1. 홈피서버는 셀계정 사용 가능합니다. (호스팅업체 사용등)
2. 방송서버는 쉘계정 없습니다. (대표적인 유료서버 http://inlive.co.kr, http://pamazan.com기타등등)
설사 전제가 없더라도.
극단적으로 생각해서 홈피 동시 접속자가 1억명이며 한 페이지에서 가만히 있고 리프레시나 cron이나 둘다 1분주기로 업뎃을 실시할시. 서버에서 벌어지는 10분동안의 사건사고들을 보면,
1. 리프레시 사용시
httpd프로세스 10억회, 소켓접속 10억회, 파일생성 10억회.
2. crond 사용시
httpd프로세스 1억회, 소켓접속 10회, lynx프로세스 10회, crond실행 10회, 파일생성 10회.
(물론 주기적으로 새 곡명이 홈피에 출력되진 않지요. 메뉴를 돌아다니거나 필요시 릴로드 눌러주면 됩니다)
창민님의 설정한 상황을 제대로 이해하기 힘든데요..
홈피의 특정페이지상에서 serverinfo.php를 계속 리프레시 했을경우로 이해하고 작성한 답변입니다.
즉 창민님의 serverinfo.php를, 접속한 1억명의 사용자의 브라우저가 리프레시 시켜준다는 의미이지요.
제가 잘못 이해한거면 답글 부탁드립니다.
누차 말씀드리지만, 이거는 이론이나 최적화방법을 소개하는게 아니고 호스팅이라는 열악?한 환경에서 확실한 득을 보았기 때문에 올리는 "팁"입니다.
"팁"은 자기가 필요하지 않으면 안쓰면 되는겁니다. 창민님의 쉬운 방법으로 우선 생각했다가 도저히 안되겠어서 이 방법을 생각해 낸 것입니다.
모두 즐건 하루되세요~ -
Romeo
2002.01.18 12:41
곰곰히 생각컨데.
crond 없이, 생성된 서버정보파일의 업뎃 날짜를 봐서 1분이 지났을때에만 소켓접속을 홈피상에서 실시하여 정보파일 업뎃하면..
홈피 접속수가 아무리 많아도 1분회 1회에 딱걸린? 사람만 소켓 접속을 하겠네요.
크론과 리프레쉬에 대한 절충안이 되려나? -_-; -
이승원
2002.01.19 11:54
지가 생각하기론 그냥 방송정보만 수집하는
서버를 단독으로 돌리는것이 좋을것 같은데요 이히
그런데 머니가 많이든다는것이 문제 헤헤
서버 한대의 얼마나 되죠 한 천만원 되나 ^^;;
^^ 그럼 이만 빠빠이
제목 | 글쓴이 | 날짜 |
---|---|---|
좋은 난수값을 얻기위한 시드배정 방법 mt_srand(), srand() | 차카게살자 | 2002.02.21 |
필터링조금 다른거.. [7] | 두기두바 | 2002.02.10 |
한글 필터링 정확히 하기 [1] | mini | 2002.02.09 |
원고지 함수;; [3] | 디쓰 | 2002.02.07 |
md5() 알고리듬 [8] | 양창민 | 2002.02.05 |
이제 홈페이지 업데이트 안하는 수모를 겪지 말자! [7] | 담배를끊으면복이옴과 | 2002.02.02 |
이제 PHP에 ?id=가나다라 같은것을 넣자! [12] | 담배를끊으면복이옴과 | 2002.01.30 |
초보분들을 위한 연산자 총정리 [6] | TheMics | 2002.01.29 |
[PHP]모르는 분이 있는듯 해서...변수관련 [2] | TheMics | 2002.01.24 |
cron을 이용해 윈앰프 방송정보를 빠르게 분석. [9] | Romeo | 2002.01.15 |
파일시스템에서 비밀번호 생성/수정/인증 [7] | 두기두바 | 2002.01.10 |
파일시스템(배열)에서의 검색기능 [5] | 두기두바 | 2002.01.09 |
[추천 팁] 디망쉬식 스킨 시스템 [4] | 디망쉬 | 2001.12.11 |
[추천 소스] phpMyAdmin 다중사용자용... [5] | WOWpc | 2001.11.29 |
MySQL에서 한글 정렬 문제 [2] | 손정호 | 2001.11.21 |
phpMyAdmin에서 dump 안 되시는 분들 보세요 [5] | 똥가리 | 2001.11.18 |
컴에 phpMyAdmin 깔고 원격 Mysql 관리.(이것도 팁이 되려나?) [1] | 최형삼 | 2001.11.17 |
[추천 소스] 특정일로부터 몇일 지났나 또는 몇일 남았나 알아보는 소스 ㅡ.ㅡ; [1] | 타스케 | 2001.11.15 |
게시판 만들 때 스팸메일을 막을 수 있는 방법중 한개. [11] | WOWpc | 2001.11.09 |
[GD] 이미지 회전 함수 공개합니다. [7] | 노경민 | 2001.11.05 |
딴창으로 다시 로그인 후 만료된페이지 릴로드하니 휴... 오늘밤 잠 못이룰뻔 했네요..