【JavaScript】Nodejsの基本と便利なモジュール

今回はNode.jsの基本的な機能と周辺ライブラリを簡単に紹介します。

Let’s npm install -g tips !

組み込みNodejsの可能性

物理サーバを管理していた時代からスケーラブルなクラウドに移行するなかで、小型デバイスがサーバ機能を持つという逆転の発想もいいんじゃないかなと思います。

組み込み機器にnodeをNFSでマウントしてみた人もいるみたいですし、ネットワーク機能があれば複数センサと組み合わせて色々できると思う。
センシングありきではシーズ指向になってしまいますが、以下の特徴は組み込み用途でも生きそう。

  • イベント駆動である点
  • シングルスレッドでもノンブッロキングI/Oだから外部リソースへのアクセス時に即座に処理が返り、次のプログラムステップに移行する。マルチスレッドでなくてもある程度のリクエストをさばける
  • 使用メモリが少ない

c でこれだけの機能を実装するのは大変そうだしセンサロギングなら Node + NoSQL は相性良さそうということで可能性があると思います。

Node.js

nodeはサーバとしての低レイヤー機能を提供します。

  • Process : 現在のプロセスの情報を取得する
  • Console : ログなど標準出力情報を取得する
  • Timer : 指定時間後にcallback関数を呼べる
  • EventEmitter : イベントを発生させるオブジェクト。イベントに対してリスナのコールバック関数を実行する

サーバ起動ならhttpモジュールを require してバインドするだけです。
このhttpモジュールはデフォルトのコアモジュールに分類されます。また、httpモジュールはClient機能もあるのでGETリクエストを発行することもできます。

  • コアモジュール : nodeが提供するデフォルトモジュール。httpモジュールもこれに分類される。
  • ファイルモジュール : 自分で定義するモジュール

規模が大きくなったときにファイルを分割したい場合は、ファイルモジュールを作成できます。

// ownModule.js
function getStr(str){
  var name = "fisproject";
  return  name + str;
}

module.exports.getStr = getStr;
var ownModule = require("./ownModule");

Nodeは最低限の低レイヤーのサービス提供なので、Expressを使う事で実際上の細かいことが楽にできます。
まず、npmをインストール。

$ sudo apt-get install npm
$ node -v
v0.10.13

Express

ProductionとDevelopment環境の使い分けを app.configure で設定できます。
クエリなどでルーティングしたい時はURlモジュールを読み込んだり、Auth認証情報とかもできます。

  • GET : データ取得。URLにクエリ文字列として?キャラクタの後に付加される
  • POST : データ登録。Bodyに付加される。クエリ長のよる制限がない
  • PUT : データ更新
  • DELETE : データ削除

Expressでは Get,Postメソッド別のルーティング、特にIDによるルーティングは next で実装できます。
また、下記のような豊富なミドルウェアを利用する事ができます。

  • basicAuth : 認証
  • session + cookieParser : セッション保持、クッキー解析
  • limit : リクエストボディの制限サイズ設定
  • static : 静的ファイルの送信(html, css, image etc)
  • bodyparser : ファイルのアップロード受信

forever

運用環境でもnodeコマンドで起動するのはどうも微妙です。
そこでforeverというデーモンマネージャーを使いアプリケーションをデーモン化することができます。
起動と停止は以下

$ forever start app.js
$ forever stop app.js

現在、foreverで動いているアプリも確認できます。

$ forever list

foreverで動かしている時のlogの場所は以下で確認します。

$ forever logs -l

node-supervisor

supervisorはファイルの変更を監視し変更時に再起動を自動的に実行します。
というのも、通常requireで呼ばれるモジュールはコンパイルされているので、app.js変更時に再起動が必要になってしまうからです。

$ npm install -g supervisor
$ supervisor app.js
DEBUG: Running node-supervisor with
DEBUG:   program 'iOSApp-Node/app.js'
DEBUG:   --watch '.'
DEBUG:   --ignore 'undefined'
DEBUG:   --extensions 'node|js'
DEBUG:   --exec 'node'
DEBUG: Starting child process with 'node app.js'

log4js

