У меня есть следующий запрос в jquery. Он читает "публиковать" адрес пары подписки/публикации Nginx, созданной с использованием модуля долгого опроса Nginx.
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = $.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: 46000, // must be longer than max heartbeat to only trigger after silent error.
error: function(jqXHR, textStatus, errorThrown) {
alert("Background failed "+textStatus); // should never happen
getxhr.abort();
requestNextBroadcast(); // try again
},
success: function(reply, textStatus, jqXHR) {
handleRequest(reply); // this is the normal result.
requestNextBroadcast();
}
});
}
Код является частью чата. На каждое отправленное сообщение отвечает нулевой запрос (с сообщением 200/OK), но данные публикуются. Это код для чтения адреса подписки, когда данные возвращаются.
Используя тайм-аут, все люди в чате посылают простое сообщение каждые 30-40 секунд, даже если они ничего не набирают, поэтому есть данные для чтения этого кода - как минимум 2 и, возможно, больше сообщений на 40 секунд.
Код в 100% устойчив в EI и Firefox. Но один из прочитанных примерно 5 ошибок в Chrome.
При сбое Chrome это происходит с таймаутом 46 секунд.
В журнале отображается один или один запрос активности сети в любой момент времени.
Я просканировал этот код в течение 3 дней, пытаясь различной идеи. И каждый раз, когда IE и Firefox работают нормально, и Chrome терпит неудачу.
Одно из предложений, которое я видел, - сделать звонок синхронным, но это явно невозможно, потому что он слишком долго блокирует пользовательский интерфейс.
Изменить - у меня есть частичное решение: Код теперь этот
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = jQuery.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: <?php echo $delay; ?>,
error: function(jqXHR, textStatus, errorThrown) {
window.status="GET error "+textStatus;
setTimeout(requestNextBroadcast,20); // try again
},
success: function(reply, textStatus, jqXHR) {
handleRequest(reply); // this is the normal result.
setTimeout(requestNextBroadcast,20);
}
});
}
Результат иногда ответ задерживается до тех пор, пока не произойдет $delay (15000), тогда очереди в очереди поступают слишком быстро, чтобы следовать. Я не смог заставить его отправлять сообщения (только проверенные с отключением netwrok optomisation) с этим новым соглашением.
Я очень сомневаюсь, что задержки связаны с сетевыми проблемами - все машины являются виртуальными машинами на моей одной реальной машине, и нет других пользователей локальной локальной сети.
Изменить 2 (Пятница 2:30 BST) - Изменен код для использования promises - и POST действий начал показывать те же симптомы, но сторона приема начала работать нормально! (????!!!???). Это процедура POST - она обрабатывает последовательность запросов, чтобы гарантировать, что только один за раз выдался.
function issuePostNow() {
// reset heartbeat to dropout to send setTyping(false) in 30 to 40 seconds.
clearTimeout(dropoutat);
dropoutat = setTimeout(function() {sendTyping(false);},
30000 + 10000*Math.random());
// and do send
var url = "handlechat.php?";
if (postQueue.length > 0) {
postData = postQueue[0];
var postxhr = jQuery.ajax({
type: 'POST',
url: url,
data: postData,
timeout: 5000
})
postxhr.done(function(txt){
postQueue.shift(); // remove this task
if ((txt != null) && (txt.length > 0)) {
alert("Error: unexpected post reply of: "+txt)
}
issuePostNow();
});
postxhr.fail(function(){
alert(window.status="POST error "+postxhr.statusText);
issuePostNow();
});
}
}
Примерно за одно действие в 8 вызов handlechat.php будет отключен и появится предупреждение. После подтверждения оповещения все сообщения в очереди поступают.
И я также заметил, что вызов handlechat был остановлен, прежде чем он написал сообщение, которое другие увидели бы. Мне интересно, может ли быть какая-то странная обработка сессионных данных php. Я знаю, что он тщательно ставит в очередь вызовы, чтобы данные сеанса не были повреждены, поэтому я старался использовать разные браузеры или разные машины. Существует только 2 рабочих потока php, однако php НЕ используется при обработке/активности или в обслуживании статического содержимого.
Я также думал, что это может быть нехваткой рабочих nginx или php-процессоров, поэтому я поднял их. Сейчас труднее добиться того, чтобы все провалилось, но все же возможно. Я предполагаю, что вызов /activity теперь терпит неудачу один раз в 30 раз и вообще не отбрасывает сообщения.
И спасибо, ребята, за ваш вклад.
Резюме результатов.
1) Это ошибка в Chrome, которая некоторое время находилась в коде.
2) С удачей ошибка может быть сделана, чтобы появиться как POST, который не отправлен, и, когда он истечет, он оставляет Chrome в таком состоянии, что повторное POST будет успешным.
3) Переменная, используемая для хранения возврата из $.ajax(), может быть локальной или глобальной. Новый (promises) и старый формат вызовы оба запускают ошибку.
4) Я не нашел работу или способ избежать ошибки.
Ян