autotestのmapping

なぜかmodelファイルの変更をしても、autotestで再実行されない。
とりあえず、autotestのmappingを下のようにしたら実行されるようになった。
app以下のファイルとspecファイルのmapping。

.autotest


Autotest.add_hook(:initialize) {|at|
at.add_mapping(/app\/([\/\w_]+)\.rb$/) do |f, matched|
"spec/#{matched[1]}_spec.rb"
end
}


デフォのmappingどうなってんだろう・・。

MacはBSDベース

MacLinuxベースじゃない。BSDベース。そのおかげではまった。

historyの出力から、行番号部分だけとりたかった。
これを、


121 ls -al
122 pwd
こうしたかった。

ls -al
pwd
だけ。

で、sedで-r(拡張表現オプション)つけて実行。


history | sed -r "s/^ +[0-9]+ //"
したら、

sed: illegal option -- r
そんなオプションないっておこられた・・。

原因は、MacBSD UNixベース。
sedBSDベースのもの。
man sedすると


-E Interpret regular expressions as extended (modern) regular expressions rather than
BSDベースだと、拡張表現は-rじゃなくて。-Eみたい。

grepは-Eなのになー。

Mac Lionにclispをインストール

Mac Lionにclispをいれる。


brew install clisp
Warning: Building with LLVM, but this formula is reported to not work with

If it doesn't work you can: brew install --use-gcc

Error: Failed executing: ulimit -s 16384 && make
「--use-gcc」つけろって怒られる。
gccを使うっよって宣言するオプション?今まで指定したこと無いんだけど。
Macに入ってるgccLLVMのものだから、そのあたりの絡みだろうか。
とりあえずつけて再実行。

brew install --use-gcc clisp
==> Summary
/usr/local/Cellar/clisp/2.49: 62 files, 16M, built in 6.8 minutes
無事はいった。

unicornのpreload_app

unicornの設定「preload_app」について。
ざっくりと、「workerのアプリケーションの先読み」の設定らしい。


このサイトに詳しい説明があったので訳してみた。英語は苦手なので怪しいがなんとなく雰囲気は合ってる気がする。

http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-preload_app

Enabling this preloads an application before forking worker processes.

workerをforkする前のアプリケーションの先読みを有効にします。

This allows memory savings when using a copy-on-write-friendly GC

これは、copy-on-write-friendlyに相性の良い環境では、メモリを節約できます。

but can cause bad things to happen when resources like sockets are opened at load time by the master process and shared by multiple children.

しかし、socketのようなリソースはmasterによってロード時に開いて複数のchildren(worker)で共有されているときに悪いことが起こる可能性があります。

People enabling this are highly encouraged to look at the before_fork/after_fork hooks to properly close/reopen sockets. Files opened for logging do not have to be reopened as (unbuffered-in-userspace) files opened with the File::APPEND flag are written to atomically on UNIX.

これを有効にするなら、before_forkもしくはafter_forkでsocketをの適切を開き直すことをおすすめします。
でもログファイルはUNIXによってアトミックに書き込まれるので問題なし。

In addition to reloading the unicorn-specific config settings, SIGHUP will reload application code in the working directory/symlink when workers are gracefully restarted when preload_app=false (the default).

preload_app=falseの時にHUPでunicornの再起動が正常に行われた場合、設定とアプリケーションをリロードし、リロードされたものへのシンボリックリンクが切り替わります。

■preload_appの設定によるSIGHUPでの再起動時の挙動の違い

preload_appの設定によって、SIGHUP(workerの処理の完了をもって再起動)を送ったときに挙動が違ってくる。

true

  • unicornの設定:再読み込みされる
  • アプリのリロード:されない。アプリはマスタでロード済みのものを使う。アプリをリロードしたければ、SIGUSR2を送って新マスタ&workerを立ち上げる方法をとる。
  • ダウンタイム:発生しない(マスタのアプリをそのまま使うので、workerがあがった時から処理が可能)

