こんにちは、7月の3連休はつくばエクスプレスに家族で乗り込み、つくばエキスポセンターへ行ってきました。このところ、飛行機に夢中だった長男がロケットに夢中に成り、次男は、慶応大学の開発したメタリックブルーのタイヤのいっぱいある、電気自動車が大変気に入った様子でした。@kjunichiです。
背景
h2oがFastCGIに対応したことにより、PHPが動かせる旨の記事を読み。この時点ではじめてFastCGIの事を知った。
以前よりTrusterdでCGIっぽいことをやろうとしており、これらがつながった。そうかFastCGIなる規格に対応すれば、TrusterdからPHPやPerlも動かせそうだと。
やってみた事
rebuildfmのh2oの回でFastCGIのことが話題に出て、バイナリベースのプロトコルであることを知った。同時にそこそここのチャレンジが難しそうだとも感想を持った。
cgi-fcgiを使う
公式ページ?にはSDKやドキュメントが置いてあり、色々読み漁ったり、DLした。その結果、SDK付属のcgi-fcgiを使えば、FastCGIベースのスクリプトを動かせる事がわかった。
SCRIPT_NAME=/test.php SCRIPT_FILENAME=./test.php REQUEST_METHOD=GET ./cgi-fcgi -bind -connect 127.0.0.1:9000
分かった事
コマンドラインで動かせたので、mrubyでもすぐ動かせる。
`SCRIPT_NAME=/test.php SCRIPT_FILENAME=./test.php REQUEST_METHOD=GET ./cgi-fcgi -bind -connect 127.0.0.1:9000`
PHPのハローワールドが動かない
mirbで確認してphpからの応答が帰って来たので、早速、trusterd.conf.rbを書いて動かした。が、動かない、nghttpクライアントでしばらく応答待ちとなりエラーとなる。
<?php
phpinfo();
たったこれだけのシンプルなコードなのに。。。
返却する文字列長に着目した
なんとなく、このphpinfo()が返す文字列が長いなーぁとの感想をもち、wcすると、9万バイトあった。
そこで、rputsする文字列長をだんだん長くして、nghttpクライアントがエラーになるか試して。
境界値は65535
rputsに1度に渡す文字列の長さではなく、累積で65535バイトを越えると、動かない感じだなぁ
— kjunichi (@kjunichi) 2015, 7月 17
ruby力がないのと算数が苦手なので、trusterd.conf.rbを書き直しまくり、65535を境に動かなくなることを突き止めた。だから、この時にtrusterd.conf.rbは内緒。
mruby-http2、9万バイトのファイルだと落ちなかったから、rubyのコールバック周りに何か問題があるのかなあ
— kjunichi (@kjunichi) 2015, 7月 18
pipeで取得したファイルデスクリプタの制限
これ、OSXのバグで動かないんだろと思いもしたが、Linuxでも動かない、 dockerのお陰でサクッと確認出来た / “main.c” http://t.co/3kKetma82F
— kjunichi (@kjunichi) 2015, 7月 19
パイプバッファの最大値以上のサイズのバイト列をwrite出来ない。
OSX,Linuxともに64KB。むかしのLinuxではこのパイプバッファの上限をfcntlで変更できていたが、最近のカーネルではサイズ固定の模様。
なんでpipe使っているの
mruby-http2でrubyスクリプトの処理をpipe関数を使い、ファイルデスクリプタを扱うことで、他の静的コンテンツ(ファイルのファイルデスクリプタ)の処理やリバースプロキシ処理?(ソケットのファイルデスクリプタ)とのコードと統一化している模様。
mruby-http2モジュール側で、pipeを開いて、ライブラリ内の構造体を介してこれらのファイルデスクリプタをmrb_yield_argvで実行されるmrubyスクリプトと共有しており、mrubyスクリプトのrputsで書き込みようのファイルデスクリプタをwriteコールすることで、任意のバイト配列を書き込み、mruby-http2モジュール側で読み込み用のファイルデスクリプタをnghttp2ライブラに渡すことで最終的にHTTP/2応答としてクライアントに返してる。
通常はpipe関数は使用直後にforkして、読み書きを別々のプロセスで行っているため、今回のような事象に遭遇することは可能性が低い。
解決に向けて
mruby-http2でrputsで65535バイトの壁を超えた瞬間だ pic.twitter.com/55x3tP3CYK
— kjunichi (@kjunichi) 2015, 7月 23
ということで、65535の壁を超えるコードは出来つつある。次回に続くかも。。
Link
関連記事