【问题标题】:Phusion Passenger Error: http.Server.listen() was called more than oncePhusion 乘客错误:http.Server.listen() 被多次调用
【发布时间】:2013-12-17 21:39:37
【问题描述】:

我想用 nginx 在 phusion 乘客上执行一个简单的 node-http-proxy 示例。 您可以在 https://github.com/nodejitsu/node-http-proxy 上找到此示例代码。

var http = require('http'),
httpProxy = require('http-proxy');
//
// Create your proxy server
//
httpProxy.createServer(9000, 'localhost').listen(8000);

//
// Create your target server
//
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

如果我执行此代码,我会收到以下错误。

App 28096 stderr: /usr/share/passenger/helper-scripts/node-loader.js:157
App 28096 stderr:       throw new Error("http.Server.listen() was called more than once, which " +
App 28096 stderr:             ^
App 28096 stderr: Error: http.Server.listen() was called more than once, which is not allowed because Phusion Passenger is in auto-install mode. This means that the first http.Server object for which listen() is called, is automatically installed as the Phusion Passenger request handler. If you want to create and listen on multiple http.Server object then you should disable auto-install mode.

比我在 google 群组https://groups.google.com/forum/#!topic/phusion-passenger/sZ4SjU8ypwc 上找到一个帖子并添加

PhusionPassenger.configure({ autoInstall: false });

在我第一次调用“createServer(...).listen(port)”之前。

下一步是将监听方法的端口参数的值替换为值“passenger”。但我没有成功。有没有人设法让它运行?

--- 我的解决方案---

感谢Hongli 的建议“接下来,您需要修改一个(并且只有一个)调用......”。这解决了我的问题。

var http = require('http'),
    httpProxy = require('http-proxy');

if (typeof(PhusionPassenger) != 'undefined') {
  PhusionPassenger.configure({ autoInstall: false });
}

httpProxy.createServer(9000, 'localhost').listen('passenger');

var target_server = http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

【问题讨论】:

    标签: node.js nginx passenger http-proxy


    【解决方案1】:

    2015 年 7 月 28 日更新:此答案现已纳入官方旅客文档。最新答案请参考https://www.phusionpassenger.com/library/indepth/nodejs/reverse_port_binding.html


    Phusion 乘客作者在这里。首先,让我解释一下为什么会出现这个错误。

    the Node.js tutorial 中所述,Phusion 乘客 inverses port binding 通过连接到 http.Server.listen()。如果有多个listen(),那么Passenger不知道使用哪个http.Server对象来接收请求,所以会抛出这个错误。

    要解决这个问题,你需要告诉乘客“我想明确指定使用哪个 http.Server 来接收请求”。这分两步完成。首先,您必须在程序中尽早调用以下代码:

    if (typeof(PhusionPassenger) != 'undefined') {
        PhusionPassenger.configure({ autoInstall: false });
    }
    

    接下来,您需要修改一个(也是唯一一个)http.Server.listen() 的调用,并使其传递 'passenger' 的参数:

    server.listen('passenger');
    

    如果乘客注意到您有多个listen('passenger') 呼叫,它会抱怨。你只能拥有一个。

    从 Phusion Passenger 4.0.52 开始,您还可以将 '/passenger' 作为参数传递。这是为了支持 Hapi.js(见下文)。

    Express.js 示例

    这是一个使用 Express 框架的完整示例。您必须将 'passenger' 传递给 Express 的 listen() 调用。

    if (typeof(PhusionPassenger) != 'undefined') {
        PhusionPassenger.configure({ autoInstall: false });
    }
    
    var express = require('express');
    var app = express();
    app.get('/', function(req, res){
        var body = 'Hello World';
        res.setHeader('Content-Type', 'text/plain');
        res.setHeader('Content-Length', body.length);
        res.end(body);
    });
    
    if (typeof(PhusionPassenger) != 'undefined') {
        app.listen('passenger');
    } else {
        app.listen(3000);
    }
    

    Hapi.js 示例

    使用 Hapi.js 时,您必须将 '/passenger'(而不是 'passenger')传递给 Hapi 的服务器构造函数。这将导致 Hapi 尝试在 Unix 域套接字上侦听,从而允许 Phusion Passenger 的覆盖启动。如果您不传递该初始斜杠,则 Hapi 将尝试将参数视为 TCP/IP 域名,而 Hapi 将因错误而失败。

    if (typeof(PhusionPassenger) != 'undefined') {
        PhusionPassenger.configure({ autoInstall: false });
    }
    
    var Hapi = require('hapi');
    var server;
    
    if (typeof(PhusionPassenger) != 'undefined') {
        // Requires Phusion Passenger >= 4.0.52!
        server = new Hapi.Server('/passenger');
    } else {
        server = new Hapi.Server('localhost', 3000);
    }
    
    server.route({
        method: 'GET',
        path: '/hello',
        handler: function (request, reply) {
            reply('hello world');
        }
    });
    
    server.start();
    

    【讨论】:

    • 你如何使用 Hapi.js 做到这一点?专门将 hapi 服务器设置为主服务器,但在上面的示例中还有另一个...
    • @blakmatrix 我添加了一个关于 Hapi.js 的部分。请注意,它需要 Phusion Passenger 4.0.51,该版本尚未发布,但很快就会发布。
    • 非常感谢。我会留意新版本的!
    • 我已经完成了上面的请求示例我仍然有“http.Server.listen() 被多次调用”错误
    • @Hongli 这是我的帖子,你能看一下吗stackoverflow.com/questions/68956572/…
    【解决方案2】:

    Hapi.js v8.x.x

    对于 hapi 版本 > v6.x.x 使用这种形式:

    // http://stackoverflow.com/questions/20645231/phusion-passenger-error-http-server-listen-was-called-more-than-once/20645549
    if ('undefined' !== typeof(PhusionPassenger)) {
      PhusionPassenger.configure({autoInstall: false});
    }
    
    var Hapi   = require('hapi'),
        server = new Hapi.Server(settings.server);
    
    if ('undefined' !== typeof(PhusionPassenger)) {// Requires Phusion Passenger >= 4.0.52!
      server.connection({port: '/passenger'});
    } else {
      server.connection({port: 3000, host: 'localhost'});
    }
    
    server.route({
        method: 'GET',
        path: '/hello',
        handler: function (request, reply) {
            reply('hello world');
        }
    });
    
    // Start the server
    server.start(function serverStart() {
      server.log(['server'], 'Server@' + settings.hostname + ' (' + server.info.host + ')' + ' started at port ' + server.info.port);
    });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      相关资源
      最近更新 更多