false

  • unicornの設定:再読み込みされる
  • アプリのリロード:される
  • ダウンタイム:発生する。(workerがそれぞれアプリをロードするので、ロード完了まで処理できない)

preload_appをfalseにする時って?

あえてpreload_appをfalseにする時ってなんだろう。
preload_appがtrueの時のデメリットは、
・SIGUSR2での再起動になり、手順的に多少複雑(古いmasterを後で落とすなど)
→でもcapistrano等で自動化可能な範囲。
・SIGUSRで新マスタ&workerを立ち上げる場合、一時的にマスタ&workerのセットが2セットできるからメモリ的に一瞬大きくなる事もある
→preload_appがfalseの場合はworker数分のアプリをメモリにロードするわけだし、そっちの方が大きくなるか。

何かの情報で、SIGUSR2が不安定という事を聞いたことはあるけど、そのへんの事情なのかな。
情報とつっこみ欲しい。

Mac Lionにnginx+php-fpmをいれ、Shindigを動かす

事前にいるもの
・Homebrew
wget(Homebrewでbrew install wgetでいける)

nginx、php-fpmインストール

nginx


brew install nginx

php-fpm

php-fpmを有効にしたphpをインストールする必要がある。
brewで入るが、デフォではbrew対象外(/usr/local/Library/Formula/にスクリプトなし)なのでスクリプト作る。


cd /usr/local/Library/Formula/
curl -O https://raw.github.com/ampt/homebrew/php/Library/Formula/php.rb
mv php.rb `brew --prefix`/Library/Formula
インストール。fpm有効にするオプションを忘れずに。

brew install php --with-fpm
このphp-fpm版のphpの前にphpが入ってたらパス通ってるのなら置き換える。

sudo mv /usr/bin/php /usr/bin/php.old
sudo ln -s /usr/local/Cellar/php/5.3.10/bin/php /usr/bin/php
ls -al /usr/bin/php
> lrwxr-xr-x 1 root wheel 36 2 25 22:22 /usr/bin/php -> /usr/local/Cellar/php/5.3.10/bin/php

shindigを動かす

apache.orgからsindigを拾う


sudo mkdir -p /var/project/shindig
cd /var/project/shindig
wget http://www.apache.org/dist/shindig/2.0.0/shindig-2.0.0-php.tar.gz .

shindig.htaccessを使っているが、nginxは.htaccessなんて読まないのでnginx.confで同じ挙動になるようにしてやる

shindingの.htaccess

# A
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L]
# B
php_flag always_populate_raw_post_data On
php_flag magic_quotes_gpc Off

A.リクエストされたものが、ファイルでもディレクトリでもない(該当なし)ならindex.phpに飛ばしているらしい。
B.phpのalways_populate_raw_post_dataをOn、magic_quotes_gpcをOffに。
という二つの設定がある。

これを、nginx.confとphp.iniで設定する。また、ついでにphp-fpmで動くように設定する。

nginx.confの設定


vi /usr/local/etc/nginx/nginx.conf
下記の内容を追記。

server {
server_name localhost;
listen 8080;
root /var/project/shindig;
access_log /var/project/shindig/logs/access.log;
index index.php;
if (!-e $request_filename){
rewrite ^ /index.php;
}
location / {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
}
}

php.iniの設定

always_populate_raw_post_dataをOnになっているか確認。


php-fpm -i| grep always_populate_raw_post_data
php-fpm -i| grep magic_quotes_gpc
always_populate_raw_post_dataはONに、magic_quotes_gpcはOffになっている必要がある。
そうでないと、shindigを動かしたときに

Your environment does not have always_populate_raw_post_data enabled which will interfere with Shindig. Please set 'always_populate_raw_post_data' to 'On' in php.ini

とか怒られる。


php-fpm -i | grep php.ini
設定変更。ちゃんとphp-fpmを有効にしたphpの設定を変える(元からPHP入ってて、php.ini二つあるとか)

vi /usr/local/Cellar/php/5.3.10/etc/php.ini