サーバへのアクセスログはとっておきたいですね。
ログ出力をファイルに書き込みたいので入れました。Expressのloggerより高機能みたいです。

$ npm install log4js

簡単なファイルモジュールにしました。

var log4js = require('/path/to/your/log4js');

// setting
log4js.configure({
      appenders: [
        { type: 'file', filename: '/home/***/iOSApp-Node/logs/access.log', category: 'console', backups: 30, maxLogSize: 1024 * 1024 }
      ]});

var consoleLog = log4js.getLogger('console');
consoleLog.info('Server Start');

module.exports.log4js = log4js;
module.exports.consoleLog = consoleLog;

ちゃんとログがとれてるか確認します。

$ tail logs/accees.log
[2013-02-11 00:15:17.279] [INFO] console - Server Start
[2013-02-11 00:15:27.510] [INFO] console - 126.205.194.98 - - "GET /*******.json HTTP/1.1" 200 369 "" "%E4%BB%8A%E3%81%95%
*****/1.11 CFNetwork/609 Darwin/13.0.0"

どんなアクセスメソッドが多いかなどの集計スクリプトも書いておくと便利です。

WebSocket

WebSocketはHTTPを拡張することで利用できます。
accept配列にあるホストのみ接続が許可されます。

socket.ioはWebSocket機能に加えてサポートしてない古いブラウザに対しても双方向通信APIを使ってくれます。

$ npm install websocket
> websocket@1.0.8 install /home/fis/node_modules/websocket
> node install.js
[websocket v1.0.8] Attempting to compile native extensions.
[websocket v1.0.8] Native extension compilation successful!
websocket@1.0.8 node_modules/websocket

$ npm install socket.io
socket.io@0.9.13 node_modules/socket.io
├── base64id@0.1.0
├── policyfile@0.0.4
├── redis@0.7.3
└── socket.io-client@0.9.11 (xmlhttprequest@1.4.2, uglify-js@1.2.5, ws@0.4.25, active-x-obfuscator@0.0.1)

argv

nodeアプリケーションの起動時のサブコマンドとオプションを取得できます。

$ npm install argv

使い方は簡単です。

var argv = require('argv');
console.log(argv.run());

if (argv.run().targets == "dev") {
 // your code
}

実行結果は以下。

$ node test.js dev
{ targets: [ 'dev' ], options: {} }

詳しくはこちらを参考に。

node-cron

node-cronは定期的にサーバ内部で処理を行わせたい場合に便利です。min hour day month week の順。 * はワイルドカードです。
Timezone(”Asia/Tokyo”など)を使う場合は time も必要です。

$ npm install time
$ npm install cron

memcached

memcached-clientです。

$ sudo yum install memcached
$ npm install memcache 

memcachedをport 12345で起動します。

バックグラウンドプロセスで起動しておきます。

$ memcached -u memcached -p 12345 &
[1] 26362
$ lsof -i:12345
COMMAND     PID     USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
memcached 26362 ***   26u  IPv4 1607519      0t0  TCP *:italk (LISTEN)
memcached 26362 ***   27u  IPv6 1607520      0t0  TCP *:italk (LISTEN)
memcached 26362 ***   28u  IPv4 1607523      0t0  UDP *:italk 
memcached 26362 ***   29u  IPv6 1607524      0t0  UDP *:italk 

memcached-clientのcodeです。

var memcache = require('memcache');

var client = new memcache.Client(12345, 'localhost');
 
client.connect( 'localhost', function( err, conn ){
  if( err ) throw new Error( err );
  console.log( conn.server );
});

client.set('mame', 'root', function(error, result){
}, 9160);
 
client.get('mame', function(error, result){
    console.log(result);
});
 
client.close();

key(mame)の結果です。

$ node smp_memcash.js 
root

404 NotFound

HTTP status Code 404を返すコードです。

app.use(express.static(__dirname + '/public'));
app.use(app.router);
app.use(function (req, res, next) {  // Return HTTP status code 404
     var errLog = 'NotFoundError: cannot find ' + req.url;
     console.log(errLog);
     res.status(404);
     res.render('index', {
     title: 'Not found'
   });

ブラウザにはindex.jadeの内容が表示されます。