在dotcloud上托管一个nodejs服务器
Hosting a nodejs server on dotcloud
我正在尝试在托管服务"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
- 将一个方法转换为promise:Nodejs
- NodeJS在一个较大的字符串中获取一个字符串的索引
- 有没有一个Nodejs库可以序列化和反序列化命名组件的路径(比如URL路径名)
- NodeJS-从同一文件中的另一个方法调用一个方法
- Nodejs一个请求阻塞另一个请求
- Ajax在NodeJS中为一个耗时的请求请求多次重试
- NodeJS:一个全局EventEmitter或每个模块它'他自己的
- NodeJS:创建一个hash并返回一个函数的值
- RethinkDB:在r.js方法中加载一个NodeJS包
- 如果一个nodejs模块将一个对象导出到另外两个模块,那么在一个下游模块中对该对象所做的更改是否会传播到另一个下游模块
- 如何创建一个nodejs websocket客户端
- 如何从我的npm模块中写入另一个nodejs项目根文件夹
- 在dotcloud上托管一个nodejs服务器
- 有一个NodeJS CLI的启动脚本
- 将get请求从一个node.js服务器转发到另一个nodejs服务器
- 将一个模块包含在另一个 nodeJS 文件中
- 从一个函数内部的 request.get 返回变量值到另一个 NODEJS 表达式
- 创建一个NodeJS模块
- 如果我构建一个NodeJS应用程序,我需要gulp或Grunt吗?
- 最小化JS的好方法是什么?CSS上传一个NodeJS应用到Heroku