2013-02-16 126 views
3

我正嘗試在託管服務「dotcloud」上託管nodejs應用程序。 我的nodejs使用包「websocket」來處理通信。 即。 npm install websocket在dotcloud上託管nodejs服務器

我的應用程序在筆記本電腦上運行本地主機時效果很好。但是,當我在dotcloud上部署應用程序時,它無法正常工作。

這裏是正在發生的事情:你的瀏覽器指向的URL dotcloud: pirate-captainlonate.dotcloud.com

然後,快速處理與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) 

好吧,好吧,我真的很想得到這個工作。我一直在這個永遠。讓我知道如果你還有什麼需要幫助我回答我的問題。

感謝,

--Nathan

附錄:這是服務器如何發送HTML文件。

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

偉大的問題,大量的信息,很容易找到你的問題。基本上你需要第二個http端口。我在下面的答案中解釋如何做到這一點。 – 2013-02-16 12:24:44

回答

-1

貌似你試圖訪問端口1337 WebSocket的,但你應該嘗試通過端口80

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

大多數公共平臺只有80端口反向代理到應用程序說起來,你有沒有試過在Nodejitsu上運行你的應用程序?http://nodejitsu.com

+0

所以這裏是:如果你看看http://docs.dotcloud.com/0.9/services/nodejs/,那麼你會看到dotcloud需要用戶讓他們的服務器監聽端口8080,因爲端口80需要root和我們沒有根。 果然,嘗試這樣做會產生:「Error:listen EACCES」。現在,如果明文在8080上監聽,並且http.createServer在8080上監聽,那麼你會得到:「錯誤:監聽EADDRINUSE」,因爲有兩件事佔用了一個端口,所以你會期待這一點。這是一種泡菜。 nodejitsu比dotcloud更好嗎? – Captainlonate 2013-02-16 04:55:33

+0

因此,如果服務器在端口8080上偵聽,並且您的websocketserver在另一個端口上偵聽,則一切都應該解決。這是有道理的,這將工作。但是當我嘗試它時,我根本沒有任何錯誤。頁面加載像正常,但websocket連接沒有建立... – Captainlonate 2013-02-16 04:58:37

+0

我不知道如果代碼可以在nodejitsu上工作,糾正我,如果我錯了,但根據此鏈接:https://手冊.nodejitsu.com/a-quickstart/faq#faq-how-can-i-make-my-app-use-a-port-other-port-80它說你不能聽更多的一個端口每個服務一次,上面的代碼想要一次收聽2個不同的端口。也許你可以使用代理或其他? – 2013-02-16 12:33:52

2

看起來您正在嘗試爲您的服務使用2個http端口,而dotCloud僅支持1個開箱即用,因此您需要通過在您的服務中添加一小段代碼讓他們知道您希望擁有另一個端口dotcloud.yml

下面是一個例子dotcloud.yml被請求第二個TCP端口稱爲服務器

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

一旦你添加此加推,你的服務器將給予您可以使用第2個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全部大寫。用下面的信息替換{{variable}}。

{{app_name}} =你的應用的名稱從dotcloud.yml,在上面的例子中它是app {{port_name}} =端口名,server在上述dotcloud.yml例子。

要找到此文件,您可以從應用程序environment.jsonenvironment.yml文件,shell ENV變量或登錄到dotCloud儀表板,單擊您的應用程序,然後單擊Environment選項卡以查看應用程序變量列表。

如果你做出這三個改變,你的問題應該消失。

如果你需要更多的代碼示例,請查看這個github回購,做類似於你正在做的事情。

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

+0

好吧,但如果我這樣做,那麼我的客戶端嘗試建立連接的端口是什麼?我嘗試過無端口,4242,1337,然後我試圖做出一些巨大的巨無霸,結果令人驚訝。無論我放入WebSocket()構造函數調用什麼都沒有關係,每次都得到相同的結果:沒有錯誤,沒有建立連接。 – Captainlonate 2013-02-17 05:43:17

+0

@Captainlonate我更新了答案,包括如何找出可以連接的端口來自您的客戶。 – 2013-02-17 13:44:12

+0

好的,Ken,狀態更新:我嘗試了你所說的,但是我不能在我的client.js文件中使用process.env []。無論括號'[]'中的內容如何,​​函數調用「process.env」都不被識別。 Chrome的控制檯顯示:Uncaught ReferenceError:進程未定義。爲清楚起見,這就是我的client.js文件中的行所示: var thePort = process.env ['DOTCLOUD_APP_SERVER_PORT']; 堅持我肯,我非常想要這個工作。 – Captainlonate 2013-02-17 17:53:07

1

< < <樓主這裏>>>

好吧,我得到這個對Dotcloud工作。我只是想發佈你們需要知道的東西。 如果您一直在關注此問題,最終的解決方案即將發佈。 我想感謝dotcloud的Ken讓我走上正確的道路。感謝他 我瞭解了有關environments.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']; 

好了,現在快遞(在我的情況「隨心換」),需要偵聽端口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」在Dotcloud上部署和運行我的nodejs應用程序。