D-7 <altijd in beweging>

Day to day life of a Perl/Go/C/C++/whatever hacker. May include anything from tech, food, and family.

2011年06月

6/22 修正: mod_perlじゃなくてただのapache moduleだった。自分の中でmod_perlとapache moduleが同じ箱に入ってて違和感なくmod_perlって書いちゃった・・・

-----

今の職場ではちょっと前から「開発支援」という名目で仕事をしている。まぁ要は「ちゃんとVCS使え」「テスト書け!」「プロセスを自動化しろ!」とか煩いことを言うおっさんの役目なわけです。

まぁそんな事をしてるのであんまり表側のアプリとかを直接触ったりはしないのですが、あるとき突然某システムの話をしてるときに「あ、これオブジェクトストレージに突っ込もう」という話になりました。聞くともう大分前から使ってるSで始まって、Tが間にあって、Fで終わるオブジェクトストレージの事らしいんですが、これのフロントエンドがmod_perl apache moduleで書かれてるわけですよ。

・・・テストできない(しづらい)じゃん!

そんなわけでAPIの基本部分だけでいいからPSGIのがほしいよね!ってことになり、Plack-App-STFってのを書いて、これを通してテストするようにしてみた・・・のが運の尽き。IRCでどっかのCTOさんが「本体も書き直してよ」的な事を言うわけですよ。

しょうがないですよね。昔はどうであれ僕も今はサラリーマンですからね。役職にChiefってつく人に言われたらやりましょう。

というわけでとあるオブジェクトストレージのフロントエンドがmod_perl apache moduleで書かれてたのを完全にPSGIベースに直して、この間からすこーーーしずつリプレースをしようという事で作業をしている。

元々動いているシステムなので全部入れ替わるのは大分先の話だろうけど・・・

で、まぁまだソースコード出してないけど、今回これを作るのにやったことやなんとなく思ったことなど。

仕組みとしてはディスパッチャーがあり、こいつが裏方にある複数台のストレージノードにGET/PUT/DELETEを発行する形でデータのやりとりをしている。例えば GET http://stf/hoge.jpg とかしたら、裏にN台ある/hoge.jpgを保管してあるストレージの中から一台を選んでそいつのデータをクライアントに送る。

これまでのコードは mod_proxyに近いことを apache module内でやってたんだけど、Plack/PSGIでProxyとかなんかPerlのリソースの無駄遣いな気がしたので mod_reproxyを使う事にしたのが大きな変更点のひとつ。要は新しいバージョンからディスパッチャーがまずランダムにHEADを裏方に発行して、一番速く、かつ200が帰ってきたストレージのURLをX-Reproxy-URLでmod_reproxyに送るというもの。

このmod_reproxyは弊社の内部事情でフロントがapacheなので@kazuho氏謹製のmod_reproxyを使っている・・・が、一部問題が出たので色々俺俺な変更を入れたmod_reproxyを現在はつかっている次第。マージ/レビューを待っている今日この頃!

あと、裏方にHTTPリクエストを送る方法なんだが、これ複数リクエストを同時に送って待つ、みたいなコードだからここだけ非同期にしたら速いんじゃね?とか安易な考えで実装してみたら正直大して速くなかった。まぁそこだけイベントループのスタート・終了がある分オーバーヘッドがあるわけだし当然っちゃあ当然なんだけど、それよりFurlの速いこと速いこと。もうこの手のAPIとかを叩く系のクライアントは本当Furlだけでいいよ。変にI/O多重化するより普通のループでFurlをぶんまわしたほうが全然速い。

最後に、はまったこと。歴史的な事情によりID生成の際のロック機構にSysV IPCを使ってるんだけど、semaphoreはグローバルだってことをみんな忘れないでな!特に、Starletとかの中のアプリでsemaphore使ってると、時々世代交代が起こることを忘れるな!DESTROYとかに $sem->removeとか入れておくと確保したはずのsemaphoreが子プロセスに勝手に消されてて他のプロセスが簡単に死ぬぜ。こういうのはDESTROYとかの中で if ($$ == $parent_pid) とかしてちゃんと「リソースを作ったプロセス」が「リソースを解放するプロセス」かどうか確認してから解放しましょう。



まぁそんなわけでmod_perl apache moduleだったオブジェクトストレージをPSGIで書き直した。正直大分コードの見通しもよくなった気がするし、なによりMiddlewareとかも使えるし、拡張性がぐっとあがったので満足。パフォーマンスはまったく遜色ないかと思う。

ロケタッチとかの一部サービスは今ヘッダを見るとPerlが裏で動いているのが見えるはずですね。しかしこれは開発支援なのか?という疑問は未だに残っている。

