Я хочу запрограммировать HTTP WebChat, используя длинные HTTP-запросы (Comet), ajax и websockets (в зависимости от используемого браузера). База данных пользователя находится в mysql. Чат написан на PHP, за исключением, может быть, самого потока чата, который также может быть записан в javascript (node.js):
Я не хочу запускать php-процесс для каждого пользователя, так как нет хорошего способа отправить чат-сообщения между этими дочерними блоками php. Поэтому я подумал о написании собственного сервера сокетов в PHP или node.js, который должен иметь возможность обрабатывать более 1000 подключений (пользователей чата). Как чисто веб-разработчик (php), я не очень хорошо разбираюсь в сокетах, поскольку я обычно позволяю веб-серверу заботиться о соединениях. Сообщения чата не будут сохранены на диске или в mysql, а в ОЗУ как массив или объект для лучшей скорости.
Насколько я знаю, нет способа одновременно обрабатывать несколько соединений в одном php-процессе (сервер сокетов), однако вы можете принимать большое количество соединений сокетов и обрабатывать их последовательно в цикле (чтение и запись; message -> write для всех соединений сокетов). Проблема в том, что наиболее вероятно будет отставание от ~ 1000 пользователей, а операции с mysql могут замедлить все это, что повлияет на всех пользователей.
Мой вопрос: может ли node.js обрабатывать сервер сокетов с лучшей производительностью? Node.js основан на событиях, но я не уверен, может ли он обрабатывать несколько событий одновременно (не нужно многопоточность?) Или если есть очередь событий. С очередью событий это будет точно так же, как php: обрабатывать пользователя после пользователя.
Я мог бы также генерировать php-процесс в чате (гораздо меньше пользователей), но у afaik есть однопоточные IRC-серверы, которые также способны обрабатывать тысячи пользователей. (написано на c ++ или что-то еще), поэтому, возможно, это также возможно в php.
Я бы предпочел PHP над Node.js, потому что тогда проект был бы php-only, а не смесью языков программирования. Однако, если Node может обрабатывать соединения одновременно, я бы выбрал его.
JavaScript, или в этом случае V8, который является движком, используемым Узлом, по дизайну однопоточный. Так что да, есть очередь событий.
Но в конце концов, это не проблема, что-то всегда будет происходить в первую очередь, если вы не используете несколько процессоров, и даже тогда у вас, скорее всего, будет только одна сетевая карта … один маршрутизатор … вы получите эту идею. Кроме того, использование 1000+ потоков … не очень хорошая идея, плохо масштабируется, и вы окажетесь в параллельном HELL .
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.
Еще одна тема, на которую я ответил, которая может вам помочь, и будет легко масштабироваться в соответствии с вашими потребностями. => Как использовать redis PUBLISH / SUBSCRIBE с nodejs для уведомления клиентов при изменении значений данных?