在dotcloud上托管一个nodejs服务器

Hosting a nodejs server on dotcloud

本文关键字:一个 nodejs 服务器 dotcloud      更新时间:2023-09-26

我正在尝试在托管服务"dotcloud"上托管一个nodejs应用程序。我的nodejs使用包"websocket"来处理通信。即。npm install websocket

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

这是正在发生的事情:您将浏览器指向 dotcloud 上的 url: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
});

这应该足以让你们了解它是如何工作的。现在你们中的一个人可能会问,">>点云日志"显示什么?

[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');
});

看起来您正在尝试为您的服务使用 2 个 http 端口,而 dotCloud 仅支持开箱即用的 1 个端口,因此您需要通过在dotcloud.yml中添加一个小片段来让他们知道您想要另一个

端口

下面是一个示例dotcloud.yml,它要求第二个称为服务器的 tcp 端口

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

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

这是一个代码片段,它将从 ENV 获取您的端口,当不存在时,它将默认为 4242,因此您仍然可以在本地运行。

var webSocketsServerPort = process.env['PORT_SERVER'] || 4242;

如果你想知道我是如何得到 ENV 变量名称的,这很简单。 它将PORT_,然后是dotcloud.yml名称的大写字符串。由于我在上面使用了服务器,它变得PORT_SERVER,如果我使用节点,它就会PORT_NODE,所以放你想要的,但要确保这些值匹配。

客户:

要了解需要在客户端上连接到哪个端口,您需要再次返回到环境变量。这次您正在寻找一个看起来像这样的变量 DOTCLOUD_APP_SERVER_PORT .重要提示您的变量名称可能不同

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

变量的名称看起来像这样DOTCLOUD_{{app_name}}_{{port_name}}_PORT全部大写。将 {{变量}} 替换为以下信息。

{{app_name}} = 来自 dotcloud.yml 的应用程序名称,在上面的示例中,它是app {{port_name}} = 端口名称,server上面的 dotcloud.yml 示例中。

要找到它,您可以从您的应用程序environment.jsonenvironment.yml文件、shell ENV 变量或登录 dotCloud 仪表板,单击您的应用程序,然后单击环境选项卡以查看您的应用程序变量列表。

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

如果您需要更多代码示例,请查看此 github 存储库,该存储库执行与您尝试执行的操作类似的操作。

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

<<<原始海报在这里>>>

好吧,我得到了这个在Dotcloud上工作。我只是要发布你们需要知道的内容。如果您一直在关注此问题,则即将发布最终解决方案。我要感谢来自dotcloud的Ken让我走上了正确的道路。多亏了他我了解了 environment.yml、environment.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 url时,这就是您发送它们的方式一个文件,就我而言,我将.html文件更改为 .ejs 文件,以便我可以将其呈现为一个模板。

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

"game"意味着在我告诉服务器查找模板的任何文件夹中,都应该有一个名为 game.ejs 的文件。请注意我如何使用一些数据呈现名为 game.ejs 的模板。在这种情况下数据是我的服务器中的局部变量.js名为"superCoolPort"的文件。这就是什么该变量为:

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

好的,现在快递(在我的例子中是"xpress"(,需要侦听端口 8080。

xpress.listen(8080);

这不是您的 WebSocket 将尝试连接的端口。这是端口您的浏览器尝试连接到该页面。但是,点云不允许您在端口 80 上托管任何内容,因此,如果您将其托管在 8080 上,他们会为您将其重定向到 80。这样,您无需在浏览器中键入 url:8080。

现在让我解释一下 http 服务器是如何变成 wsServer 的。基本上你设置HTTP 服务器并使其侦听端口。然后,将此 http 服务器挂载到网络套接字服务器。看到我在顶部声明"服务器"的位置吗?

这是 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});
});

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

好的,接下来我将讨论模板。我曾经有一个名为game.html的文件。好吧,我想要这是一个模板,我可以用一些数据(websocket 的端口号需要连接(。所以首先我把文件名改成了game.ejs。然后,我做了一些修改,如下所示:

<body onload="init()">

成为

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

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

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

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

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

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

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

我想使这个解决方案尽可能完整,所以这是我的dotcloud.yml文件。它坐着我的服务器上方的一个目录.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文件。它与我的服务器.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"
}

最后,老实说,我不知道这是否必要,但这是我的主管.conf 文件。它与服务器.js位于同一目录中。

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

嗯,我认为这就是一切。我希望我没有遗漏任何东西。最终,这些变化是我需要的使用"websocket"获取我的nodejs应用程序,以便在dotcloud上部署和运行。

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

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

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