JSON-lib 2.4のバグを見つけた気がする

JavaJSONを扱うときにJSON-libを使ってるんですが、JSON文字列からJSONObjectにパースするところでバグっぽいのに遭遇しました。
以下のJSON文字列をパースしようとするとClassCastExceptionが出ます。

{"hoge":{"{}":"fuga"}}

確認したのは以下のコード。

public class Main {
    public static void main(String[] args) {
        /**
         * OKパターン
         */
        String ok = "{\"{}\":\"fuga\"}";
        JSONObject okObject = JSONObject.fromObject(ok);

        /**
         * NGパターン
         */
        String ng = "{\"hoge\":{\"{}\":\"fuga\"}}";
        try {
            JSONObject.fromObject(ng);
        }
        catch (ClassCastException e) {
            e.printStackTrace(); // 出る
        }

        /**
         * NGパターン2
         */
        JSONObject ng2 = new JSONObject();
        try {
            ng2.put("hoge", okObject);
        }
        catch (ClassCastException e) {
            e.printStackTrace(); // 出る
        }
    }
}

ネストしたオブジェクトのキーが、JSONのオブジェクトとして解釈できる文字列だとダメっぽいです。他にも以下の文字列がダメでした。

{"hoge":{"[]":"fuga"}}
{"hoge":{"null":"fuga"}}
{"hoge":{"function(){}":"fuga"}}

修正しようにもソースが見つからないし、どうもプロジェクト自体メンテされてない感じがしたので、回避するには他のライブラリに乗り換えるしかなさそうです。
Javaで使えるJSONのライブラリでおすすめがあったら教えて下さい。もしくはJsonConfigをうまいこと設定すれば回避できるなら、そっちの方法も知りたいです。

さくらのVPSにRubyの環境を構築したときのメモ

さくらのVPSの新プランに申し込んだので早速環境構築をしました。RedmineGITLABを動かす予定なので、RVMを使ってRuby1.8.7Ruby1.9.2をインストールしたときのメモです。

環境


プラン:さくらのVPS 1G
OS:CentOS 6 x86_64

ユーザ作成とログイン周りの整理

初期状態だとrootユーザでログインすることになるので、以下の記事を参考に作業用のユーザを作成します。

さくらのVPS開通後にやったこと

作成したユーザでログインして作業します。今回はユーザ名を ope で作成したので、適宣読み替えてください。

user@local$ ssh ope@サーバのIPアドレス

RVMをマルチユーザ環境にインストール

RVMをマルチユーザ環境にインストールします。別にマルチユーザ環境じゃなくてもいいですが、なんとなくやってみたかったのでマルチユーザ環境にインストールしました。マルチユーザ環境にインストールするには、インストールのコマンドを sudo で実行すればいいだけのようです。

ope@remote$ sudo bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

マルチユーザ環境にインストールすると /usr/local/rvm 以下にインストールされます。このディレクトリは rvm というグループに書き込み権限が与えられているので、ope を rvm グループに追加します。

ope@remote$ sudo /usr/sbin/usermod -a -G rvm ope

RVMの環境をロードするためにファイルを読み込まないといけないのですが、何を読み込んだらいいんだろう? /etc/profile.d/rvm.sh かな?よくわからなかったので一旦ログアウトして再ログインしました。

ope@remote$ exit
user@local$ ssh ope@サーバのIPアドレス

以上で RVM の準備が完了です。

Rubyをインストール

以下のコマンドでRuby1.8.7Ruby1.9.2をインストールします。

ope@remote$ rvm install 1.8.7
..... # なにやらインストールっぽいログ
ope@remote$ rvm install 1.9.2
..... # なにやらインストールっぽいログ

デフォルトでRuby1.9.2を使いたいので、以下のコマンドを入力します。

ope@remote$ rvm use 1.9.2 --default

バージョンを確認して、1.9.2になってたら完了。

ope@remote$ ruby -v
ruby 1.9.2p318 (2012-02-14 revision 34678) [x86_64-linux]

Ruby1.8.7が使いたくなったら以下のコマンドを入力すれば、そのセッションの間だけRuby1.8.7が使えます。

ope@remote$ rvm use 1.8.7
Using /usr/local/rvm/gems/ruby-1.8.7-p358
ope@remote$ ruby -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]

いい感じ。

第2回 渋谷Edge Rails勉強会 に行ってきました #shibuyarails

