2005年04月27日
Rubyでの排他制御
サーバアプリケーションを開発する場合、避けて通れないのが排他制御。
Rubyにはいくつかの方法が準備してある。まず、File#flock。これは、UNIX系のOSで標準のflock(2)そのもの。
実際にSOAPのサーバで使ってみたが、これはうまく動かない。何故なら、File#flockは、プロセスに対して動くものだから。soap4rのサーバは、Rubyスレッドで実現されているので、多数のスレッドを起動しても、プロセスとしては一つだけ。File#flockであるスレッドPがロックをかけた後、別のスレッドQがロックをかけると、プロセスの実行がそこでブロックされてしまう。ということはスレッドQだけでなく、スレッドPも停止状態になってしまうということ。別の言葉で言うと、File#flockはスレッドセーフではない。
Soap4rのサーバがスレッドを利用しているのなら、スレッドセーフな排他制御を使えばよいわけだ。最もポピュラーなのは、Mutexを使うことだろう。
今回の実装も、これを使うことにした。
soap4r(webrick)問題
今回のサーバ=クライアント間のRPCには、SOAPを使っている。開発中に、サーバがフリーズするという問題に見舞われた。問題は、クライアントからのリクエストが殺到したときに起きることが判った。これはきっと、サーバ側にスレッドセーフでないコードが含まれているからだな、と考えた。
このsoap4rは、webrickを使っている。どちらの問題なのか切り分けるため、webrickでも同等のプログラムを作成し、実行してみると…、やはりサーバフリーズ。どうも、webrick以下の問題らしい。
で、webrickやopensslの開発者の一人であるごとうゆうぞうさんに相談してみたところ、最新版のRubyに最新版のopenssl(for ruby)が入っているので、それで試せ、という助言をいただいた。試すと…動く!
というわけで、現行バージョンのsoap4rをご使用中あるいは開発中、設計中の皆さん、リリース版ではなく、最新安定板を使いましょう。
2005年04月15日
サーバコードの取り込み
IAServer、RAServer、EEServerのコード、lib/C16r/(ia|ra|ee)server.rbをパッケージに取り込みました。
今のところ、各プログラムを実行して、SOAPのRPCを処理するサーバが立ち上がるところまでと、
test/TestIAServer.rbを書いている途中ですが。
ちなみに、
前のエントリで検討した設定値の問題は、(IA|RA|EE)Server#config=(hash)というメソッドを準備することで回避している。コードを参照のこと。
2005年04月11日
サーバ設定のためのラッパークラス?
現在、EEServer、RAServer、IAServerなどのクラスは、通信相手などを定数で持っている。例えば、RAServerは、IAServerに対してPKCS#12の発行をSOAPで要求するが、このとき先ず、IAServer側のURIや名前空間を事前に知っている必要がある。
s = SOAP::RPC::Driver::new(IASERVER_URI,IASERVER_NAMESPACE)
次に、IAServerの提供しているメソッド名および引数(の数)を知っている必要がある。
s.add_method("ias_issue_p12","p12_password","key_length","o","ou","cn","em
ailAddress","issuerAltName","friendly_name")
また、セッション情報はファイルで格納することになっているが、これらのファイルが格納されるディレクトリを指定する必要がある。
File::open("#{RASERVER_DATA_PATH}#{session_id}.2",'r') do |file|
これらの定数は、現在の実装ではクラス定数として定義されている。このため、このクラスから生成したインスタンスは、すべて同じ定数を参照することになる。
しかし本来、これらの定数は、インスタンス変数として生成時もしくはその後に使用目的に沿った値で初期化されるべきだ。なぜなら例えば、RAサーバは、複数のRAに対するRAサーバとして動作することがあるためだ。この場合、セッション情報の保存先やIAサーバを切り替える、ということが考えられるだろう。
SOAP::RPC::HTTPServerの下位クラスでinitializeが定義できるのなら良いのだが、そうでないとすれば、これらの設定を保持するためのラッパークラスで包んであげる必要があるのかな。
2005年04月08日
サーバコードの取り込み準備
各サーバにバラバラになっていたプログラムを整理中です.
基本方針は, 以下の通り:
- 各プログラムバラバラに定義されていたオブジェクトを,lib/C16r/C16rCommon.rb の中でmodule CommunityPKIBuilder の定数として定 義する.
- 各サーバのクラスは,
- CommunityPKIBuilder::EEServer
CommunityPKIBuilder::RAServer- CommunityPKIBuilder::IAServer
とする.- エラークラスを整理する.
- require '...' はファイルの先頭に集める.
などなど.
作業中のファイルをここで公開するのは…まだまずいかな。
2005年04月07日
試験用証明書自動生成
試験用の証明書を発行するスクリプト、test/gen_certs.rbを追加した。
これに伴い、証明書のファイル名などを定数として定義するtest/param.rbを追加した。
証明書は自動生成になったので、test/{cakey.pem,cacert.pem}などは削除した。
鍵用途
CACAnetCAを変更し、X.509 version 3拡張領域のkeyUsage、extendedKeyUsage、basicConstraintsを変更した。
CACAnetCA#create_self_signed_certificate
証明書の拡張領域のモードを指定できるようにした。
デフォルトは、CA。
2005年04月05日
有効期限切れ
テストスクリプト中に含まれているtest/cacert.pemが有効期限切れになっています。
おかげでテストスクリプトがfailします。
すぐ直しますんで、しばらくお待ちください。