이 주제에 대한 게시물을 읽었으며 답변은 혜성, 역 아약스, http 스트리밍, 서버 푸시 등입니다.
Gmail 채팅은 어떻게 클라이언트 상호 작용없이 AJAX 요청을 할 수 있습니까?
매우 간단한 예제를 작성하기 위해 수행 할 수있는 코드 참조가 있는지 알고 싶습니다. 많은 게시물이나 웹 사이트가 기술에 대해 이야기합니다. 완전한 샘플 코드를 찾기는 어렵습니다. 또한 혜성을 구현하기 위해 많은 방법을 사용할 수있는 것 같습니다 (예 : Hidden IFrame, XMLHttpRequest). 제 생각에는 XMLHttpRequest를 사용하는 것이 더 좋습니다. 다른 방법의 장단점에 대해 어떻게 생각하십니까? Gmail은 어느 것을 사용합니까?
서버 측과 클라이언트 측 모두 에서이 작업을 수행해야한다는 것을 알고 있습니다. PHP 및 Javascript 샘플 코드가 있습니까?
답변
페이스 북이하는 방식은 꽤 흥미 롭습니다.
이러한 알림을 수행하는 일반적인 방법은 주어진 간격 (아마도 몇 초마다)마다 서버에서 스크립트 (AJAX 사용)를 폴링하여 문제가 발생했는지 확인하는 것입니다. 그러나 이것은 네트워크 집약적 일 수 있으며 아무 일도 일어나지 않기 때문에 종종 무의미한 요청을합니다.
페이스 북이하는 방식은 한 폴링이 완료 되 자마자 다른 폴링을 발행하자마자 간격으로 폴링하는 대신 혜성 접근법을 사용하는 것입니다. 그러나 서버의 스크립트에 대한 각 요청은 시간이 매우 길며, 서버는 요청이 발생한 후에 만 요청에 응답합니다. Facebook에있는 동안 Firebug의 콘솔 탭을 표시하고 스크립트에 대한 요청이 몇 분 정도 걸릴 수 있습니다. 이 방법은 요청 수와 전송 빈도를 즉시 줄이므로 매우 독창적입니다. 이제 서버가 이벤트를 ‘실행’할 수있는 이벤트 프레임 워크를 갖게되었습니다.
그 뒤에는 해당 설문 조사에서 반환 된 실제 내용과 관련하여 JSON 목록이며 이벤트 목록으로 보이는 내용과 관련 정보가 있습니다. 그래도 축소되었으므로 읽기가 약간 어렵습니다.
실제 기술 측면에서 AJAX는 요청 시간 초과 및 기타 여러 가지를 제어 할 수 있기 때문에 여기로가는 방법입니다. jQuery를 사용하여 AJAX를 수행하는 것이 좋습니다 (Stack overflow cliche here), 많은 호환성 문제가 사라질 것입니다. PHP와 관련하여 PHP 스크립트에서 이벤트 로그 데이터베이스 테이블을 간단히 폴링하고 어떤 일이 발생했을 때만 클라이언트로 돌아갈 수 있습니까? 나는 이것을 구현하는 많은 방법이 있다고 생각합니다.
구현 :
서버 측:
PHP에는 혜성 라이브러리가 몇 가지 구현되어 있지만 솔직히 말하면 다음과 같은 의사 코드와 같이 매우 간단합니다.
while(!has_event_happened()) {
sleep(5);
}
echo json_encode(get_events());
-
has_event_happened 함수는 이벤트 테이블이나 무언가에 무슨 일이 있었는지 확인한 다음 get_events 함수는 테이블의 새 행 목록을 반환합니까? 실제로 문제의 상황에 따라 다릅니다.
-
PHP 최대 실행 시간을 변경하는 것을 잊지 마십시오. 그렇지 않으면 조기 시간 초과됩니다!
고객 입장에서:
Comet 상호 작용을 수행하기위한 jQuery 플러그인을 살펴보십시오.
- 프로젝트 홈페이지 : http://plugins.jquery.com/project/Comet
- Google 코드 : https://code.google.com/archive/p/jquerycomet/- 서브 버전 저장소에서 일종의 사용 예가 나타납니다.
즉, 플러그인은 약간의 복잡성을 추가하는 것처럼 보이며 클라이언트에서 매우 간단합니다 (jQuery 사용).
function doPoll() {
$.get("events.php", {}, function(result) {
$.each(result.events, function(event) { //iterate over the events
//do something with your event
});
doPoll();
//this effectively causes the poll to run again as
//soon as the response comes back
}, 'json');
}
$(document).ready(function() {
$.ajaxSetup({
timeout: 1000*60//set a global AJAX timeout of a minute
});
doPoll(); // do the first poll
});
모든 것은 기존 아키텍처가 어떻게 구성되는지에 달려 있습니다.
답변
최신 정보
이에 대한지지를 계속 받으면서이 답변이 4 살이라는 것을 기억하는 것이 합리적이라고 생각합니다. 웹은 정말 빠른 속도로 성장 했으므로이 답변에 유의하십시오.
나는 최근에 같은 문제가 있었고 그 주제에 대해 연구했습니다.
제공된 솔루션을 롱 폴링이라고하며,이를 올바르게 사용하려면 AJAX 요청에 “대형”시간 초과가 있는지 확인하고 현재 종료 (시간 초과, 오류 또는 성공) 후에 항상이 요청을 작성해야합니다.
긴 폴링-클라이언트
여기서는 코드를 짧게 유지하기 위해 jQuery를 사용합니다.
function pollTask() {
$.ajax({
url: '/api/Polling',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (eventList) {
// Handle your data here
var data;
for (var eventName in eventList) {
data = eventList[eventName];
dispatcher.handle(eventName, data); // handle the `eventName` with `data`
}
}).always(pollTask);
}
( jQuery docs에서 ) 를 기억하는 것이 중요합니다 .
jQuery 1.4.x 이하에서 XMLHttpRequest 객체는 요청 시간이 초과되면 유효하지 않은 상태가됩니다. 객체 멤버에 액세스하면 예외가 발생할 수 있습니다. Firefox 3.0 이상에서만 시간 초과로 스크립트 및 JSONP 요청을 취소 할 수 없습니다. 시간 종료 기간이 지난 후에도 스크립트가 실행됩니다.
긴 폴링-서버
특정 언어는 아니지만 다음과 같습니다.
function handleRequest () {
while (!anythingHappened() || hasTimedOut()) { sleep(2); }
return events();
}
여기에서 hasTimedOut
코드가 영원히 기다리지 않도록 anythingHappened
하고 이벤트가 발생했는지 확인합니다. 는 sleep
아무 일도없는 동안 다른 물건을 할 스레드를 해제하는 것입니다. 은 events
JSON 형식 (또는 원하는 다른 형식)으로 이벤트 사전 (또는 원하는 다른 데이터 구조)을 반환합니다.
확실히 문제를 해결하지만 연구 할 때와 같이 확장 성과 성능이 걱정된다면 내가 찾은 또 다른 해결책을 고려할 수 있습니다.
해결책
소켓을 사용하십시오!
클라이언트 측에서 호환성 문제를 피하려면 socket.io를 사용 하십시오 . 소켓을 직접 사용하려고 시도하고 소켓을 사용할 수 없을 때 다른 솔루션으로 대체합니다.
서버 측에서 NodeJS를 사용하여 서버를 작성 하십시오 (예 🙂 . 클라이언트는 서버로 작성된이 채널 (관찰자)을 구독합니다. 알림을 보내야 할 때마다이 채널에 게시되고 아래 첨자 (클라이언트)에게 알립니다.
이 솔루션이 마음에 들지 않으면 APE ( Ajax Push Engine )를 사용해보십시오 .
도움이 되었기를 바랍니다.
답변
Facebook의 메시징 시스템에 대한 슬라이드 쇼에 따르면 Facebook은 혜성 기술을 사용하여 웹 브라우저에 메시지를 “밀어 넣습니다”. Facebook의 혜성 서버는 오픈 소스 Erlang 웹 서버 mochiweb에 구축됩니다.
아래 그림에서 “채널 클러스터”라는 용어는 “경쟁 서버”를 의미합니다.
다른 많은 대형 웹 사이트는 회사마다 필요한 차이가 있기 때문에 자체 혜성 서버를 구축합니다. 그러나 오픈 소스 혜성 서버에 자신 만의 혜성 서버를 구축하는 것이 좋습니다.
당신이 시도 할 수 icomet , libevent와 내장 C1000K C ++ 혜성 서버를. icomet은 JavaScript 라이브러리도 제공하므로 다음과 같이 간단하게 사용할 수 있습니다.
var comet = new iComet({
sign_url: 'http://' + app_host + '/sign?obj=' + obj,
sub_url: 'http://' + icomet_host + '/sub',
callback: function(msg){
// on server push
alert(msg.content);
}
});
icomet은 Safari (iOS, Mac), IE (Windows), Firefox, Chrome 등 광범위한 브라우저 및 OS를 지원합니다.
답변
Facebook은 HTTP 대신 MQTT를 사용합니다. 폴링보다 푸시가 더 좋습니다. HTTP를 통해 서버를 지속적으로 폴링해야하지만 MQTT 서버를 통해 메시지를 클라이언트에 푸시합니다.
MQTT와 HTTP 비교 : http://www.youtube.com/watch?v=-KNPXPmx88E
참고 : 내 대답은 모바일 장치에 가장 적합합니다.
답변
긴 폴링의 중요한 문제 중 하나는 오류 처리입니다. 두 가지 유형의 오류가 있습니다.
-
요청이 시간 초과 될 수 있으며이 경우 클라이언트는 즉시 연결을 다시 설정해야합니다. 메시지가 도착하지 않았을 때 긴 폴링에서 발생하는 정상적인 이벤트입니다.
-
네트워크 오류 또는 실행 오류 이것은 클라이언트가 서버를 다시 온라인 상태로 올바로 수락하고 기다려야하는 실제 오류입니다.
주요 문제는 오류 처리기가 유형 2 오류에 대해서도 즉시 연결을 다시 설정하면 클라이언트가 서버를 DOS한다는 것입니다.
코드 샘플이있는 두 대답은 이것을 놓칩니다.
function longPoll() {
var shouldDelay = false;
$.ajax({
url: 'poll.php',
async: true, // by default, it's async, but...
dataType: 'json', // or the dataType you are working with
timeout: 10000, // IMPORTANT! this is a 10 seconds timeout
cache: false
}).done(function (data, textStatus, jqXHR) {
// do something with data...
}).fail(function (jqXHR, textStatus, errorThrown ) {
shouldDelay = textStatus !== "timeout";
}).always(function() {
// in case of network error. throttle otherwise we DOS ourselves. If it was a timeout, its normal operation. go again.
var delay = shouldDelay ? 10000: 0;
window.setTimeout(longPoll, delay);
});
}
longPoll(); //fire first handler