我正在尝试在托管服务"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.json
、environment.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