在dotcloud上托管nodejs服务器

时间:2013-02-16 03:33:05

标签: javascript node.js websocket dotcloud

我正在尝试在托管服务“dotcloud”上托管nodejs应用。 我的nodejs使用包“websocket”来处理通信。 即。 npm install websocket

我的应用在笔记本电脑上的localhost上运行时效果很好。但是当我在dotcloud上部署应用程序时,它无法正常工作。

以下是正在发生的事情:您将浏览器指向dotcloud上的网址: pirate-captainlonate.dotcloud.com

然后,express用express.get('/'.......){}处理GET请求 express按照您的预期将.html页面提供给客户端。 .html文件 反过来尝试与服务器建立websocket连接。我又能得到 这在我的本地机器上运行得很好。但是,没有建立任何联系。 具体来说,dotcloud绝对是我的.html文件,但.html文件没有与服务器建立websocket连接。但是也没有调用connection.onerror。有点奇怪。

以下是一些可帮助您了解我正在做的事情的代码:

客户端:

this.connection = new WebSocket('ws://pirate-captainlonate.dotcloud.com:1337'); 

this.connection.onerror = function (error) {
        console.log("ERROR with the connection *sadface*");
    };

**** Note that I note the onerror function here to show that I do indeed have it set up, but it's not being called. It would seem that no error is being thrown.

服务器端:

var webSocketServer = require('websocket').server; // websocket
var server = require('http').createServer();
var expr = require("express"); // load the express module
var xpress = expr(); // xpress now holds the server object

// Helps Node serve the game.html page upon a get request
xpress.configure(function() {
    xpress.use(expr.static(__dirname + "/public"));
     xpress.set("view options", {layout: false});
});

// All requests to root serve the game.html page
xpress.get('/', function(req, res) {
    res.sendfile(__dirname + '/public/game.html');
});

// What ports to listen on
var webSocketsServerPort = 1337;
xpress.listen(8080);
server.listen(webSocketsServerPort, function() {
    console.log((new Date()) + " Server is listening on port " + webSocketsServerPort);
});

// WebSocket Server
var wsServer = new webSocketServer({
    httpServer: server
});

这应该足够代码向您展示它是如何工作的。现在你们中的一个人可能会问,“>> dotcloud logs”是什么?

[www.0] ==> /var/log/supervisor/app.log <==
[www.0] Sat Feb 16 2013 02:57:59 GMT+0000 (UTC) Server is listening on port 1337
[www.0] ==> /var/log/supervisor/supervisord.log <==
[www.0] 2013-02-16 02:57:57,946 WARN Included extra file "/home/dotcloud/current/supervisord.conf" during parsing
[www.0] 2013-02-16 02:57:58,033 INFO RPC interface 'supervisor' initialized
[www.0] 2013-02-16 02:57:58,033 WARN cElementTree not installed, using slower XML parser for XML-RPC
[www.0] 2013-02-16 02:57:58,033 CRIT Server 'unix_http_server' running without any HTTP authentication checking
[www.0] 2013-02-16 02:57:58,038 INFO daemonizing the supervisord process
[www.0] 2013-02-16 02:57:58,039 INFO supervisord started with pid 140
[www.0] 2013-02-16 02:57:59,048 INFO spawned: 'app' with pid 154
[www.0] 2013-02-16 02:58:00,290 INFO success: app entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
[db.0] ==> /var/log/mongodb/mongodb.log <==
[db.0] Sat Feb 16 01:45:02 [conn4] end connection 127.0.0.1:51326 (0 connections now open)

好吧,我真的很想让这个工作。我一直在这里。让我知道你们还有什么需要帮助我回答我的问题。

谢谢,

- 森

附录:这是服务器发送html文件的方式。

xpress.get('/', function(req, res) {
    res.sendfile(__dirname + '/public/game.html');
});

3 个答案:

答案 0 :(得分:2)

