Статьи

Дилемма скорости Node.js: AJAX или Socket.IO?

Первоначально опубликовано Daniel Chirca

Первое, на что я наткнулся, когда начал свой первый проект Node.js, было то, как обрабатывать связь между браузером (клиентом) и промежуточным программным обеспечением (промежуточное программное обеспечение — это приложение Node.js, использующее узел CUBRID. Драйвер .js ( node-cubrid ) для обмена информацией с базой данных CUBRID 8.4.1 ).

Я уже знаком с AJAX (кстати, слава Богу за jQuery !! ), но, изучая Node.js, я узнал о  модуле Socket.IO и даже нашел несколько довольно хороших примеров кода в Интернете … Примеры, которые было очень-очень легко (пере) использовать …

Так что это быстро становится дилеммой:  что выбрать, AJAX или sockets.io?

Очевидно, поскольку мой опыт был весьма ограничен, мне сначала понадобилось больше информации оттуда … Другими словами, пришло время сделать качественный поиск в Google ?

Доступно много информации, и, очевидно, нужно будет отфильтровать весь «шум» и сохранить то, что действительно полезно. Позвольте мне поделиться с вами некоторыми ссылками на товары, которые я нашел по этой теме:

Подводя итог, вот что я быстро нашел:

  1. Socket.IO (обычно) использует постоянное соединение между клиентом и сервером (промежуточное программное обеспечение), поэтому вы можете достичь максимального ограничения числа одновременных соединений в зависимости от ресурсов, имеющихся у вас на стороне сервера (в то время как больше асинхронных запросов AJAX можно обслуживать с помощью те же ресурсы).
  2. С AJAX вы можете делать RESTful запросы. Это означает, что вы можете использовать преимущества существующей HTTP-инфраструктуры, например, прокси для кеширования запросов и использования условных запросов get .
  3. В AJAX больше издержек на обмен данными по сравнению с Socket.IO (заголовки HTTP, файлы cookie и т. Д.)
  4. AJAX обычно быстрее, чем Socket.IO, «кодирует» …
  5. При использовании Socket.IO возможна двусторонняя связь, при которой каждая сторона — клиент или сервер — может инициировать запрос. В AJAX только клиент может инициировать запрос!
  6. Socket.IO имеет больше вариантов транспорта, включая Adobe Flash.

Теперь для моего собственного приложения меня больше всего интересовала скорость выполнения запросов и получения данных с сервера (Node.js)!

Что касается обмена данными промежуточного программного обеспечения с базой данных CUBRID, так как ~ 90% моего доступа к данным были только для чтения, хороший механизм кэширования данных, безусловно, отличный способ! Но об этом я поговорю в следующий раз.

Поэтому я решил увеличить их скорость (AJAX и socket.io), чтобы проверить , какая из них быстрее (по крайней мере, в моей аппаратной и программной среде) ….! Мое промежуточное программное обеспечение было настроено для работы на процессоре i5, 8 ГБ оперативной памяти и жестком диске Intel X25.

А если серьезно, то каждый тест скорости и, вообще говоря, любой тест производительности так сильно зависит (!) От вашей аппаратной и программной конфигурации, что всегда хорошая идея попробовать что-то в вашей собственной среде, меньше полагаться на различную информацию, которую вы найдете в интернете и многое другое на ваших собственных выводах!

Тесты, которые я решил сделать, должны соответствовать следующим требованиям:

  • Контрольная работа:
    • AJAX
    • Постоянное соединение Socket.IO
    • Socket.IO непостоянные соединения
  • Тест 10, 100, 250 и 500 обменов данными между клиентом и сервером
  • Каждый обмен данными между промежуточным ПО SERVER (веб-сервер Node.js) и клиентом (браузер) представляет собой строку случайных данных размером 4 КБ.
  • Запустите сервер в режиме выпуска (не отладки)
  • Используйте Firefox в качестве клиента
  • Минимизируйте вывод сообщений консоли для сервера и клиента.
  • Проводите каждый тест после полной перезагрузки страницы клиента
  • Повторите каждый тест по крайней мере 3 раза, чтобы убедиться, что результаты соответствуют

Тестирование Socket.IO, используя постоянное соединение

Я создал небольшой сервер Node.js, который обрабатывал клиентские запросы:

io.sockets.on('connection', function (client) {
    client.on('send_me_data', function (idx) {
        client.emit('you_have_data', idx, random_string(4096));
    });
});

И это клиентский скрипт JS, который я использовал для теста:

