我正在尝试在托管服务“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');
});
答案 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}}
。
要找到这个,您可以从应用server
,environment.json
文件,shell ENV变量中获取,或登录dotCloud信息中心,点击您的应用,然后点击环境标签应用程序变量列表。
如果你做了这三个改变,你的问题就会消失。
如果您需要更多代码示例,请查看此github repo,其中包含与您尝试执行的操作类似的操作。
答案 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