看起来您正在尝试使用2个http端口进行服务,而dotCloud仅支持1个开箱即用,因此您需要通过在{{{{{{{{{{{{ 1}}

这是一个示例dotcloud.yml,它要求第二个名为 server 的tcp端口

dotcloud.yml

一旦添加并推送,您的服务器将获得可用于服务器的第二个TCP端口,您只需要通过从环境文件中获取值来找出哪个端口。

这是一个从ENV获取端口的代码片段,默认情况下会默认为4242,因此您仍然可以在本地运行。

app:
    type: nodejs
    ports:
       server: tcp
    config:
       node_version: v0.8.x

如果您想知道我如何获得ENV变量名称,那很简单。它将是PORT_,然后是var webSocketsServerPort = process.env['PORT_SERVER'] || 4242; 中名称的大写字符串。由于我上面使用了服务器,它变成了 PORT_SERVER ,如果我使用了节点,它就是PORT_NODE,所以把你想要的东西,但要确保这些值匹配。

<强>客户端:

要找出您需要在客户端上连接的端口,您需要再次返回环境变量。这次您正在寻找一个看起来像dotcloud.yml的变量。 重要您的变量名称可能不同

我是如何获得该envirornment变量名称的?

变量的名称看起来像DOTCLOUD_APP_SERVER_PORT全部大写。将{{variable}}替换为以下信息。

DOTCLOUD_{{app_name}}_{{port_name}}_PORT =您的dotcloud.yml中应用的名称,在上面的示例中为{{app_name}} app =端口名称,上面的dotcloud.yml示例中为{{port_name}}

要找到这个,您可以从应用serverenvironment.json文件,shell ENV变量中获取,或登录dotCloud信息中心,点击您的应用,然后点击环境标签应用程序变量列表。

如果你做了这三个改变,你的问题就会消失。

如果您需要更多代码示例,请查看此github repo,其中包含与您尝试执行的操作类似的操作。

https://github.com/3on/node-tcp-on-dotcloud

答案 1 :(得分:1)

&LT;&LT;&LT;原始海报在这里&gt;&gt;&gt;

好吧,我让这个在Dotcloud上工作。我只想发布你们需要知道的内容。 如果您一直在关注此问题,那么即将发布最终解决方案。 我要感谢来自dotcloud的Ken让我走上了正确的道路。谢谢他 我了解了environment.yml,environments.json文件。另外,做一个

console.log(process.env);
服务器端的

是一个HUUGE助手。 KK在这里解决方案:

首先,我希望您了解我如何声明我的要求和变量:

var webSocketServer = require('websocket').server; // websocket
var server = require('http').createServer();
var expr = require("express"); // load the express module
var xpress = expr(); // xpress now holds the server object

好吧,既然你知道这些东西是什么,我需要告诉你我决定了 使用ejs渲染模板。我遇到的一个问题是我需要我的客户能够 “知道”通过WebSocket连接到服务器的端口。如果没有websocket连接,我还有什么方法可以给客户端提供一个像“port”这样的变量。请记住,端口可能会发生变化,所以我不能只是在我的ws:// url末尾硬编码像50234这样的端口。解决方案是使用“ejs”。

ejs是一个模块(即“npm install ejs”)我真的不会解释如何使用它。 但这是我以前学过的网站:http://embeddedjs.com/

以下是您需要了解的一些事项: 当客户将其浏览器指向您的dotcloud网址时,这就是您发送它们的方式 在我的情况下,我将.html文件更改为.ejs文件,以便我可以将其渲染为 模板。

xpress.get('/', function(req, res) {
    res.render('game', 
    {
        answer: superCoolPort
    });
});

'游戏'意味着在我告诉服务器寻找模板的任何文件夹中都应该有 一个名为game.ejs的文件。 注意我是如何用一些数据渲染名为game.ejs的模板的。在这种情况下 数据是我的server.js文件中的一个名为“superCoolPort”的局部变量。这是什么 该变量是:

var superCoolPort = process.env['DOTCLOUD_WWW_SERVER_PORT'];

好的,现在快递(在我的情况下是'xpress'),需要监听8080端口。

xpress.listen(8080);

这不是您的WebSocket尝试连接的端口。这是港口 您的浏览器尝试连接到该页面。但是,Dotcloud不允许你这样做 在端口80上托管任何东西,所以如果你在8080上托管它,它们会为你重定向到80。这样,您无需在浏览器中键入url:8080。

现在让我解释一下http服务器如何变成wsServer。基本上你设置了 http服务器并使其侦听端口。然后你将这个http服务器挂载到 websocket服务器。看看我在顶部声明“服务器”的位置?

这是http服务器要监听的端口。请注意,这意味着websocket服务器也将侦听此端口。

var webSocketsServerPort = process.env['PORT_SERVER'] || 4242;
server.listen(webSocketsServerPort, function() {
    console.log((new Date()) + "The http server is listening on port " + webSocketsServerPort);
});

// WebSocket Server
var wsServer = new webSocketServer({
    // WebSocket server is tied to a HTTP server. WebSocket request is just
    // an enhanced HTTP request.
    httpServer: server
});

在我转到客户端之前,我想让您知道如何设置我的快速配置。

xpress.configure(function() {
     // Sets the directory to look for templates
     xpress.set('views', __dirname + '/public');
     // This line tells Express that we are using the ejs engine to render templates
     xpress.set('view engine', 'ejs');
     xpress.use(expr.static(__dirname + "/public"));
     xpress.set("view options", {layout: false});
});

以上所有内容都是对server.js文件的修改。

好的,接下来我会谈论模板。我曾经有一个名为game.html的文件。好吧,我想要 这是一个模板,我可以使用一些数据(websocket的端口号)进行渲染 需要连接)。所以首先我将文件的名称更改为game.ejs。 然后,我做了一些修改如下:

<body onload="init()">

成了

<body data-port="<%=answer%>" onload="init()">

看看onload =“init()”如何?这意味着在页面加载之前不会调用init。 这很重要,因为当我们想要访问端口时,您无法保证这一点 除非你在“init()”里面,否则它是可用的。我知道这是因为我试图访问 在我定义init()之前,它说变量为null。

现在在init()内部,您可以像这样访问端口号:

var port = $('body').data('port');

现在我的client.js文件可以像这样初始化websocket连接:

this.connection = new WebSocket('ws://pirate-captainlonate.dotcloud.com:' + this.thePort);

其中“this.thePort”与上面的“port”相同。

我想让这个解决方案尽可能完整,所以这里是我的dotcloud.yml文件。它坐着 我的server.js文件上面的一个目录:

www:
    type: nodejs
    approot: app
    ports:
        server: tcp
    processes:
        app: node app.js
    config:
        node_version: v0.8.x

db:
    type: mongodb

这是我的package.json文件。它与我的server.js文件位于同一目录中(在我的情况下实际上称为app.js):

{
  "name": "app",
  "version": "0.0.0",
  "scripts": {
    "start" : "node app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies":{
      "express" : "",
      "mongodb" : "",
      "fs": "",
      "ejs": "",
      "ws": "",
      "websocket": ""
  },
  "repository": "",
  "author": "",
  "license": "BSD"
}

最后,老实说我不知道​​这是否有必要,但这是我的 supervisord.conf文件。它与server.js位于同一目录中。

[program:node]
command = node app.js
directory = /home/dotcloud/current

我觉得这就是一切。 我希望我没有遗漏任何东西。但最终,这些变化才是我所需要的 使用“websocket”获取我的nodejs应用程序以在Dotcloud上部署和运行。

答案 2 :(得分:-1)

看起来您正在尝试访问端口1337上的WebSocket,但您应该尝试通过端口80.

this.connection = new WebSocket('ws://pirate-captainlonate.dotcloud.com');

大多数公共平台只通过端口80向您的应用程序反向代理。说到,您是否尝试在Nodejitsu上运行应用程序? http://nodejitsu.com