実は、 AV女優.com は裏で Node.js が走っています。
表のウェブサーバは、
で紹介した通り、Nginxです。
では、どこでNode.jsを使っているか。
こっそりと設置された、流行っていない AV女優.com アダルト掲示板 です。
ここのところ、Node.jsはとても人気者ですが、その記事の大半は入門記事です。
今回は、取り上げられることの少ない、 本番環境 でのNode.jsの運用ノウハウをシェアします。
最後には、運用に役立ちそうなリンクもまとめてみます。
AV女優.comのサーバ構成
Node.jsを使って構成を考えるとき、真っ先に悩むのが、 データの保存先とその方法 です。
入門として良く上がる、チャットシステムであれば、データを保存する必要はありません。
リアルタイム・メッセージングを体験するのが目的であるためです。
例えば、次のNode.js入門の記事でもデータは保存していません。
- Nodeで作る人工無脳
- Node.js と Socket.IO を使ったNode.js入門です。
ステップ・バイ・ステップで書かれており、大変分かりやすい記事です。
しかし、データの保存に関してはノータッチです。
しかし、本番環境で運用する場合、入力されたデータを投げ捨てる訳にはいきません。
そこで、簡単に思いつくのは、Node.jsに データベース を扱わせることです。
- node.jsとMySQLで割と普通のデータベースウェブアプリを作ってみるチュートリアル
- Node.jsとMySQLを使った ベーシックなウェブ・アプリケーション開発 です。
この記事も、Node.jsを使ったウェブ・アプリケーション開発の入門に最適です。
しかし、これには若干、気になる点があります。
- 1. データのバリデーションをNode.js側で処理する必要がある
- 通常のウェブ・アプリケーションであれば、 Node.jsだけで構成されているのは稀 です。
その他にPHPやPythonと言った、ベーシックなサーバ・サイド・スクリプト言語で書かれたアプリケーションも存在するでしょう。
これらのアプリケーションも、データのバリデーション・ロジックを持っています。
これをNode.jsで同じように実装してしまうと、コードがDRYになりません。 - 2. Node.jsの開発ノウハウが足りない
- データの取り扱い は、セキュリティ上、最も気を使うところです。
Node.jsを使い始めたばかりの状態で、ここをNode.js上に実装してしまうのは、少し気が引けます。
慣れない環境で、バグを作り込んでしまいそうです。
そこで、 AV女優.com では、データの保存や読み込みは全て、 CakePHP (AV女優.com はCakePHPで出来ています) に任せることにしました。
Node.jsは リアルタイム・メッセージング だけを担当します。
AV女優.com のサーバ構成です。