おしまい。



    このエントリーをはてなブックマークに追加 mixiチェック Share on Tumblr

Learn Python The Hard WayAdvice From An Old Programmerにとても良いことが書いてあった

Which programming language you learn and use does not matter. Do not get sucked into the religion surrounding programing languages as that will only blind you to their true purpose of being your tool for doing interesting things.

自分はJapan Perl Associationとかやってるけど、これはいつも思ってる。

根本的には正直みんなが選ぶ言語がPerlじゃなくてもいいとさえ思ってる。問題発言かもしれないけど、自分はPerlとその文化が好きだから是非みんなにPerlを選択肢の一つとして選んで欲しいし、Perlを選ぶことによって得られるメリットはたくさんあるとは思う物の、プログラマとしては別にどの言語を選ぶなんてどうでもいい

(じゃあなんでJPAとかやってるかというと、Perlという選択肢をみんなに公平に判断して欲しいから。まぁこれはまた別のエントリになる話だけど、要は古い情報や感情的な意見だけじゃなくて、ちゃんとメリットデメリットを判断できる形にしてからみんなに判断してほしい)

そのかわり上の引用の通り、一つの言語だけ知っててその「宗教」にはまりそれ以外を覚える必要がないと言ってる人とか、あまりにも抽象的な理由で言語の好き嫌い言ってる人は普通にエンジニアとしてはどうかな・・・と思う。

言語はツール・表現方法であって、ただ適材適所だと自分は思ってる。


自分はPerlは好きだけど、普段は必要に応じてCも書けばJavascriptも書くし、今まで「手を入れた」程度のプログラムだったらJavaもRubyもPHPもC++もLispもやってる(実はメジャーな言語でpythonだけは見ただけで書いた事がない)。どれも別に本質的には言語云々ではなく、たまたまやりたい事があったからそれに合う道具でやった、っていうだけ。

まぁ、そんなわけで言語Xのほうが言語Yより・・・とかどうでもいいし、みんなもっとゆるーくやんなよ。色々出来るってのが一番重宝がられると思うしね。




(ちなみに色々な言語を使えるようになるためには普段使ってる自然言語と一緒で、ひとつの「主言語」は奥深いところまで押さえておく必要はあると思うのでなんでもかんでも手を出せばいいというわけではないのでそこは注意が必要かな)


以上、雑文でした。

    このエントリーをはてなブックマークに追加 mixiチェック Share on Tumblr

週末にsupervisorっていうものについて話してる人がいたので、特に理由なくPerlでクローンを書いてみようと思った。というわけで本当に基本の部分まで書いた。名前はBrahman。神様の名前にしたかったのはプロセスの生死を管理するから。

繰り返すけど、特に理由はない。書きたかったから。ちなみに内部的には多分本家と全然互換性はない。設定ファイルがだいたいクローンできればいいや、というくらい。


今のところできることは、例えば今daemontoolsで管理してるplakupサーバーがあったとして、こんな感じの設定を書くと立ち上がってstdout/stderrを一緒のログに保存してくれる、ってところまで。

[program:yourapp]
environment=PORT=50000
directory=/service/yourapp
command=/service/yourapp/run
stdout_logfile=/var/log/yourapp.log
redirect_stderr=true

以上を書いて、brahmand -c config.ini とか書くと勝手にこのプロセスがずっと生きてるように管理してくれるでござる。brachmanctl list とかすると、現在動いているプロセスとかでてくるので、supervisor.processes.pid あたりをkillしてみると生き返るのが見えるかと思います。

一応頑張った点としては、万が一 ログのプロセスが死んじゃったとしても、daemontoolsのsuperviseに相当するプロセスが生き残ってればまたログを取るプロセスが生き返って、もう一度アタッチしてログをとり続けられる事と、ログを取る以外のプロセスもアタッチすることによってイベントを受け付ける事ができる、など。

あと外部からのコマンドうけつけはJSONRPCで行う。今はごめん、list(動いているプロセスとかをリスト)とstop(brahmandと管理してるプロセスをストップ)しかできないけど、しこしこ書いていけばいくらでもAPIは追加できる。

ここまで正味二日間でできた。JSONRPCは以前書いた物の流用、あとはTwiggyとかを以前からバリバリ書いてたおかげで楽だった。Twiggyがそのままエンベッドできるのにも助かった。

とりあえず自分の使ってる開発サーバーはこいつに移行できるようにしてみようかな、と思ってるけど、人柱とか一緒にやってくれる人がいると嬉しいなー、と。

    このエントリーをはてなブックマークに追加 mixiチェック Share on Tumblr

このページのトップヘ