勇者コレクター攻略日記

元々はプロのプログラマがレビューする転職情報。今は勇者コレクターの攻略がメイン

node.jsのインストールを試してみる

   

node.js hands-on v1.0 documentation > インストール
http://dl.dropboxusercontent.com/u/219436/node.js/handson/build/html/intro/install.html

まずはダウンロード
$ wget http://nodejs.org/dist/node-v0.3.0.tar.gz

ってこれって最新版?
http://nodejs.org/dist/
覗いてみると
http://nodejs.org/dist/latest/
に最新版があるみたい

32bit用と64bit用があるけど
念のため
$ uname -a
で32bitから64bitか確認する

Linux localhost.localdomain 2.6.18-371.4.1.el5PAE #1 SMP Thu Jan 30 06:51:58 EST 2014 i686 i686 i386 GNU/Linux

ということで32bit版をダウンロードしてくる
http://nodejs.org/dist/latest/node-v0.10.28-linux-x86.tar.gz
と思ったらこれは実行ファイルだった・・・

今度こそソースを落としてくる
http://nodejs.org/dist/latest/node-v0.10.28.tar.gz

でいつものようにconfigure~make~installして
シェルからJSインタプリタの起動、
nodeの引数にJSファイルを指定してJS実行
shebangによるスクリプト実行などできたのでインストール完了!

ここでいまさらだけど、node.jsが一体何なのかを調べてみる。
JavaScriptでサーバサイド機能やソケット通信を実装するための仕組み、
だと思ってたのだけど、よくよく最初から話を追ったらノンブロッキングI/Oが本質だった。

■ファイル記述子(ファイルディスクリプタ)について
プログラミングにおいてファイルへの参照を抽象化したものだが、
UNIX系システムではデバイスやFIFO、ソケットも抽象化している。
実際socket()関数はソケットを抽象化したディスクリプタを返す。

■select()関数について
複数のファイルディスクリプタの状態監視を行う
具体的には、read可能になったかを監視するファイルディスクリプタセット=readfds、
write可能になったかを監視するファイルディスクリプタセット=writefds、
そして例外が発生したかを監視するファイルディスクリプタセット=exceptfdsを指定する
ファイルディスクリプタセットの操作には FD_ZERO()、FD_SET()、FD_CLR()といったマクロが用意されている。
なおselect()は指定したディスクリプタセットに状態変化があるまでblockする。

■poll()関数について
ファイルディスクリプタそれぞれに対して、イベントを待つことができる。
待つイベントは構造体のメンバeventsに指定でき、実際に発生したイベントは構造体のメンバreventsに格納される。

■JavaScriptがシングルスレッドでイベントループをもっている
さらにイベントのモニタリングとハンドリングが同一スレッドである。
これってJavaScriptとか、もっというとECMAScriptで規定された仕様なのか、
ただのブラウザの実装依存なのかずっと気になっていた。
仕様は見つからないのでただのブラウザの実装依存であり、これを前提にしたようなコードは書いてはいけないと思う
setTimeout(‘doSomethingWithFoo(Foo)’, 1000) 1秒後にFooを使用して何かを行う
initializeFoo() // Fooの初期化
みたいなコードね
と思っていたらWeb WorkersとしてW3Cからマルチスレッド仕様が公開されていた。

■Web Workers
HTML5から使用可能になる
JavaScriptでノンブロッキング処理を実現するための機能。
JSファイルを指定してウェブワーカー作成し、JSを実行させる。
ウェブワーカーはブラウザによって別スレッドで実行される。
これ、ワーカーのスコープが気になるんだけど
self と this はワーカーのグローバルスコープになるらしい。
あと、windowオブジェクトやdocumentオブジェクトにはアクセスできないし、
DOM操作は非スレッドセーフだからやってはいけない(できない?)みたい。
確かにJavaScriptでマルチスレッド特有の問題が出ても対処の仕様がなさそうだし、これは理解できる。

■C10K問題とは
「C10K問題」(クライアント1万台問題)とは、
ハードウェアの性能上は問題がなくても、
あまりにもクライアントの数が多くなるとサーバがパンクする問題のこと
http://www.hyuki.com/yukiwiki/wiki.cgi?TheC10kProblem

