3

ホスティングサービス「dotcloud」でnodejsアプリをホストしようとしています。私のnodejsは、パッケージ「websocket」を使用して通信を処理します。すなわち。npm installwebsocket

私のアプリは、ラップトップのローカルホストで実行されているときにうまく機能します。しかし、アプリを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
});

これは、それがどのように機能しているかを皆さんに示すのに十分なコードであるはずです。さて、あなたの一人はおそらく「>>dotcloudlogs」は何を示しているのかと尋ねるでしょう。

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

3 に答える 3

2

サービスに2つのhttpポートを使用しようとしているようですが、dotCloudはすぐに使用できるポートを1つしかサポートしていないため、小さなスニペットを追加して、別のポートが必要であることを通知する必要があります。dotcloud.yml

これは、サーバーdotcloud.ymlと呼ばれる2番目のtcpポートを要求している例です。

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

これを追加してプッシュすると、サーバーに使用できる2番目のTCPポートがサーバーに与えられます。環境ファイルから値を取得して、どのポートであるかを確認する必要があります。

これは、ENVからポートを取得するスニペットです。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}}=上記のdotcloud.ymlの例ではポート名serverです。

これを見つけるには、アプリenvironment.jsonenvironment.ymlファイル、シェルENV変数から取得するか、dotCloudダッシュボードにログインし、アプリをクリックしてから、[環境]タブをクリックしてアプリケーション変数のリストを表示します。

これらの3つの変更を行うと、問題は解決するはずです。

さらにコード例が必要な場合は、このgithubリポジトリをチェックして、実行しようとしていることと同様のことを実行してください。

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

于 2013-02-16T12:22:53.937 に答える
1

<<<オリジナルポスターはこちら>>>

了解しました。これをDotcloudで動作させることができました。皆さんが知っておくべきことを投稿します。この問題をフォローしている場合は、最終的な解決策が投稿されようとしています。正しい道を歩んでくれたdotcloudのKenに感謝します。彼のおかげで、environments.yml、environments.jsonファイルについて学びました。さらに、

console.log(process.env);

サーバー側にはHUUGEヘルパーがいました。KKはここで解決策を示します:

まず、requiresとvariablesをどのように宣言するかを見てもらいたいです。

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接続がすでに確立されていない場合、他にどのようにして「ポート」などの変数をクライアントに提供するのでしょうか。ポートが変更される可能性があることに注意してください。そのため、ws://urlの最後に50234などのポートをハードコーディングすることはできませんでした。解決策は「ejs」を使用することでした。

ejsはモジュールです(つまり、「npm install ejs」)。実際には、その使用方法については説明しません。しかし、これは私が学んだウェブサイトです:http: //embeddedjs.com/

知っておくべきことがいくつかあります。クライアントがブラウザでdotcloudurlを指定すると、このようにしてファイルが送信されます。私の場合は、.htmlファイルを.ejsファイルに変更して、次のようにレンダリングできるようにしました。テンプレート。

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

「ゲーム」とは、サーバーにテンプレートを探すように指示したフォルダーに、game.ejsという名前のファイルがあるはずであることを意味します。game.ejsというテンプレートをいくつかのデータでレンダリングしていることに注目してください。この場合、データは「superCoolPort」と呼ばれる私のserver.jsファイルのローカル変数です。これはその変数が何であるかです:

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ファイルの1つ上のディレクトリにあります。

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にデプロイして実行するために必要なものでした。

于 2013-02-18T22:55:45.247 に答える
-1

Looks like you're trying to access the WebSocket on port 1337, but you should be trying over port 80.

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

Most public platforms only reverse proxy to your application over port 80. Speaking of, have you tried running your application on Nodejitsu? http://nodejitsu.com

于 2013-02-16T04:39:30.750 に答える