dotCloud で WebSocket
dotCloud が WebSocket に対応したという発表がありました。
dotCloud Announces Native Support for WebSockets | dotCloud Blog
dotCloud は多くの言語やミドルウエアに対応していて、 CLI からアプリがデプロイできる PaaS サービスといった感じです。
(Heroku なんかをイメージしてもらうとわかりやすいかも。)
早速、 Node.js + Socket.IO でどんなもんか試してみました。
アカウントは自分は結構前にとったんですが、今ならすぐ取得できるっぽいです。
CLI のインストール
専用の CLI があるのでそれをインストールするところから始めます。
http://docs.dotcloud.com/firststeps/install/ にある通り、 Python の pip で入れます。
Jxck$ sudo easy_install pip && sudo pip install dotcloud
インストールしたら、 dotcloud コマンドが使えるようになります。
最初に dotcloud コマンドを実行したら、 API key とやらを聞かれるので入力します。
API key は、メッセージの通り http://www.dotcloud.com/accounts/settings で確認できます。
Jxck$ dotcloud Warning: .dotcloud/dotcloud.conf does not exist. Enter your api key (You can find it at http://www.dotcloud.com/accounts/settings): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx error: usage: dotcloud [-h] {info,status,scale,run,logs,versions,url,setup,list,stats,var,restart,alias,rollback,push,destroy,create,ssh,history} ...
エラってね?(汗
うーん、とりあえず -h したら、 steup がそれっぽいので、もう一度やってみる。
Jxck$ dotcloud setup Enter your api key (You can find it at http://www.dotcloud.com/accounts/settings): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
できたっぽい。 ~/.dotcloud/dotcloud.conf を見てみる。
Jxck$ cat .dotcloud/dotcloud.conf { "url": "https://api.dotcloud.com/", "apikey": "xxxxxxxxxxxxxxxxxxxxxxxxxxx" }
こんなのができてる。
アプリ作成
dotCloud アプリを作成してデプロイします。
ここでは Node を使います。 Node を使ったアプリについては、
dotCloud - Node.js Service が参考になります。
まずは create コマンド。
Jxck$ dotcloud create wstest
(これは、ローカルに何かファイルを作ったりではないみたい)
好きなディレクトリを作って、 build file を作ります。名前は dotcloud.yml
Jxck$ mkdir dotcloud
Jxck$ cd dotcloud
dotcloud.yml はこんな感じ
www: type: nodejs approot: wstest
approot に実際にアプリがあるディレクトリを書きます。
ディレクトリ内には、実際のアプリと package.json, supervisord.conf などを配置します。
だからこの場合、こういう構成になります。
Jxck$ tree dotcloud dotcloud ├── dotcloud.yml └── wssample ├── package.json ├── server.js └── supervisor.conf 1 directory, 4 files
とりあえず普通の http サーバを作って動かしてみます。
サーバは server.js に実装します。しかし dotCloud ではエントリファイルは supervisor.conf で指定するため、
server.js である必要はないんですが、まあ慣習です。
また、 http サーバをデプロイする場合は、必ず 8080 ポートをリッスンする必要があるそうです。
(もちろん外からは 80 でアクセスできるので、リバース Proxy があるんでしょう)
server.js
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(8080);
supervisor.conf
ここで、実装したサーバの起動方法を指定します。
npm start に対応してないのがちょっと残念ですが、
同じ方法で別の言語も動くのでまあ、しょうがないですね。
ここで指定するから、エントリファイルは server.js でなくても実際は大丈夫です。
[program:node] command = node server.js directory = /home/dotcloud/current
デプロイ
dotcloud コマンドでできます。
見た感じ rsync で飛ばしてるみたいですね。
$ dotcloud push wstest dotcloud/ ..... Deployment finished. Your application is available at the following URLs www: http://wstest-jxck.dotcloud.com/
コマンドラインに出力されたアドレスでアクセスできます。
WebSocket
ではいよいよ、 WebSocket を使って試してみます。
ここでは Socket.IO を用いて、使用する通信を WebSocket のみにするため、
transport オプションに ['websocket'] を指定します。
静的ファイルの配信は express を用いました。(この程度なら express でも十分だった。)
package.json
依存するパッケージは package.json に書いておけば、デプロイ後に入れてくれます。
最初に npm init でプロジェクトを作り始めるとはかどります。
{ "author": "Jxck", "name": "wssample", "version": "0.0.0", "repository": { "url": "" }, "engines": { "node": "*" }, "dependencies": { "express": "*", "socket.io": "*" }, "devDependencies": {} }
サーバ
サーバはこんな感じ。
ポイントは io.set() で、 transport を指定しています。
これで socket.io は websocket の接続確立に失敗してもフォールバックをしません。
var express = require('express') , io = require('socket.io') ; var app = module.exports = express.createServer(); app.configure(function(){ app.use(express.static(__dirname + '/public')); }); io = io.listen(app); io.configure('production', function() { io.set('transports', ['websocket']); }); io.sockets.on('connection', function (socket) { console.log('connected'); socket.on('msg send', function (msg) { socket.emit('msg push', msg); socket.broadcast.emit('msg push', msg); }); socket.on('disconnect', function() { console.log('disconnected'); }); }); app.listen(8080);
クライアント
現在どの通信方法で接続を確立しているかは、
以下の場合、 socket.socket.transport の中を見るとわかります。
var socket = io.connect(); socket.on('connect', function() { console.log('connected'); console.log('transport is', socket.socket.transport); socket.emit('msg send', 'data'); socket.on('msg push', function (msg) { console.log(msg); }); });
まとめ
今回のサンプルは以下にデプロイしています。
http://wstest-jxck.dotcloud.com/
ソースは以下。
https://github.com/Jxck/dotcloud_ws_test
実行結果は以下。
WebSocket で接続できていることが確認できます。
ということで、公表されたとおり WebSocket が通っているようですね。
WebSocket が使えない PaaS (heroku とか) はまだまだ多いので、
これはひとつ大きなアドバンテージになるかもしれません。
気になるところは
- 速度
- どのくらいでるのか。これはサーバとの物理的距離も関係。
- 何使ってるの?
- おそらく dotCloud のサーバ群には Proxy などがフロントに立っているんだろうと予想できるが、何を使っているのか。
- ちなみにここに Nginx を使っている場合は、デフォルトだとできない、のでパッチなどが必要。(だから heroku は ws できないとされてる)
この辺も余裕があったら調べてみたいところですね。
あ、今更だけど、これはエイプリルネタじゃないです(汗
この記事、本当は 3 月中に書きたかった。。(月 1 でブログが目標)