var socket = io.connect(document.location.href);
 
socket.on('you_have_data', function (idx, data) {
    var end_time = new Date();
    total_time += end_time - start_time;
    logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
    if (idx++ < countMax) {
        setTimeout(function () {
            start_time = new Date();
            socket.emit('send_me_data', idx);
        }, 500);
    }
});

Тестирование Socket.IO с использованием непостоянного соединения

На этот раз для каждого обмена данными я открывал новое соединение Socket-IO.

Код сервера Node.js был аналогичен предыдущему, но я решил отправить данные клиента сразу после подключения, так как новое соединение каждый раз инициировалось для каждого обмена данными:

io.sockets.on('connection', function (client) {
    client.emit('you_have_data', random_string(4096));
});

Тестовый код клиента был:

function exchange(idx) {
    var start_time = new Date();
    var socket = io.connect(document.location.href, {'force new connection' : true});
 
    socket.on('you_have_data', function (data) {
        var end_time = new Date();
        total_time += end_time - start_time;
        socket.removeAllListeners();
        socket.disconnect();
        logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
         
        if (idx++ < countMax) {
            setTimeout(function () {
                exchange(idx);
            }, 500);
        }
    });
}

Тестирование AJAX

Наконец, я поставил AJAX для тестирования …

Код сервера Node.js, опять же, не сильно отличался от предыдущих:

res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end('_testcb(\'{"message": "' + random_string(4096) + '"}\')');

Что касается клиентского кода, это то, что я использовал для тестирования:

function exchange(idx) {
    var start_time = new Date();
 
    $.ajax({
        url : 'http://localhost:8080/',
        dataType : "jsonp",
        jsonpCallback : "_testcb",
        timeout : 300,
        success : function (data) {
            var end_time = new Date();
            total_time += end_time - start_time;
            logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
             
            if (idx++ < countMax) {
                setTimeout(function () {
                    exchange(idx);
                }, 500);
            }
        },
        error : function (jqXHR, textStatus, errorThrown) {
            alert('Error: ' + textStatus + " " + errorThrown);
        }
    });
}

Помните, что при кодировании вместе AJAX и Node.js необходимо учитывать, что вы можете выполнять междоменные запросы и нарушать одну и ту же политику происхождения , поэтому вам следует использовать формат на основе JSONP !

Кстати, как вы видите, я процитировал только самые важные части тестового кода, чтобы сэкономить место. Если кому-то нужен полный код, сервер и клиент, пожалуйста, дайте мне знать — я буду рад поделиться ими.

ОК — пришло время посмотреть, что мы получили после всей этой работы!

Я провел каждый тест для 10, 100, 250 и 500 обменов данными, и вот что я получил в итоге:

Обмен данными Socket.IO НЕ постоянный (мс.) AJAX (мс.) Socket.IO постоянный (мс.)
10 90 40 32
100 900 320 340
250 +2400 800 830
500 4900 1500 1600

Глядя на результаты, мы можем сразу заметить несколько вещей:

  1. Для каждого типа теста результаты ведут себя достаточно линейно; это хорошо — это показывает, что результаты соответствуют.
  2. Результаты ясно показывают, что при использовании непостоянных соединений Socket.IO показатели производительности значительно хуже, чем у других.
  3. Похоже, между AJAX и постоянными соединениями Socket.IO нет большой разницы — речь идет только о разнице в миллисекунды. Это означает, что, например, если вы можете жить с менее чем 10 000 обменов данными в день, есть большие шансы, что пользователь не заметит разницу в скорости …

График ниже иллюстрирует числа, которые я получил в тесте:

nodejs_socketio_ajax_performance.png

…Так что же дальше…?

… Ну, я должен выяснить, какой тип трафика мне нужно поддерживать, и затем я перезапущу тесты для этих номеров, но на этот раз за исключением непостоянных соединений Socket.IO. Это потому, что очевидно, что мне нужно выбирать между AJAX и постоянными  соединениями Socket.IO .

И я также узнал, что, скорее всего, разница в скорости будет не такой большой, как можно было бы ожидать … по крайней мере, не для веб-сайта с небольшим трафиком, поэтому мне нужно начать искать другие преимущества и недостатки для каждый подход / технология при выборе моего решения!

Это довольно много для этого поста — увидимся в следующий раз с постом о Node.js и кешировании !

PS Вот еще несколько полезных ресурсов, чтобы найти интересные материалы о Node.js , Socket.IO и AJAX :