最近Rails3の勉強を始めてて、ちょうどいいタイミングで勉強会があったので参加してきました。

【満員御礼/増員230名】 第2回 渋谷Edge Rails勉強会 @masuidrive氏によるRails3講義 × 株式会社ドリコム事例発表

講師は風呂グラマーとして有名な @masuidrive さん。以前 Titanium Mobile の勉強会でお会いしたのですが、まさかRails勉強会でも会うことになるとは。

今回は先日購入した新しいiPadを実戦投入してみたということでメモを取るのに必死で途中聞けなかったんですが、頑張ってまとめてみます。

内容はRailsの歴史から始まって、Railsを取り巻く環境(経済面)とか開発・運用の話、Railsの今後について広く浅くという感じでした。ところどころ具体的な話が出てきて色々参考になりました。気になった点は以下のとおり。

  • Railsアプリを監視するNew Relicというサービスがある
  • Railsアプリを開発・運用してるとバージョン追従問題に躓く
  • テストを書いてないとRailsアプリの運用は大変
  • レベル別デプロイというアイデア
  • Scaffoldは使わない
Railsアプリを監視するNew Relicというサービスがある

これはすごいです。New Relic というサービスなんですが、Railsアプリのレスポンスのパフォーマンスだけでなく、メソッド呼び出しレベルまで落としこんで計測できるらしいです。どのメソッドにどれだけの時間がかかっているからそこをチューニングすれば云々とかが一発でわかりますね。
いいなーって思ったんですが、1サーバの監視で月額1万円くらいするらしく、個人にはちょっと辛いサービスだなという感じです。でも使ってみたい。

Railsアプリを開発・運用してるとバージョン追従問題に躓く

Railsの場合バージョンが0.1でも違うと大きく変わっていたりして、大変らしいです。Twitterのタイムラインを見ていても2.x系から3.0にバージョンアップするより、3.0から3.1にバージョンアップするほうが苦労したなんて人もいました。それぐらい大変。
でもそれにはRailsのしっかりとした思想があって「変化を進んで受け入れる」ということらしいです。開発者のDHHさん曰く「テストをしっかり書いて、テストがこけた部分だけ修正すればいいじゃん」みたいなことらしいです。

テストを書いてないとRailsアプリの運用は大変

ということで、テストを書いてないとRailsアプリの運用は大変みたいです。周辺のライブラリのバージョンを上げる必要が出てきて、そのバージョンを上げるためにはRails本体のバージョンも上げないと行けなくなって大変。みたいなことが起こるそうです。
コードとテストの比率は1:3位が理想だけど、最低でも1:1は必要とのこと。1:3という比率は、コードを書くのに1週間かかったら、そのテストを書くのに3習慣かかるってことらしい。大変。

レベル別デプロイというアイデア

レベル別デプロイってどういう事かというと、新機能を追加するときにステージング環境を用意しないで、最初から本番環境にデプロイしましょうということ。ただし、新機能を公開する範囲を制限する。最初にそのサービスの開発者だけが使えるように制限して、その後、部内→社内→αテスタ→βテスタ→全体公開という流れで開放していく。そうすることでスムーズに新機能が追加できるよねということ。
現場でよく聞く「開発環境だと動くんですけど」なんて言い訳を効かなくなる日もそう遠くない?

これはクックパッドかどこかがやってたよなーって思ってたら、質問タイムでそういう話が出てきました。なんていうプロダクトか忘れましたがなんかあるっぽいです。

Scaffoldは使わない

衝撃的でした。railsを初めて触ったときに衝撃を受けた機能なだけに、それを使わないっていうのも衝撃的でした。まあ、Model定義してController書いてroute.rb編集してView書いてってしたほうが自分の思ったような挙動になるよね。というか、モデルに対する単純なCRUDなんて、実際のアプリケーションだとそんなに多く無いのかな。

感想

masuidriveさんの後にもう一つ「Railsのはまりポイント10選」という発表もあったのですが、iPadでメモを取ることに疲れてそんなにメモが取れていません。申し訳ない。ただ、気をつけようと思ったのは以下の2つ。どちらもMySQL使用時に引っかかりそうな罠です。

  • index名の長さ

MySQLのindex名は64文字まで。
Railsが生成するindex名の規則は「テーブル名_カラム名1_カラム名2_....」みたいになるので要注意。

  • tinyintという型について