php_flag always_populate_raw_post_data On
php_flag magic_quotes_gpc Off

起動、確認

起動

php-fpmとnginxを立ち上げる。


php-fpm
nginx

アクセスしてみる

http://localhost:8080/gadgets/ifr?url=http://www.labpixies.com/campaigns/todo/todo.xml
にアクセスして、ガジェットパーツが読み込まれたらOK(TODOリスト)

さくらVPSで、node0.5.3〜npmのinstallではまった

ローカルのnode.js環境をさくらVPSに移した。
いくつかはまる部分があったので備考録。

まずはnode.jsのソースをもってきてconfigure。


cd /usr/local/src/
wget http://nodejs.org/dist/v0.5.3/node-v0.5.3.tar.gz
tar xzvf node-v0.5.3.tar.gz
cd node-v0.5.3
./configure
落ちた・・。pythonがエラーってるっぽい。

/usr/local/src/node-v0.5.3/wscript: error: Traceback (most recent call last):
File "/usr/local/src/node-v0.5.3/tools/wafadmin/Utils.py", line 274, in load_module
exec(compile(code, file_path, 'exec'), module.__dict__)
File "/usr/local/src/node-v0.5.3/wscript", line 222
"-pre" if node_is_release == "0" else ""
^
SyntaxError: invalid syntax
ググってみると、英語のページでPythonが古いんだみたいな事を言われていた。
最新(2.7.2)をいれる。

wget http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz
tar xzvf Python-2.7.2.tgz
cd Python-2.7.2
./configure
make
make install
Pythonはすんなり入った。

では、再度node.jsのインストール


./configure
configure通過。

make
次はmakeがこけた。

[ 5/36] libv8.a: deps/v8/SConstruct -> build/default/libv8.a
/usr/local/bin/python "/usr/local/src/node-v0.5.3/tools/scons/scons.py" -j 1 -C "/usr/local/src/node-v0.5.3/build/default/" -Y "/usr/local/src/node-v0.5.3/deps/v8" visibility=default mode=release arch=x64 toolchain=gcc library=static snapshot=on
scons: Reading SConscript files ...
ImportError: No module named bz2:
File "/usr/local/src/node-v0.5.3/deps/v8/SConstruct", line 37:
import js2c, utils
File "/usr/local/src/node-v0.5.3/deps/v8/tools/js2c.py", line 36:
import bz2
Waf: Leaving directory `/usr/local/src/node-v0.5.3/build'
Build failed: -> task failed (err #2):
{task: libv8.a SConstruct -> libv8.a}
make: *** [program] Error 1

bz2がない?またググってみるとbzip2-develが必要らしい。しかもそれはPythonインストール時に無いといけなかったららしい。。


yum install bzip2-devel
しかもこれはPythonのインストール時に必要だったらしい。
↑のPythonインストール(./configure〜make install)をもう一度。。

これで、nodeのmake、make installも通った。


'install' finished successfully (0.137s)

また、その後npmのinstallでもはまった。


npm install socket.io
下記のエラー出力。

npm ERR! tar "-mvxpf" "-" "-o" "-C" "/tmp/npm-1313209389660/1313209389660-0.5830379514954984/contents/___package.npm" tar: Ignoring unknown extended header keyword `LIBARCHIVE.creationtime'
npm ERR! tar "-mvxpf" "-" "-o" "-C" "/tmp/npm-1313209389660/1313209389660-0.5830379514954984/contents/___package.npm" tar: Ignoring unknown extended header keyword `SCHILY.dev'
npm ERR! tar "-mvxpf" "-" "-o" "-C" "/tmp/npm-1313209389660/1313209389660-0.5830379514954984/contents/___package.npm" tar: Ignoring unknown extended header keyword `SCHILY.ino'
これはtarが古いようだ。(ver 1.15)
tarをバージョンアップ。
この際、FORCE_UNSAFE_CONFIGURE(安全でないconfigureを強制。。)を1にしないとcofigureが通らなかった。

