drubyにおいて値渡しと参照渡しについてハマって期待通りに動作しなかった件があるので、記録する。
CGIにてアップロードされたファイルに対して、エンコードや解凍など時間のかかる作業を行わせたい場合、CGIプログラム内で行ってしまうと、ユーザに対する返答がエンコードなどの作業が終わった後になってしまうため、遅れてしまい不満が出てしまう。
まずファイルのアップロードだけが上手くいったら受け付けた旨をユーザーに返答し、バックエンドのサーバーにて作業を行いたい要求があった。
別の問題として、通常、CGIは平行して実行されるが、そのように実装してしまうと重い作業の処理が並列に走ってしまい、サーバがまともに動作できない問題を抱えていた。さらに利用度が上昇した場合、重い作業はサーバごと切り離したい、もしくはサーバを複数用意して並列に走らせたい要求があった。
これらの問題を解決するために、CGIから何らかの通信によって別のプログラムに処理を渡し、重い処理を行ってもらう方針で設計を進める。その別のプログラムでは、Queue(待ち行列)によるタスクを採用し、リクエストを受けるとQueueに入れて1つずつpopしていくことによって作業の単一化を満たす。
もともとCGIについてはrubyにて実装していたので、drubyと呼ばれる仕組みを採用するに至った。drubyとはrubyのオブジェクトをそのまま通信に乗せることができるイメージの分散通信を行わせるライブラリであり、TCPソケットなどを意識しないでuriだけでサービスを定義できる。drubyを用いた分散は例えば「はてなスクリーンショット」にて採用されていたりする。
このdrubyを用いて変換したいファイルオブジェクト、タイトル、コメントをサーバプログラム側に渡していたのだが、どうもサーバプログラム側でコネクションが切れてしまったとエラーを出してしまい、重い作業を中断してしまう。
そこでdrubyサーバプログラム側で”hello”としか表示しないメソッドを定義して、CGIから叩かせた所、コネクション関係のエラーが出ないことに気がついた。さらにこのメソッドではCGIプログラム側にdrubyサービスの起動が必要なかった。drubyサービスは相手からの通信データを受けるために必要だ。
drubyサーバに渡していたデータのうち、ファイルオブジェクトを文字列(string)にした所、コネクションによるエラーは発生しなくなった。これが値渡しなのだと考えている。ファイルオブジェクトの場合、参照渡しになってしまい、そのファイルオブジェクトの変更をサーバプログラムの処理終了後に受け取ろうとするが、CGIプログラムは短命なのでdrubyサーバが終了してしまい、エラーが発生してしまったのだと今では考えている。
待ち行列の実装自体はrubyの方に存在しており、q = Queue.newで作成、q.push taskでタスクを入れる、loop do; task = q.pop〜 endにて無限ループでタスクを出すという方針で上手くいっている。q.popはブロッキングしてくれるので、taskが0の場合にpop以後の処理を行ってしまうということはない。このため簡潔に記述することができる。
上記のハマりポイントを脱し、drubyによる分散化の利点を達成することができた。
drubyによる分散CGI設計とハマりポイント への2件のフィードバック