掲示板のメッセージの書き込みは全て、 Node.js を仲介します。
図を見れば分かりますが、流れは次のようになります。
- Node.jsがメッセージを受け取ります。
- Node.jsは何も加工せず、CakePHPに渡します。
- CakePHPがデータのバリデーションを実行し、データベースにメッセージを書き込みます。
- 書き込みが成功したら、CakePHPはJSONで結果をNode.jsに渡します。
- 受け取った結果を、何も加工せず、Node.jsに接続しているクライアントにブロードキャストします。
この流れを作ることで、データを保存しつつ、リアルタイム・メッセージングを実現出来ます。
しかも、コードは DRY です。
もし、既にメッセージ書き込みのロジックが、 (Node.js側でない) アプリケーションに実装済みなら、Node.jsのコードとクライアントのJavaScriptを少し書くだけで、OKです。
既存のアプリケーションを簡単にリアルタイム対応出来ます。
ウェブ・サーバとNode.js間で通信を行うため、余計なコストが掛かってしまいますが、そこは開発コストとのトレード・オフですね。
Node.jsとSocket.IOを使って、メッセージング・サーバを開発する
実際に、Node.jsのコードから、先ほど紹介した構成を理解します。
AV女優.com で走っているNode.jsは、ほんの 139行のコード で動いています (ちなみにプロジェクト名は、 ohyes です)。
ウェブ・サーバとNode.jsが通信する部分のサンプル・コードを上げておきます:
// モジュールの読み込みと、settings変数を用意する。 var http = require('http'), io = require('socket.io'), settings = { app_host: 'localhost', app_port: 80, }; // Socket.IOを初期化し、待ち受ける。 var socket = io.listen(app); // メッセージを受け取ったら、write()関数を呼び出す。 socket.on('connection', function(client) { client.on('message', function(data) { write(client, data); }); }); /** * 掲示板への書き込み * client: Socket.IOのclientオブジェクト * data: POSTでNode.jsに渡されたデータ一式 */ function write(client, data) { // dataにはメッセージの他に、ユーザ認証のためのクッキーを入れてある。 var id = data.topic_id, cookie = data.cookie; // httpモジュールを使って、ウェブ・サーバと通信する。 // (queryString()とcookieString()は自作関数) var query = queryString({'data': data}), options = { host: settings.app_host, port: settings.app_port, path: '/topic/write/' + id, method: 'POST', headers: { 'Cookie': cookieString(cookie), 'Content-Length': query.length, 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest', }, }; // 以下の手順でウェブ・サーバと通信する。 // 1. http.requestオブジェクト生成(http.request()) // 2. クエリ書き込み(request.write()) // 3. 送信(request.end()) var request = http.request(options, function(response) { response.setEncoding('utf8'); if (response.statusCode != 200) { client.send({result: false}); return; } response.on('data', function(result) { try { result = JSON.parse(result); } catch(e) { result = {result: false}; } client.send(result); if (result.result) { client.broadcast(result); } }); }); request.write(query); request.end(); }
解説用のサンプルなので、このままでは動きません。
雰囲気だけ掴んで頂ければ、結構だと思います。
ここでは、ユーザ認証するために、 セッション を維持する必要があります。
上記のコードでは、data変数にcookieがセットしてあります。
下記のコードをクライアント・サイドに実装することで、クッキーをNode.jsに送ることが出来ます:
var socket = new io.Socket(); socket.on('connect', function() { socket.send({ cookie: document.cookie }); }); socket.connect();
Node.js側でなく、既存のウェブ・アプリケーション側にロジックを寄せれば、このレベルのコードでリアルタイム・メッセージングが出来るようになります。
残りの部分は 人口無能のチュートリアル と同じです。
人口無能のチュートリアル を参考に、 Socket.IO を使って、独自に実装してみてください。
Ubuntuに本番環境を用意する
コードは端折りましたが、本番環境の用意も要点を絞って説明します。
例によって、 人口無能のチュートリアル を参考に、 npm と Node.js はインストールしておいてください。
Ubuntu 10.04のリポジトリにも、Node.jsのパッケージがあるのですが、バージョン0.2.6と少し古いです。
チュートリアル通り、naveでインストールするのが無難でしょう。
ビルドには、メモリが1Gバイトは必要です。
私は、512Mバイトの仮想マシン上で、メモリ不足でマシンがハングしました .;)
本番環境は、以下のいずれかの記事を参考に準備します。
- Run Node.js as a Service on Ubuntu
- Ubuntuのupstartスクリプトを使った環境の準備です。
プロセスが落ちた場合も、respawnで自動復帰させます。 - Keep a node.js server up with Forever
- Node.jsのモジュールであるForeverを使った環境の準備です。
npmでインストール出来るのでお手軽です。
AV女優.com では upstartスクリプト を使ってNode.jsを走らせています。
基本的に、記事の通りやれば本番環境を用意出来ます。
しかし、注意する点が一点あります。
それは、 npmでインストールしたモジュールのパス です。
npmは一般ユーザ権限でインストールすると、 ~/node_modules ./node_modules にインストールされ、モジュールを読み込む場合もここから読み込みます [1] 。
しかし、これは本番環境では気持ち悪いのです。
本番環境では、システム全体の共通パスにインストールし、それを参照したいものです。
これを実現するには、 root権限 で -gオプション を付けて、モジュールをインストールします。
そうすると、 /usr/local/lib/node_modules にモジュールがインストールされます。
参照するときはどうするか?
NODE_PATH 環境変数を設定します。
つまり、Ubuntuのupstartスクリプトは次のようになります:
description "ohyes server with Node"
author "sunomaru"
start on started mountall
stop on shutdown
respawn
respawn limit 99 5
script
export HOME="/srv/ohyes"
export NODE_PATH="/usr/local/lib/node_modules"
export NODE_ENV="development"
if [ ! -d "/var/log/node" ]; then
mkdir /var/log/node
fi
exec /usr/local/bin/node /srv/ohyes/app.js >> /var/log/node/ohyes.log 2>&1
end script
post-start script
end script
もし、開発環境でも同様にモジュールを共通で使いたい場合、 npmをroot権限で使うことを心がけ、 .bashrc などにNODE_PATHを設定しておくと良いかもしれません。
Node.jsの開発/運用に役立つ記事
最後に、Node.jsを使う上で、参考になる記事をまとめておきます。
本番環境
- Nodeにおけるスケールアーキテクチャ考察(Scale編)
- Node.jsをスケールするための構成 が、詳しく解説されています。
より実践に近い内容で解説されているため、とても参考になります。 - Web開発系のクラウド(SaaS, PaaS, IaaS)まとめ
- 近年、やたらと数の増えたクラウドサービスに関するまとめです。
Node.jsに対応したPaasが多く紹介されています。
ここに紹介されている 11サービス中、6サービス がNode.jsに対応しています。
テスト
- Unit testing in node.js
- とても分かりやすい、Node.jsにおける ユニットテストのチュートリアル です。
このチュートリアルをこなせば、Node.jsである程度のテストが書けるようになります。
1〜2時間もあれば終わるので、是非どうぞ。
TIPS
- node.jsでhttp sessionを共有するsocket.ioのテストを書く
- Node.jsと既存のウェブ・アプリケーション間で セッションを共有する方法 が解説されています。
また、そのテストの仕方もまとめられています。
JavaScript
- Learning Advanced JavaScript
- チュートリアル形式でJavaScriptが学習出来ます。
その場でコードを修正して走らせる ことができ、JavaScriptへの理解を深めることが出来ます。 - JavaScript 第5版
- オライリーのJavaScript本です。
私はまだ読んでないのですが、評判はかなり良いです。
JavaScriptの基礎力向上 にどうぞ。 - Learning Server-Side JavaScript with Node.js
- サーバ・サイドのJavaScript を学ぶための簡単なチュートリアルです。
インストールから、ツイッターのリアルタイム・ストリーミングまで、実際に手を動かしながら学べます。 - JavaScriptのいろいろなコーディングルールをまとめてみた
- JavaScriptのコーディングルール がまとめられています。
公式ではありませんが、Node.jsのコア・デベロッパの方が書いたNode.jsのコーディング・ルールは こちら 。
全般
- node.jsとWebSocketの利用シーン
- AjaxからWebSocketに至るまでの経緯や、WebSocketの活用方法までわかりやすく解説されています。
Node.jsとWebSocketの概要 を知るには、とても良い記事です。 - Nodeにおけるスケールアーキテクチャ考察(SSP編)
- Node.jsのアーキテクチャ について、細かく考察されています。
Node.jsを本格的に運用するのであれば、必読です。
いかがでしょうか。
今回紹介した構成は、アクセスが増えてきた場合にスケールしにくい構成です。
しかし、 Node.js開発の工数が少なくて済み、コードをDRYにしやすいという点 で優れています。
簡単にリアルタイム・メッセージングを導入出来ます。
AV女優.com が流行り、アクセスが増えてきたら、また構成を考える必要があるでしょう。
そのときは、またこのブログでシェアしていきます。
私自身、まだまだノウハウが少ないので、困っています。
アドバイスなどありましたら、コメント欄までお願いします。
盛り上がる兆しのない AV女優.com アダルト掲示板 にも、何か書き込んでくれると嬉しい限りです。
| [1] | はてなブックマークのコメントで指摘があったので、修正しました。ドキュメントには、 ./node_modules にインストールされるとあります。私の環境だと、必ず ~/node_modules にインストールされるのですが、何故でしょう? |