ようするにサーバサイドのプログラムの問題ということだけど、
これ読んでてselect()やpoll()はわかっても
epoll(), kqueue(), /dev/poll なんてわからないことにショックを受けた!
ざっくりいうと
epoll(): Linuxで使用できるpollの進化版
kqueue(): FreeBSDで使用できるry
/dev/poll: Solarisで使用できるry

■epoll()について
poll()と比べたときのepoll()のメリットは
エッジトリガとレベルトリガが使用できること。
レベルトリガとして使用した時はpoll()と機能的な差異はない。

■そもそもなぜselectやpollが必要か
ノンブロッキングI/Oを実現するため。
どういうことかというと、これらのシステムコールはI/O可能なディスクリプタを調べるために使用できる。
例えばソケットを読むときはデータがないとブロッキングしてしまうので、
予めシステムコールを使ってI/O可能な(ブロッキングしない)ディスクリプタに対してだけ読み書きを行えば
ブロッキングしないI/Oが実現できる。

■ソケットプログラムでここの考慮が必要か?
大規模なサーバサイドのプログラムを書くのでもなければ
socket()→bind()→listen()→accept()でブロッキングさせて
accept()が制御を戻したら接続済みソケットは別スレッドでI/Oすれば十分だと思う。

■Google V8 JavaScript Engine
Googleが開発したJavaScriptエンジン。
ECMAScript(ECMA-262)5th Edition準拠。

■libevとかlibeioについて
Node.jsで採用されているイベントループとノンブロッキングI/Oのためのライブラリ。
と思ってたんだけど、いつの間にかlibuvに変更されてる・・・
Changelog見ても
unix: add custom thread pool, remove libeio (Ben Noordhuis)
#1591, #1656, #1657 Implement fs in libuv, remove libeio and pthread-win32
とある。これってFile I/Oだけがlibuvに置き換わり、さらにスレッド処理が独自方式になってlibeioは完全に消えたってこと?
確かに今の手元バージョン(0.10.28)でgrepすると
#include “uv.h” してるところはあるけど
#include “eio.h” しているところはないね

■EventEmitterって?
Node書くならEventEmitterについて知っとくべし
http://qiita.com/yuku_t/items/d69d3a2c7dafa7d04e87

ECMA Scriptではイベントの監視にaddEventListenerを使うけど
NodeではEventEmitterというはなし。
このページで分かった基本的な使い方
EventEmitter.on() でイベントに対するリスナ登録
EventEmitter.once() でイベントに対する単発のコールバック登録
EventEmitter.emit() でイベントを発生させる
EventEmitter.once() で登録したコールバックはイベントが複数回発生した場合でも、最初の1度しか実行されない

■Socket.IO
リアルタイムWebを構築しやすくする「Socket.IO」とは
http://codezine.jp/article/detail/7075

リアルタイムWebのための技術
HTTP Pollingはクライアントがサーバに定期的にリクエストを発行する
Comet(HTTP Long polling)はクライアントが発行したリクエストに対して
サーバはレスポンスを返さずにコネクションを維持しておき、クライアントに通知したいデータが発生したらレスポンスを返す。
1度レスポンスを返した or タイムアウト によってリクエストが無効となった場合、
クライアントはサーバに対して即座に次のリクエストを発行する。
あとは使ったことないけどPlugin SocketとかWeb Socketとか。
これらの実装方式を隠ぺいしてくれるのがSocket.IO

■たとえばEventEmitterの実装ってどうなってる?
Node.jsを触っててふと不思議に思ったのが、
NodeのNativeクラスのさらにC++のNative側の実装を追いたいときはどうすればいいのか、ということ
EventEmitterだったら
var EventEmitter = require(‘events’).EventEmitter;
するので、配布物の中にevents.jsがあるということ。
中を見ると、当たり前だけどJavaScriptで書かれているだけ。
てことはV8さえあればNode.jsは動く気がするし、
いちいちlibuvを採用!とかChromeには取り込まれてないけどNodeにはパッチで採用!
とかやってるのってどこの話なんだろう・・・。
もっとFile I/Oとかが絡んでこないとNative側の実装まで食い込んでいかないのだろうか

 - 未分類