ActiveRecordではMySQLのtinyintはbooleanとして扱われる。

おまけ

iPadを使って一生懸命とったメモを貼っておきます。


Railsの歴史から

2005年にrails誕生
特徴
CoC
DRY
MVC
フルスタック
Generator/Scaffold
Write less code
なるべく少ないコードでいろいろできる
問題点
不安定
遅い
メモリ食い
実績が少ない
Rubyプログラマが少ない
特に海外

2007年 rails2
特徴
RESTfull
XMLからJSON
問題
実装複雑
他のフレームワークが出てきた
Merb まーぶ
モデル != テーブル
DataMapper

周辺
Merbベースにrailsを作るぞ!
周辺サービスが出てきた
heroku
new ralic 監視サービス
railsプラグインとして組み込める
月1万円くらい
Engine yard
しばらく食べていけそうな経済圏が出来ている

2010年 rails3
特徴
問題
バージョン追従問題
本体のバージョンを固定するとプラグインのバージョンを上げられない
バージョンアップにはテストが必要
3.2.2でほぼ完成

Railsの思想
変化を進んで受け入れる
互換性よりはプログラムとしての正しさを追求する

向いてるアプリ
一般的なwebサービス
変化が激しい
apiを提供する

コードを書く
黙々かく
後で呪われないように
scaffoldは使わないよね
プラグインを使うか、使わないか

テストを書く
変化への備え
最低でもtest/codeは1.0を超えたい
3あるといい
UnitTest vs RSpec
密かに裏コマンドを用意する
テストデータを作る

パフォーマンス
ベンチマーク
sqlレベルでチューニングするしかない
特にmysql
キャッシュ
memcached使ってます
routes重いよ

運用
Unicorn? Passenger?
heroku
監視

レベル別デプロイ
一部のユーザのみに新しいコードをデプロイ
開発者 部内 社内 あるふぁ べーた 全体 という段階を踏む
ますいさんがnginxモジュールとして開発中
クックパッドが似たようなの作ってたよ

rails4
次のバージョンは4
今年出る予定
Ruby1.9
REST 強化
Railsは大きくなりすぎてる懸念
モジュール化しすぎててどこを直せばいいかわからない

Delayed Jobはいけてないの?
何となくresque使ってます

rails for zombie

JAWS SUMMIT 2012 DAY2 に行ってきました

JAWS SUMMIT 2012 2日目のクラウドデザインパターンに関する講演を聞いてきました。題目は「ベストプラクティス:RIA とスマホクラウド

メモした限りの内容を以下にまとめます。


AWSにはサービスを止めない運用のために必要な機能が揃っている
・EC2
・ELB
・AutoScaling
・CloudWatch
・自動スナップショット
・RDS

・RIAに求められる良いレスポンスを実現するには

・リクエスト数を減らす
・ファイルをまとめる
CSSのスライスとか使う

・適切に配置
・htmlの上にcss,下にjs
・動的htmjでcss/jsを書かない
・RequireJs等を使ってjsを非同期で読み込む

・静的ファイルをS3,CloudFrontへ
・EC2、ELBの負荷が減る
・HTML等はgzip圧縮したものを置いておく
・S3 or CloudFront どっちを使えばいい?
・S3でも十分だが、速度を求めるならCloudFront
・CroudFrontは東京と大阪にエッジロケーションがある
・速度的には5倍くらい出る
・アクセス権等の細かい設定をしたければS3
・手作業で設定するのがめんどくさい
・キャッシュ設定
gzip設定とか
・ビルドツールを使え
・antとか

DNSにはRoute53
・切り替えが一瞬

・ディスクアクセスを減らす
・EC2とEBSはネットワークでつながっている
インスタンスタイプによって、その帯域幅が変わる
・ログをファイルに出しすぎない
・fluentd的なものをつかってS3へ
・ディスクアクセスを高速化したい時は
・大きいインスタンスを使う
・RAID0を組む
・ephemeralディスクを使う
・シーケンシャルなアクセスが早い
・EC2で使えるディスクの性能はブログを参照
http://dev.classmethod.jp/ria/amazon-ec2-ebs-ranking/

