non vorrei lavorare

2020年度からの小学校プログラミング教育の必修化を親として迎えるブロガーの書く、子供との日常

libtrusterdでHTTP/2でphpを動かして分かったこと

こんにちは、7月の3連休はつくばエクスプレスに家族で乗り込み、つくばエキスポセンターへ行ってきました。このところ、飛行機に夢中だった長男がロケットに夢中に成り、次男は、慶応大学の開発したメタリックブルーのタイヤのいっぱいある、電気自動車が大変気に入った様子でした。@kjunichiです。

 

背景

h2oがFastCGIに対応したことにより、PHPが動かせる旨の記事を読み。この時点ではじめてFastCGIの事を知った。

以前よりTrusterdでCGIっぽいことをやろうとしており、これらがつながった。そうかFastCGIなる規格に対応すれば、TrusterdからPHPPerlも動かせそうだと。

やってみた事

 

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

ruby力がないのと算数が苦手なので、trusterd.conf.rbを書き直しまくり、65535を境に動かなくなることを突き止めた。だから、この時にtrusterd.conf.rbは内緒。

pipeで取得したファイルデスクリプタの制限

 

パイプバッファの最大値以上のサイズのバイト列を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して、読み書きを別々のプロセスで行っているため、今回のような事象に遭遇することは可能性が低い。

 

解決に向けて

ということで、65535の壁を超えるコードは出来つつある。次回に続くかも。。

 

Link

関連記事

 

11年前の記事

5年前の記事

1年後の記事