Задать вопрос

SockJS, node.js, а что если php не успеет?

Играюсь с реал таймом и сделал простенькую связку, собственно пример того, что будет в будущем:

Наш клиент:
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>

<div id="content"></div>

<script type="text/javascript">

    var content = document.getElementById('content');
    
    
    var sock = new SockJS('http://127.0.0.1:9999/echo');
    
    sock.onopen = function() {
       console.log('open');
    };
    
    
    sock.onmessage = function(e) {
       content.innerHTML = e.data;
    };
    
    
    sock.onclose = function() {
       console.log('close');
    };

</script>


Сервер node.js
var http = require('http');
var sockjs = require('sockjs');
var http = require('http');

var options = {
    host: 'portf2.ru',
    path: '/poling/server.php'
};



var echo = sockjs.createServer();


echo.on('connection', function(conn) {
    
    setInterval(function(){
                
        var req = http.get(options, function(res) {
            
          //console.log('STATUS: ' + res.statusCode);
          //console.log('HEADERS: ' + JSON.stringify(res.headers));
        
          // Buffer the body entirely for processing as a whole.
          var bodyChunks = [];
          res.on('data', function(chunk) {
            // You can process streamed parts here...
            bodyChunks.push(chunk);
          }).on('end', function() {
            var body = Buffer.concat(bodyChunks);
            var response = JSON.parse(body);
            
            conn.write(response.date);
            
          })
        });
        
        
        
        req.on('error', function(e) {
          console.log('ERROR: ' + e.message);
        });

    }, 1000);

    
    conn.on('data', function(message) {
        conn.write(message);
    });
    
    
    conn.on('close', function() {});
});

var server = http.createServer();
echo.installHandlers(server, {prefix:'/echo'});
server.listen(9999, '0.0.0.0');


И апи на php:
<?php 
$objDateTime = new DateTime('NOW');
$date = $objDateTime->format('H:i:s');
$ar = ['date'=>$date];

echo json_encode($ar);


В дальнейшем будет все работать следующим образом:
Есть страница с игроками ожидающие игры. Это таблица которая должна постоянно обновляться. Ну например присоединился новый игрок, мы должны его показать, игрок покинул игру, нужно это показать и тп.

Собственно на php есть api которое возвращает json данные об игре (сколько игроков, какие игроки и тп.) задача node.js получать эти данные и отправлять на клиент, который рисует таблицу.

Теперь у меня возник ряд вопросов:
1) Что если php не успеет ? Ну например, я указал, что в setInterval данные будут обновляться каждую секунду, что будет если php не успеет обработать все за 1 секунду ? Тоесть глюк на сервере, много информации, много трафика, что вообще будет ?
На текущем примере я попытался пощипать php дописав sleep(10), и он начал творить что то странное, тоесть вначале ждет 10 секунд, потом показывает дату обновляет 5 раз по 1 секунде и снова ждет 10 секунд.
Что вообще происходит в этом случае и чем чревато ?

2 ) К примеру php будет справляться все будет отлично, но что будет на больших нагрузках ? Когда на странице например будут находиться 10 000 юзеров ?

3) Как я знаю сокеты работают по тспи соединению и должны гарантировать доставку данных на клиент. На практики так и есть или же потеря данных вероятна ?
  • Вопрос задан
  • 3854 просмотра
Подписаться 4 Оценить Комментировать
Решения вопроса 2
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
А что будет если не успеет JS? Из описанного вами, издержки на доставку данных будут в десятки раз привышать издрержки на вычисления. Для начала стоит понять что setInterval не гарантирует того, что функция будет вызвана именно через одну секунду, там тоже будут свои флюктуации в силу однопоточности JS. Как с этим бороться, сходу не подскажу, все зависит от логики приложения.

10 000 одновременных запросов к серверу (именно отдельных запросов, а не через WebSockets) могут положить небольшой сервер. Для этого существует нагрузочное тестирование.

TCP гарантирует отсутствие потери данных, собственно по этому в реалтаймовых штуках TCP используется только в случае, если UDP дает большую потерю пакетов (например UDP трафик режется или что-то в этом духе). То есть когда сервер отправляет пакет, от откладывает его в буфер до подтверждения его получения клиентом. Если сервер в течении определенного времени не получает по ICMP подтверждения о том что пакет был отправлен, он заново начинает отправлять весь буфер. Когда буфер полон - новые пакеты вы отправить уже не можете пока не освободится, насколько я помню, хотя бы половина. В реалтайме же вас не должна смущать ситуация с потерей пакетов (если данные помещаются в один пакет конечно), так как у них не так много времени, что бы нести "актуальные данные". проще послать следующий пакет. чем переотправлять уже не актуальные данные. Но WebSockets не работают с UDP.
Ответ написан
avalak
@avalak
Поскольку WebSockets у вас используется в одном направлении разницы с SSE по сути нет. Кстати, почему от SSE отказались?

node.js в текущей схеме бесполезен. От того что php будет долбить запросами node.js а не браузер лучше не станет + у вас образовалась лишняя сущность.

лучше php => redis pub/sub => nodejs / tornado => ws / sse

setInterval использовать не рекомендуют. setTimeout лучше.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы