帰り道、空を見ると月が綺麗でした。

何気ないことを綺麗だと思うことを忘れない様にしたい。というひとりごと。
帰り道、空を見ると月が綺麗でした。

何気ないことを綺麗だと思うことを忘れない様にしたい。というひとりごと。
bit.lyで短縮されたURLのクリック状況は短縮されたURLの末尾に'+'をつけると知ることができるので、そこからクリック数をスクレイピングしてみようという話。*1
# bitlycun.rb require 'nokogiri' require 'open-uri' url = "https://bit.ly/#{ARGV[0]}+" page = open(url) html = Nokogiri::HTML(page.read, nil, 'UTF-8') html_a = html.search('//span[@class="count"]') tmp = html_a[0].children.text clickcun = tmp.gsub(/(\r\n|\r|\n)/, "") puts "http://bit.ly/#{ARGV[0]} : click count = #{clickcun}"
スクリプトを実行する際、引数にbit.lyで短縮した際の可変部分(http://bit.ly/***** の ***** ) を第一引数に渡せば現在までのクリック数を取得することができる。
% ruby bitlycun.rb IxW4jJ
http://bit.ly/IxW4jJ : click count = 3
*1:ネタとして探したらあちこちにありそうだったけど…(略
意外とまだ咲いていた。

REMP Ver.2.5をリリースしました。REMPを利用しているユーザのオンライン状態を確認できるようになり、デスクトップへの通知に対応しました。また操作パフォーマンスも大幅に向上しています。 URL
2012-03-25 23:06:27 via web
と、twitterではお知らせしたのですが、改めて。
REMP Ver.2.5をリリースしました。*1
見た目上の大きな変更や派手な機能追加は無いのですが、以下の様な点が改善されています。
機能的に新しくなったのはログイン状態表示とデスクトップ通知になります。
REMPでは、自分のfriendsに対して自分が見つけたYoutube動画を送ることができるのですが、もし誰から動画が送られた瞬間にログインしている状態であればChromeのデスクトップ通知の機能を利用して画面上にポップアップして通知させることができます。ちょうどイメージ的には、メールソフトでメールを受信したときに表示されるNotifyのポップアップの様なイメージです。
また、自分の友達がREMPにログインして操作開始したことも同様にデスクトップ通知で知ることができます。
設定は、画面左下の歯車のアイコンで設定をすることができます。

あと、細かいところではブラウザサイズを小さくした際にREMPのプレイヤー上部に表示される再生ボタン等のサイズが絶妙に調整される様になっています。細かいところで@hika69のコダワリが出ています。*2
自分が担当したサーバ側の技術的な部分では、通知系にはPUSHERを利用したWebsocket経由でのフックを使っていたり、ログアウト検出用に独自のお手軽メッセージキューを使ったりしていますが、そのあたりはまたブログに書いていきたいと思います。
(PUSHERの話題は、このあたりを参照)
Hi!
では、実際に現在のREMPの場合において、どの程度メモリ使用量が変化したのかを確認してみました。
Apacheをフロントのリバースプロキシとして、背後にRack用のWebサーバ(Thin or unicorn)を動かすという挙動はかわらないので、Thinとunicornの両方のサーバを立てて、リバースプロキシ(mod_proxy)で均等に複数のプロセスで起動させているthinサーバとunicornにアクセスする様にして3分毎に実メモリ使用量を監視してグラフにしてみました。
mod_proxyの設定は以下の様な形にしています。以下の様に設定することでthinの1プロセスとunicornへ均等にアクセスがされる様にしています。
<IfModule mod_proxy.c> (中略) <Proxy balancer://***> BalancerMember http://127.0.0.1:4040 loadfactor=10 #thinのプロセス(1/2) BalancerMember http://127.0.0.1:4041 loadfactor=10 #thinのプロセス(2/2) BalancerMember http://127.0.0.1:4044 loadfactor=20 #unicornのプロセス </Proxy> </IfModule>
で、この様な設定にした状態でREMPの本番環境にしてみたところ、得られた各プロセスが消費しているメモリ使用量の変化は以下の様な具合です。
(赤色の線がThinの1プロセス vs 緑色の線がunicornのマスタープロセス+水色の線がunicornのワーカープロセス で比較すればよいのかな。と。)
少なくてもREMPのAPIサーバ側のSinatraで実装したアプリをThinの上で稼働させた場合とunicornで稼働させた場合を比較するケースでは、単純に見ると半分程度にメモリ使用量を押さえることができる様です。
もう少し更に検証したいと思います。
REMPで今までApacheのリバースプロキシを通してthinサーバでAPIを稼働させていたのですが、稼働時間が長くなるとメモリの利用割合が増える状況が続いていたため、どうしようかと悩んでいたところ会社でmizzyさん(@gosukenator)からunicornだとメモリ利用量が押さえられるという話を伺ったので早速切り替えてみました。
unicornは、Rack 環境をロードした master プロセスが fork して子の worker を作る仕組みになっているため、安定性とメモリ利用量を小さくすることができることが期待されます。
unicornのインストールはgemを使うことで簡単に行えます。
$ sudo gem install unicorn
現在、REMPのAPIサーバはthinで動いているのでアプリケーションのルートにunicornの設定ファイルを書き足すことでunicorn上でアプリをすぐに動かすことができます。
ここでは、
設定例を書いています。
# unicorn.conf listen "/tmp/unicorn.sock", :backlog => 64 preload_app true port = 4044 listen port worker_processes 4 pid "tmp/pids/unicorn.pid" stderr_path "log/unicorn_error.log" stdout_path "log/unicorn_out.log"
この設定ファイルを書き足せば以下のコマンドですぐに動かすことができます。
(-Dでデーモン化)
$ unicorn -c unicorn.conf -D
設定ファイル内のログに正常にログが吐かれていれば、稼働していることを確認することができます。
$ cat log/unicorn_error.log 125.***.***.*** - - [18/Mar/2012 18:56:11] "GET /status/info HTTP/1.1" 200 2 0.0045 125.***.***.*** - - [18/Mar/2012 18:56:11] "GET /status/info HTTP/1.1" 200 2 0.0531
自分用メモ。
サーバ上で起動させているThinサーバを再起動させたい場合、
$ thin -C thin.yaml restart
と行うと、yamlでthinのプロセスが常駐する様に設定していた場合、一度全部のプロセスを閉じた後、設定数分のプロセスの起動が行われるため、接続が不可能な状態が一瞬生じます。
せっかく複数プロセスが稼働しているのであれば、一つずつのプロセスで再起動がかけられればよいので、方法を調べたところ --onebyone というオプションを付与することで実現できました。
$ thin -C thin.yaml --onebyone restart
といった具合。
こうすると、以下の様に個々のプロセスの停止と起動が繰り返されます。
$ thin -C thin.yaml --onebyone restart Stopping server on 0.0.0.0:4040 ... Sending QUIT signal to process 12835 ... >> Waiting for 1 connection(s) to finish, can take up to 30 sec, CTRL+C to stop now >> Exiting! Starting server on 0.0.0.0:4040 ... Waiting for server to start ... Stopping server on 0.0.0.0:4041 ... Sending QUIT signal to process 12846 ... Starting server on 0.0.0.0:4041 ... Waiting for server to start ... (以下略)
REMP開発中に誤爆して本番環境上の開発者のプレイリストがうっかり意図しない内容に更新してしまうというケースが生じたため、デイリーでとっているmongo DBのバックアップから復旧させてみました。*1
行いたいのは、特定のユーザのプレイリストのみの復旧なので、単純にmongorestoreする訳にはいかないので、方法として以下の手順で復旧させました。
以下、復旧した際のメモをば…。
まず、保管されていたバックアップファイルを展開します。
[ローカル環境]
% tar xvzf rempdb-20120228.tgz
rempdb-20120228/
rempdb-20120228/rempdb/
rempdb-20120228/rempdb/library.bson
(中略)
前段で展開されるバックアップファイルの中身のファイルがJSONであれば、直接テキストファイルなので編集して該当するユーザのコレクションのみの抽出も行えるのですが、BSONのため一度手元のmongo dbに取り込んで処理することにしました。
リストアはmongorestoreコマンドを使えばよいので、リファレンスに従って操作して、
[ローカル環境]
% mongorestore -d rempdb --drop rempdb-20120228/rempdb
connected to: 127.0.0.1
Wed Feb 29 17:43:12 rempdb-20120228/rempdb/library.bson
Wed Feb 29 17:43:12 going into namespace [rempdb.library]
Wed Feb 29 17:43:12 dropping
(中略)
これで手元のmongo dbにバックアップファイルの内容がリストアされました。
(コマンドの末尾のパスはバックアップファイルの展開先)
サーバ側で復旧させたいユーザのREMPのプレイリストを抽出するためmongoexportコマンドを利用して、該当ドキュメントのJSONファイルを出力させます。
mongoexportコマンドを使うとDBやコレクションを特定し且つ、クエリを与えてヒットしたドキュメントのJSONだけを出力することができます。
[ローカル環境]
% mongoexport -d rempdb -c library -q "{uid:'1234567'}" -o playlist.json
connected to: 127.0.0.1
exported 1 records
中身を見てみると。。。
[ローカル環境]
% cat playlist.json
{ 〜 , "uid" : "1234567" }
と、クエリで抽出されたドキュメントのJSONファイルがそのまま出力されているはずなので、その内容がリストア対象であることを確認します。
ローカル環境でまるごとリストアしたDBから出力した特定のドキュメントのJSONをサーバ側でインポートします。
mongoimportコマンドを利用することでJSONファイルをmongo DBにインポートすることができるので、以下の様にコマンドを入力。
[サーバ環境(リストアしたいDB側)]
% mongoimport -d rempdb -c library playlist.json --upsert
connected to: 127.0.0.1
imported 1 objects
これでサーバ上のmongo DBへバックアップファイルから取得した特定のドキュメントのみを復旧させることができました。
mongoのバージョンが古い場合、mongoimportコマンドに --upsertオプションが無い場合は、一旦ドキュメントを消してインポートすると良い…のかな。
MongoDB shell version: 1.*.*
connecting to: ***
>db.**.remove({uid:"1234567"})
>
で一度消して、
% mongoimport -d rempdb -c library playlist.json
connected to: 127.0.0.1
imported 1 objects
といった具合。
*1:あ、念のためですが他のユーザの方に影響はありません。開発用のクライアントを操作している際に生じたケースです。
Web CAT Studio (株式会社リクルートエージェント)主催のTitanium Mobileの勉強会に参加してきました。
200名近く参加されており、やはり注目の技術なのだなと実感しました。(7割近くがエンジニアの方, あとはディレクターやデザイナーの方)
ひと通り聴き終わっての感想は…。
といった具合です。
何はともあれ面白そうなので、早速何かつくってみようかな…。
以下、雑ではありますが、参加した際に作成したメモです。
ただし、ObjCとかJavaで拡張できる。(但し両方OSに対応する必要あり)
有償のモジュールも使える
最近のコメント