PHP Socket Server与node.js:Web聊天

19

我想用长连接的HTTP请求(Comet)、ajax和Websockets(根据使用的浏览器)编写一个HTTP WebChat。用户数据库在mysql中。聊天程序用PHP编写,除了聊天流本身可能还可以用JavaScript(node.js)编写:

我不想为每个用户启动一个PHP进程,因为没有很好的方法在这些PHP子进程之间发送聊天信息。 因此,我考虑在PHP或node.js中编写自己的socket服务器,应该能够处理超过1000个连接(聊天用户)。作为纯Web开发人员(PHP),我对sockets不是很熟悉,因为我通常让Web服务器处理连接。聊天消息将不会保存在磁盘或mysql中,而是保存在RAM中的数组或对象中,以获得最佳速度。

据我所知,在单个php进程(socket服务器)中无法同时处理多个连接,但是您可以接受大量的socket连接,并在循环中逐个地处理它们(读和写;接收到的消息->写入所有socket连接)。问题是与约1000名用户有一个延迟,而mysql操作可能会减缓整个事情,从而影响所有用户。

我的问题是:Node.js是否能够处理更好性能的socket服务器?Node.js是基于事件的,但我不确定它是否能够同时处理多个事件(这不需要多线程吗?)或者是否只有一个事件队列。如果有一个事件队列,那就跟PHP一样:逐个地处理用户。

我也可以为每个聊天室生成一个PHP进程(用户较少),但据我所知,存在单线程IRC服务器,它们也能够处理成千上万的用户(用C++或其他语言编写),因此可能在PHP中也是可能的。

我更喜欢PHP而不是Node.js,因为这样项目就仅限于PHP而不是混合编程语言。但是,如果Node可以同时处理连接,我可能会选择它。

2个回答

26

JavaScript,或者说在这种情况下,Node使用的引擎V8是单线程的设计。所以是的,只有一个事件队列。

但最终,这并不是问题,总会有事情先发生,除非您使用多个处理器,即使如此,您很可能只有一张网络卡……一个路由器……你明白了吧。同时,使用1000个以上的线程……不是一个好主意,它缩放得不好,并且你会陷入并发地狱

对于Node.js来说,1000个聊天用户不是什么问题。我可以给你一个相当基本的想法,让你了解如何设置它,这个简单的聊天程序可以通过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的工作原理。


谢谢你的代码。上周我用PHP写了几乎相同的代码(甚至是“name !==''”部分也一样),所以现在我会检查它是否和node.js一样快,这样我就不需要使用两种语言了,尽管node.js很好用,而且我已经用它进行客户端脚本编写多年了(如jquery等)。 - Eliasdx
1
@Eliasdx,你有没有对比过Node.js和PHP的基准测试?我很好奇结果可能会是什么。 - Lime
@Eliasdx 有什么新消息吗?我想自己创建一个聊天,非常想知道你的发现。我个人更喜欢 PHP。 - Steven De Groote

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接