・データベース(RDBMS)へのアクセスを減らす
・データベース(RDBMS)で何を管理するか?
・データベース(RDBMS)になんでもかんでも入れない
・データベース(RDBMS)に処理が集中するからボトルネックになる
AWSをうまく使え
・SPOF(単一障害点)がないサービスが一杯ある
・データベース(RDBMS)への問い合わせを減らす方法
・キャッシュを使う
Amazon Elasticache
RDBMSを使わない
・DynamoDB
・SimpleDB
・操作ログや履歴
・S3
・その解析
・Elastic MapReduce

・DynamoDBが熱い
・アトミックカウンタが優秀
・座席の予約
ソーシャルゲームのパラメータ
・その他いろいろ使える

感想

EBSの帯域幅インスタンスタイプによって変わるのは知りませんでした。いままで何でもかんでもとりあえずEBSみたいな感じにしてたのでちょっと反省してます。まあ、t1.microを使ってる限りはEBS以外選択肢がないんですがね。あと、ログの出しすぎも反省。開発中はまだしも、製品版ではちゃんとしないといけないと思いました。fluentdも検討したけど結局導入してないし。

DynamoDBはリリース直後からバリバリ触ってますけど、使いどころさえ間違えなければいい感じです。それこそアトミックカウンタが生きるところではかなり使えると思います。レコード数のcountとかsumとか集計を取りたいようなところでは使わないほうがいいと思います。特にレコード数のcount操作は罠が潜んでるので気をつけたほうがいいです。

http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/QueryAndScan.html#Count

DynamoDBは3月1日に東京リージョンもできたことですし、もっと日本語の情報が増えると嬉しいなと思います。現時点ではとにかく夢が詰まってるDBという感じです。僕の中で。

そういえばRIAのこともスマホのことも特に出てこなかったような・・・。

RubyでN-gramを計算するメソッド

RubyN-gramを計算するメソッドを作ったよーって言うメモです。

class String
  def ngram n
    characters = self.split(//u)
    return [self] if characters.size <= n
    return 0.upto(characters.size-n).collect do |i|
      characters[i, n].join
    end
  end
end

p "おぎやはぎですけど何か問題でも?".ngram(2)
# => ["おぎ", "ぎや", "やは", "はぎ", "ぎで", "です", "すけ", "けど", "ど何", "何か", "か問", "問題", "題で", "でも", "も?"]

ideoneで動かした結果

※ 2012-02-11 12:14 追記 ちょっと改良しました

-      characters[i..(i+n-1)].join
+      characters[i, n].join

※ 2012-02-11 12:45 コメントでeach_consメソッドを教えてもらいました

class String
  def ngram n
    characters = self.split(//u)
    return [self] if characters.size <= n
    return characters.each_cons(n).collect(&:join)
  end
end

DynamoDBやSimpleDBのモデリングにはクラス図を使ってみたらどうだろうか #jawsug

先日発表されたAmazon DynamoDBをつかうアプリケーションを設計する時、モデリングをどうしようかと困っていたのですが、クラス図を使うといい感じに表現できそうです。

Developer GuideのUse Case 2を例に図を書いて見ました。

ER図を使って表現した場合

図はMySQL Workbenchを使って書きました。
この図には幾つか問題点があります。

  • HashKey, RangeKeyの表現ができていない
  • ThreadテーブルのTagsのような複数の値をもつカラムの表現ができていない
  • テーブル間の関係がよくわからない

クラス図を使って表現した場合

図はastah* communityを使って書きました。
この図は、ER図で表現した場合の問題点をすべて解消しています。

  • 各テーブルのHashKey, RangeKeyは何か
  • ThreadテーブルのTagsがStringの配列であること
  • ForumとThreadが1対多、ThreadとReplyが1対多であること

まとめ

ツールの問題という部分もありますが、クラス図なら型を自由に定義できるため、良い感じに表現できているのではないでしょうか。これはDynamoDBやSimpleDBに限らず、MongoDBやその他のスキーマレスなDBでも使えそうな気がします。

ナウなヤングのsleep事情

Javaで一定時間sleepする時Thread.sleep()を使っていたんですけど、もっとナウい方法があったのでメモしておきます。

try {
  // レガシー極まりない5秒sleep
  Thread.sleep(5000);
}
catch(InterruptedException e) {}

try {
  // ナウなヤングの5秒sleep
  TimeUnit.SECONDS.sleep(5);
}
catch(InterruptedException e) {}

これでもう「5日間って何ミリ秒だっけ?!」とか考えるまもなく直感的にsleep出来ますね。

  // 5日
  TimeUnit.DAYS.sleep(5);