Posts Tagged ‘Scala’
EventStatsはherokuとMongoLabとさくらVPSで動いている
今月頭にブログ書きましたが、EventStatsという勉強会の参加者の推移が見れるサービスを公開しました。
まぁ自分が欲しかっただけなんですけど、使ってみて頂ければ幸いです。
今回はそのサービスの構成とかについて書いてみます。
アジェンダ
- 全体像
- システム構成
- Gitリポジトリ
- MongoDBのPaaS
- 各イベント管理サービスAPIの違い
- 開発メモ
1.全体像
開発環境も含めて全体像を図にしてみました。(初Cacooですが超べんりですね!)
赤い線がGit操作で、黒い点線がMongoDBへのアクセスです。
2.システム構成
大きく分けてwebとクローラーの2つです。
webはherokuに、クローラーはさくらのVPSに配置。
まずは優先してデータ蓄積を…ということでクローラーをpythonとmongodbで作成しました。
(サービス的にはやいとこデータためないと意味ないので。)
クローラーは5分おきに起動するのでScalaよりPythonを選択しました。起動コスト重視です。
(Scalaでサクサク開発できる程のスキルではないというのもありますが…)
実行場所はherokuのworkerも考えたましたが、最終的に既に利用していたさくらVPSでcronジョブとして運用することに。
ということでScalaのWebはデータ参照のみで、データの更新はしません。
3.Gitリポジトリ
webとクローラーは分けてGitで管理。リモートリポジトリはどちらもさくらのVPS上においています。
ただし、本番リリースは開発PCからherokuに別途pushします。
※webもさくらVPSにリモートリポジトリを持って、本番データを参照するステージング環境として利用しています。
eventstats-web
- host: heroku (Chedar)
- scala
- フレームワーク: unfiltered 0.5.1
- mongodb接続: casbah 2.1.5-1
- テンプレートエンジン: unfiltered-scalate (ssp)
- テスティングライブラリ: unfiltered-specs
- チャートのレンダリング: Google Chart Tools
eventstats-crawler
- host: さくらのvps
- python 2.6
- フレームワーク: なし
- mongodb接続: pymongo 1.11
- テスティングライブラリ: nose
- その他: BeautifulSoup (partake.inのwebスクレイピングに利用)
4.MongoDBのPaas
herokuプラグインとしてMongoLabとMongoHQの2つが提供されています。どちらも無料枠があるのですが、MongoLabの方が無料で利用できる容量が大きいのでこちらを選択。
月額の利用料金は以下です。(括弧内は1MBあたりの金額の目安です)
これ以上の容量も利用可能ですが個人で払う範囲ではないと思い除外してます。
MongoLab
- $ 0.00/240MB
- $10.00/0.5GB ($0.020/MB)
- $20.00/2.0GB ($0.009/MB)
MongoHQ
- $ 0.00/ 16MB
- $ 5.00/256MB ($0.019/MB)
- $15.00/2.0GB ($0.007/MB)
5.各イベント管理サービスAPIの違い
まずはatnd, zusaar, partake.inの3サービスに対応。
それぞれ検索APIを提供してくれているのですが、当然ながら規格とかもないのでリクエストもレスポンスも違いがあります。
データ蓄積する際にそのAPIの差異を吸収して、webアプリから参照する際は気にしなくていい戦略をとりました。
APIの違い検索のみに特化して違いをまとめると以下の通りです。
atnd
イベント数も多いので、このAPIをスタンダードに設定。
- API仕様
- リクエストパス
- /events/
- イベントの検索
- /events/users/
- イベントに参加しているユーザーの検索
zusaar
基本的にはatnd準拠っぽい感じだけど細かい違いがあります。
- API仕様
- リクエストパス
- /api/event/
- イベントの検索
- /api/event/user/
- イベントに参加しているユーザーの検索
- /api/event/
atndとの違い
- エントリポイントやデータのキー名が単数形
- events→event
- users→user
- 明確なフィールドとしてのtwitter_idが無い
- 管理者も参加ユーザーも
- ハッシュタグがない
- レスポンスはjson一択
partake.in
全然違うAPI。APIリストにあっても未実装がほとんどなので、利用する際はソースを確認したほうが良いです。
今回必要になりそうなAPIは2つくらいでした。
- API仕様
- リクエストパス
- /api/event/search
- イベントの検索
- /api/event/get
- イベントの詳細データ取得
- /api/event/search
- APIのソース(抜粋)
その他の特徴は以下。
- 複数イベントを特定して一括取得するAPIはない
- フィールド名がcamelCase形式
- レスポンスはjson一択
- 検索パラメータも特殊かつ少数
- 検索APIで取得できるのはイベントの固定情報のみ
- 参加枠数はAPIから取得可能
- 変動するユーザー数は取得不可能
- →Webページをスクレイピングするしかないという結論
上記をふまえ、atnd/zusaarはJSON形式でAPIからデータ取得。
partake.inのみイベントのリストをAPIから取得して、ユーザー数はWebページのスクレイピングで対応しました。
6.開発メモ
web(heroku)からもクローラー(さくらのvps)からも離れた場所にある
開発PC上だと気にならなかったのですが、1件1件findしてinsertやupdateをしていると当然遅いです。なのである程度まとめて一気にinsertする方針に変更しました(ベンチ結果はありません ^^;)。
更新はクローラーの1プロセスからのみ実行されるので、トランザクションとか意識しなくて良いです。なので比較的自由な構成がとれます。
ScalaでJSON API
まずはUnfilteredでJSON APIを作成。けど、jsでjson取得〜チャート生成の実行時間が思いの外大きいので、jsonも1枚のHTMLに埋め込む方針に変更。
さいごに
ざっと書きだすとこんな感じです。まぁこんな構成もあるよ、ってくらいにしか言えませんが。
webとクローラーを分けたことで、開発中のスキーマ変更が柔軟に行えたのは良かったのですが、スキーマ定義を共通で管理していないので、そのあたりうまく管理できると良いなと思ったり。
当初はもう少しwebの機能も多かったのですが、効率化をしているうちにシンプルな形に落ち着きました。Scalaのコードもかなり小規模なものになっています。
イベント管理者の方からのご意見ご要望などいただけると嬉しいです
![]()
If you enjoyed this article please consider staying updated via RSS. Links to your own social media pages could be added here.
- Tags: casbah, eventstats, heroku, mongodb, pymongo, python, Scala, unfiltered
- Posted in python, Scala, Webサービス
- No Comments
Scalaで設定ファイルを使いたい時どうしたらいいの?
2011.08.31 kmizushimaさんから頂いたコメントを元に、下記の記述を修正&追記しました。
- Twitterのutil-evalの一時ファイル生成について
- AkkaのConfigファイルのパース手法について
TwitterのOAuthの鍵やDB接続情報など、アプリを書く上で環境によって切り替える設定が大抵の場合あると思います。普段使っているPHPの場合、設定を外部ファイルに書きだす場合、ini,yaml,xml,phpのいずれかを使うことが多いのですが、Scalaの場合、設定ファイルってどうするのか気になりました。
ということで、適当に思いついたライブラリやフレームワークがどのように対応しているのか調査。
ライブラリ
propertiesファイル
- javaの古くから使われている
- キーと値のみ設定可能
- 依存関係がないので手軽。
- すべてが文字列
- 例えばこんな感じ
path/to/conf.properties
1 | hoge = "moge" |
1 2 3 | val p = new java.util.Properties() val config = p.load(new java.io.FileInputStream("path/to/conf.properties"); config.get("hoge") // "moge" |
twitterのconfiggy
- https://github.com/robey/configgy
- 独自フォーマット
- オワコン
twitterのutil-eval
- http://twitter.github.com/util/
- Evalした値をそのまま利用
- Scalaのコンパイラに任せられる。つまりScalaコードがそのまま設定ファイルに。
- 型安全
- 詳しいことはこちらを参照
- 下記処理にて設定クラスインスタンスをapply経由で取り出せる
一時的にjarファイルを生成するので環境に制約あるとダメ(たぶん)- 一時ファイルを生成するのは、ローカルにcloneした古いままのバージョン(1.2.5)で動作確認していたためでした。
- 古いコード: com.twitter.util.EvaluatorのコメントにAll generated .scala and .class files are stored, by default, in System.getProperty(“java.io.tmpdir”)と書いてあったので、「一時ファイルが生成される」と認識し、実際の動作確認でもその一時ファイルが確認できていました。
- しかし、新しいコード: com.twitter.util.EvalのコメントにはIf target is None, the results are compiled to memory (and are therefore ephemeral)とある通り、パス指定がない場合はメモリ上の仮想ディレクトリに対して操作を行う模様です。
使い方
設定のtraitを定義
src/main/scala/com/restartr/utilSample/MyConfig.scala
1 2 3 4 5 | package com.restartr.utilSample trait MyConfig { val num: Int val str: String } |
実際の設定ファイルでは、設定のTraitを継承してインスタンス生成
※クラスインスタンスでなくても文字列やリストでもOK。
path/to/config/MyConfig.scala
1 2 3 4 5 | import com.restartr.utilSample.MyConfig new MyConfig { val num = 1 val str = "san" } |
使いたい場所でEval。
1 2 3 | val conf = Eval[MyConfig](new java.io.File("path/to/config/MyConfig.scala")) conf.num // 1 conf.str // "san" |
configrity
- https://github.com/paradigmatic/Configrity
- akkaのフォーマットと同等
- 設定のフォーマット
- Scala 2.9以上対象。
- configファイルの読み書きができる
- immutable, thread safe, allow functional design pattern
各種フレームワーク
以下のフレームワークはすべて独自実装でした。Propertiesじゃ役不足だし、かといってデファクトな設定用ライブラリがないからなのでしょうか。
akkaのconfig
- akka.confとかがそれ。
- 独自パーサーを使用
- 70行程度のシンプルなパーサー
- akka.config.ConfigParser
正規表現で定義されてるScalaのパーザコンビネータ(RegexParsersを継承)で定義されている- “{“と”}”で階層構造を表現
1 2 3 4 5 | akka { cluster{ name = "test-cluster" } } |
- 使える型
- 数値
- 文字列
- 真偽値(on/off , true/false)
- リスト [1,2,3] / ["hoge","moge"]
play!frameworkのconfig
- 独自パーサー
- java.util.propertiesを継承したもの。
- 環境ごとにIDを割り当てられる
- http://playdocja.appspot.com/documentation/1.2.1/production
- http://playdocja.appspot.com/documentation/1.2.1/guide11
- IDごとに%{ID}を頭につければ切り替えてくれるみたい
Lift
- LiftRulesが設定をもつ
ざっと調べて使ってみたところ、手軽にやるならProperties、フレームワークを使うならそれに則り、厳密にやるならTwitterのEvalや、設定ファイルを読み書きできる独特なConfigrityなんかがよさそうです。
XMLは…まぁないでしょうね。
![]()
If you enjoyed this article please consider staying updated via RSS. Links to your own social media pages could be added here.
- Tags: config, library, Scala
- Posted in Scala
- 2 Comments
