PHP Socket Server против node.js: веб-чат - PullRequest
17 голосов
/ 01 января 2011

Я хочу запрограммировать HTTP-веб-чат с использованием длительных HTTP-запросов (Comet), ajax и веб-сокетов (в зависимости от используемого браузера). База данных пользователей находится в MySQL. Чат написан на PHP, за исключением, может быть, самого потока чата, который также может быть написан на javascript (node.js):

Я не хочу запускать процесс php для каждого пользователя, поскольку нет хорошего способа пересылать сообщения чата между этими php-потомками. Поэтому я подумал о написании собственного сокет-сервера в PHP или node.js, который должен был бы обрабатывать более 1000 соединений (пользователей чата). Как чисто веб-разработчик (php), я не очень знаком с сокетами, так как я обычно позволяю веб-серверу заботиться о соединениях. Сообщения чата не будут сохранены ни на диск, ни в mysql, но в RAM как массив или объект для лучшей скорости.

Насколько я знаю, нет способа обрабатывать несколько соединений одновременно в одном процессе php (сервер сокетов), однако вы можете принимать большое количество соединений сокетов и обрабатывать их последовательно в цикле (чтение и запись; входящее сообщение -> запись во все соединения сокетов). Проблема в том, что, скорее всего, будет задержка с ~ 1000 пользователей, и операции mysql могут замедлить все это, что затем повлияет на всех пользователей.

Мой вопрос: может ли node.js обрабатывать сокет-сервер с большей производительностью? Node.js основан на событиях, но я не уверен, что он может обрабатывать несколько событий одновременно (не требует ли многопоточность?) Или существует только очередь событий. С очередью событий это будет похоже на php: process user за пользователем.

Я мог бы также запустить процесс php для чата (гораздо меньше пользователей), но на самом деле существуют однопоточные IRC-серверы, которые также способны обрабатывать тысячи пользователей. (написано на C ++ или как угодно), так что, возможно, это также возможно в php.

Я бы предпочел PHP, а не Node.js, потому что тогда проект был бы только на php, а не на смеси языков программирования. Однако, если Node может обрабатывать соединения одновременно, я бы, вероятно, выбрал его.

Ответы [ 2 ]

25 голосов
/ 01 января 2011

JavaScript, или в данном случае V8, который является движком, который использует Node, по design однопоточен. Так что да, есть только очередь событий.

Но, в конце концов, это не проблема, сначала всегда что-то случится, если вы не используете несколько процессоров, и даже тогда у вас, скорее всего, будет только одна сетевая карта ... одна роутер ... вы поняли. Кроме того, использование 1000+ потоков ... не очень хорошая идея, плохо масштабируется, и вы окажетесь в параллельном режиме АД .

1000 пользователей чата, это будет без проблем для Node.js.

Я могу дать вам довольно простое представление о том, как бы вы его настроили, этот простой ванильный чат работает через telnet, у него нет .. никаких функций, но он работает:

var net = require('net'); // require the net module

var users = []; // keep track of the users

// setup a new tcp socket server
net.createServer(function(socket) { // provide a callback in case a new connection gets
                                    // established, socket is the socket object

    // keep track of this users names, via use of closures
    var name = '';

    // ask the new user for a name
    socket.write('Enter a Name(max 12 chars): ');

    // register a callback on the socket for the case of incoming data
    socket.on('data', function(buffer) { // buffer is a Buffer object containing the data
        if (name !== '') {  // in case this user has a name...

            // send out his message to all the other users...
            for(var i = 0; i < users.length; i++) {
                if (users[i] !== socket) { // ...but himself
                    users[i].write(name + ': '
                                   + buffer.toString('ascii').trim()
                                   + '\r\n');
                }
            }

        // otherwise take the data and use that as a name
        } else {
            name = buffer.toString('ascii').substring(0, 12).trim().replace(/\s/g, '_');
            socket.write('> You have joined as ' + name + '\r\n');

            // push this socket to the user list
            users.push(socket);
            for(var i = 0; i < users.length; i++) {
                if (users[i] !== socket) {
                    users[i].write('> ' + name + ' has joined' + '\r\n');
                }
            }
        }
    });

    // another callback for removing the user aka socket from the list
    socket.on('end', function() {
        users.splice(users.indexOf(socket), 1);
    });

// bind the server to port 8000
}).listen(8000);

Здесь нет никакой магии (кроме использования замыканий ), вам не нужно иметь дело с программированием необработанных сокетов, и у вас не будет проблем с параллелизмом. И вы узнаете некоторые из последних жарко;)

Я рекомендую вам посмотреть некоторые выступления, перечисленные в нашей вики-теге Node.js , чтобы лучше понять, как работает Node.js.

0 голосов
/ 01 января 2011

Другая тема, на которую я ответил, которая может помочь вам и легко масштабируется под ваши нужды => Как использовать redis PUBLISH / SUBSCRIBE с nodejs для уведомления клиентов об изменении значений данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...