Nodejs vs PHP的性能问题
发布于 3年前 作者 mackjoner 4460 次浏览

系统:Joyent smartmachine

nodejs:0.6.6

nginx+nodejs测试hello world

nginx反向代理配置

upstream nodejs {
    server 127.0.0.1:9880 fail_timeout=10s;
}
server
{
listen       80;
server_name test.nodejs;
index index.php index.html index.htm;

location  / {
    #try_files $uri /index.php;
    proxy_pass http://nodejs;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_connect_timeout 30s;
    proxy_read_timeout 2s;
}


location  ~ \.(php|php5)$ {
        fastcgi_pass  unix:/tmp/fastcgi.socket;
        fastcgi_index index.php;
        include fastcgi.conf;
}

location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
        expires      30d;
}

location ~* \.(js|css)$ {
        expires      1h;
}
location ~* \.(ini|inc)$ {
        deny all;
}

}

测试代码

 var cluster = require('cluster');
 var http = require('http');
 var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    for (var i = 0; i < numCPUs; i++) {
       cluster.fork();
  }

  cluster.on('death', function(worker) {
      console.log('worker ' + worker.pid + ' died');
  });
 } else {
     http.Server(function(req, res) {
         res.writeHead(200);
         res.end("hello world\n");
     }).listen(9880);
 }

云服务上是24个cpu,所以查看nodejs进程得到了24个进程数,测试并发请求的网络环境是8M。 LoadRunner测试的结果,400个并发,响应的平均时间是0.78s,TPS只有400多。nginx+php的应用测试结果远远高于以上nodejs的值,能到1000多TPS,平均响应时间在0.1s。

请问这里的nodejs性能瓶颈在哪里,关键还没有带业务测试,业务需要ssl和mysql,响应就更加慢了。

12 回复

upstream nodejs 应该编写10组 server吧,这样才能负载均衡

24个node进程监听同一个端口,没报错么?

400并发应该都发送到了同一个进程上了吧?

分24个端口试试,当然还有更好的办法,监听 unix socket,nginx upstream 是可以代理 unix socket的。

24组 server ~

Joyent smartmachine ,哇 , 好新潮啊

就是调用了nodejs内置了的cluster去分配的cpu资源,起写了一个server监听一个端口,而且测试的时候,发现只有前面的几个进程有cpu使用率(0.1%),后面的一大串nodejs进程均为cpu 0%。

明天用socket和增加端口的方式在测试一下,非常谢谢你的这些指导意见 :-)

说实在的,那个服务器我们不可控,那个完全是公司花钱买服务了。

使用 node-cluster 模块试试?这样可以对比测试,加nginx和直接压node都是可以的。

我看node server代码没什么问题啊。

不过24 cpu也太强大了。

var cluster = require(‘cluster’); 这个nodejs内置的和你说的node-cluster模块之间有什么区别吗,我今天又测试了,关闭了socket连接池。加nginx,20个并发,平均响应时间0.188s,50个并发,平均响应时间0.475s,100并发,0.840s

var cluster = require('cluster');
var https = require('https');
var fs = require('fs');
var numCPUs = require('os').cpus().length;

var options = {
  key: fs.readFileSync('/opt/local/etc/nginx/server.key'),
  cert: fs.readFileSync('/opt/local/etc/nginx/public.crt')
};

options.agent = false;

if(cluster.isMaster){
        for(var i = 0;i < numCPUs; i++){
                cluster.fork();
        }
        cluster.on('death',function(worker){
                console.log('worker ' + worker.pid + ' died');
        });
}else{
        https.createServer(options, function (req, res) {
        res.writeHead(200);
        res.end("hello world\n");
        }).listen(9880);
}

用git下载了这个模块,运行例子有错误日志输出,这个错误你之前遇到过吗

    localhost:demo yangzhaojie$ node main.js 
    [master] new worker forked (890:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/echo.js) for 8080
    [master] new worker forked (891:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/echo.js) for 8080
    [master] new worker forked (892:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/echo.js) for 8080
    [master] new worker forked (893:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/echo.js) for 8080
    [master] new worker forked (894:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/http.js) for 33749
    [master] new worker forked (895:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/multi_port_http.js) for 33750, 33751
    [master] new worker forked (896:/Users/yangzhaojie/tech/nodejs/node-cluster/demo/worker/multi_port_http.js) for 33750, 33751
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore
    [worker] Error: EPERM, Operation not permitted, ignore

fish,我看了api,node.js监听socket,但是node.js生成的unix socket file不是socket文件,就是一个普通文件,

var net = require('net');
var fs = require('fs');
var sock;

// Create socket file
fs.open('/tmp/node.test.sock', 'w+', function(err, fdesc){
if (err || !fdesc) {
    throw 'Error: ' + (err || 'No fdesc');
}

// Create socket
sock = new net.Socket({ fd : fdesc });
console.log(sock);
});

@mackjoner 你这样子肯定是个普通文件,fdesc 是 fs模块创建的

var serv = net.createServer(function(client){
    client.on('data',function(){
        // TODO client action
    })
})
serv.listen('path.sock');

这样子创建的,是个sock

谢谢@fish nginx开启了ssl,代理unix socket文件,node.js监听这个文件,这个模式下,并发性能还有什么办法提高吗,现在的测试结果是和nginx+php+fastcig (unix socket)的性能持平,不过并发时的错误数比php少。但是response time都比较慢,800agents平均4.7s

@mackjoner

Error: EPERM, Operation not permitted, ignore

这个问题你后来怎么觉得的?

回到顶部