wget http://files1.directadmin.com/services/all/tar-1.26.tar.gz
tar xzvf tar-1.26.tar.gz
cd tar-1.26
./configure && make && make install
FORCE_UNSAFE_CONFIGURE=1
export FORCE_UNSAFE_CONFIGURE
./configure && make && make install

入った。
これでやっと、npm installも通る。


npm install socket.io
やっとうまくいった。長かった。。だいたいソースからのインストール系ってすんなりいった記憶が少ない

socket.io@0.7.9 ../node_modules/socket.io
├── policyfile@0.0.4
├── redis@0.6.6
└── socket.io-client@0.7.9

2011/07/22 Node.jsの勉強会 「『Node.js』とは何か。そして、その先へ。」 に行ってきました

「『Node.js』とは何か。そして、その先へ。」( http://www.jus.or.jp/benkyokai/11-07.html )
(日本Unixユーザ会の勉強会)のレポートです。

・日時
2011/07/22 18:30〜20:30

・講師
bad_at_mathさん、jackさん


資料が配布され、それに従った説明を聞く+サンプルを見る形でした。
下記は配布された資料に、説明内容+aを追記したものです内容です。

■Node.js

まずはNode.jsとは。
・サーバサイドJavaScriptプラットフォーム
・2009年、Ryan Dath作

■背景

そしてそのNode.jsはなぜ(何のために)誕生したか。
C10K問題
 -同時接続数が思い切り増えていくと、サーバがパンクしてしまう
 -従来型の1スレッド1コネクションで同期I/Oというモデルにて表面化

■マルチスレッドの問題

マルチスレッドには下記の問題がある。また、腕の良い開発者でないと実装は難しい(資源の共有による、デッドロックの問題など)

○コンテキストスレッド

スレッド切り替えによるコストもばかにならない。
レジスタからのデータI/Oだけでも秒間数万系発生したりすると、それだけで高負荷な処理となる。

○メモリ効率

・1スレッドあたり2MB以上であり、スレッドの処理内容によっては10MB以上の場合も
(2MBとか10MBとかの数字はどこから出たものなんだっけ。この時間、一瞬席周りがばたついて聞き逃したっぽい。。)

ブロッキングI/O

・読み取り、書き込みが完了するまでひたすら待ち続ける処理
・ディスクやネットワークからの読み取り、書き込み性能はメモリにくらべてかなり遅いので問題になる
このあたりはLAMPな人がぶちあたりがちな問題ですね。

○I/Oコスト

CPUのL1キャッシュ : 3サイクル
CPUのL1キャッシュ : 14サイクル
RAM : 250サイクル
ディスク : 41,000,000サイクル
ネットワーク : 240,000,000サイクル

○解決策

・I/O多重化
 -select()poll()など
・イベント駆動モデル
ノンブロッキングI/O
 ちなみに、ノンブロッキングI/Oと非同期I/Oって違うものなんですね。混同してた・・。ちゃんと勉強しよう。
 - http://togetter.com/li/136290
 - http://d.hatena.ne.jp/forest1040/20110407/1302150936

○select(),poll()

一度に多数のFD(ファイルディスクリプタ)の状態を確認可能

  • select()
    • サイズの決まったFDを書き出してカーネルに確認
  • poll()
    • 可変長配列にFDを書き出してカーネルに確認
○epoll

select()やpoll()・・・FDをstateはプログラム側で検査する必要がある
epollの・・準備のできたFDの集合が返される

■性能比

liveventのベンチ比較。epoll優秀

■イベント駆動モデル

・シングルスレッド+ループ
・発生イベントの無いようにより処理分岐
・計量
・古くからGUIライブラリなどでも利用
・シグナルもその1つと言える(?)

■ノンブロッキングI/O

・読み取り、書き込み処理を行うとその成功、終了を待たずに呼び元に戻る
・ブロックしないので、他の処理を続けることが可能

■HTTPサーバ実装例

・enginex
lighttpd

■ライブラリ実装例

・libevent
・libev

■libevent

・ver0.1は2001年リリース
・Liels Provos(現Google)作
・シングルスレッド
・イベント駆動
・ノンブロッキング
・mecached等で利用

■libev

・Marc Lehman(GCCのPen最適化)
・livenentよりも高性能(ver1.x比)

■各言語での実装例

・Twisted(Phthon)
・AnyEvent(Perl)
・EventMachine(Ruby)

■Ryan Dahl

・Edd(ruby製webサーバ)
・libebb(httpサーバライブラリ)

■オリジナル実装へ

・より高速へ
・よりスケーラブルに

■Node.jsリリース

・イベント周りにはlibevを利用
・ファイルI/Oにはlibeio
Google製JSエンジン(v8)
・自前のHTTPパーサ
・C-ares(非同期DNSライブラリ)

■特徴

・シングルスレッド
・非同期
・ノンブロッキングI/O

アーキテクチャ

Node.jsは、
v8、libev、libeioで構成されている。

JavaScript

・スレッドライブラリなし
・非同期プログラミング
・近年目覚しく高速化
 GoogleMapなどのAjaxやリッチなクライアント側実装に耐えうる各ブラウザベンダがしのぎをけずって高速化に取り組んだ
・開発者人口の多さ

■V8

JavaScriptを大幅にスピードアップ
 ・プロパティ・メソッドアクセス高速化
 ・高速かつオーバーヘッドの少ないJIT
 ・効率の良いGC

■libeio

・ファイルI/Oを受け持つ
・内部ではスレッドプールを利用

■Node.jsの利点

・高効率
・賞メモリ
・HTTPがファーストクラス
・多数の接続に対応
・クライアントからサーバまで一貫(JS)
 →どっちもJavaScriptで実装
・Webアプリ経験者の敷居の低さ
 →これもJavaScriptで実装していることによる
・利用可能なライブラリはnon-blocking
・各コンポーネントの高速化の恩恵にあずかれる
 ・V8、libev

■コード例

省略
(よくある、HTTPサーバをたててHello World出力)

■Server-Side JS

Node.jsだけでなく、下記のようなサーバサイドJSライブラリもある
・Ringo.js
・Pinture
・Joyent Smart
・Jaxer

■既存のものとの違い

・目的やバックグラウンドが違う
 ・Node.jsは高速性、また多くの接続をハンドリングできることを目標に作られている
 ・JSを採用したのは上記の条件を満たす部品としてマッチしたため。

■Node.jsの得意分野

・同時接続数が多く、計量な処理のもの
 ・リアルタイムアプリケーション

■Node.jsの欠点

・シングルスレッドであること
 ・マルチコアを生かし切れない
(一応、現時点でNode Clusterやプロセスを複数たちあげる方法も無くは無い)
 ・CPUインテンシブな処理は構造上苦手(ループを高速にまわす必要がある)
 ・V7noヒープが現状、64bitで1.9GB(32bitで1GB)
 ・モジュールは非常に多く存在するが完成度があと一歩のものが多い

■Node.jsの流儀

Every I/O uses Non-Blocking I/O
・他の言語では同期I/Oを利用するライブラリを使ってしまい、処理速度が落ちる可能性があるがNodeではそれがない

■必要とされるスキル

・非同期プログラミングスキル
 ・サーバサイドではそれほど一般的ではない

■Node.jsの現状

・Windoesサポートに向けて、Microsoftが協力を表明(今ではバイナリ配布も)
・メジャープラットフォーム全てにおいて動作

■libuv

Windows版Node.jsはv8エンジンと、libuvで構成されている。
libuv…WindowsでNode.jsを機能させる為のIOライブラリ?(ここ、ちょっと理解しきれませんでした。また調べます)


ここでbad_at_mathさん講師の前半が終了

後半はjackさんによる実際のインストール〜アプリ作成まで。
また別の日に書く。かも。