« 2012年6月 | メイン | 2012年8月 »

2012年7月

2012年7月24日 (火)

PlayとMySQLとサロゲートペア

MySQLで文字コードを「utf8」とした場合UnicodeのBMPしか扱えないそうです。

http://yanok.net/2010/06/mysqlutf-8.html

サロゲートペアを扱う必要がある場合は最初から文字コードを「utf8mb4」として定義しないといけないらしい。。。(--
なんとも残念な仕様です。「Unicode対応」と言いつつサロゲートペア未対応のものはたまにあるので、そこにはそれほど驚きませんが対応するのであれば「utf8mb4」みたいな新しいキーワードを導入するのではなく「utf8」として対応してほしかったと思います。

DB作成の際には文字コードは意識しますが何の迷いもなく「utf8」を選ぶっちゅーの(--

そんな愚痴はさておいて、ここではPlayframework(1.2.5)からMySQLのutf8mb4なデータベースを扱う話をします。

MySQLでutf8mb4のデータベースを作成する方法については色々なところで紹介されているのでここでは特にとりあげません。それだけはまった人が多いってことですよね(^^;;;

さて、MySQLのutf8mb4化も終わり次にPlayのアプリケーションからINSERT/SELECTのテストを試みたんですが、最初はやっぱりサロゲートペアが正しく扱われませんでした。

データベース側の設定がまだ足りてないのかといろいろ試行錯誤したんですが、これ実はPlay側の設定の問題でした。

PlayではDBの設定はapplication.confで行うのですが、その設定方法には

db=mysql://user:pwd@host/database

のように1行にユーザー名やパスワードなどのすべての情報を記述する方法と

db.url=jdbc:mysql://host/database
db.driver=com.mysql.jdbc.Driver
db.user=user
db.pass=password

のように4行にばらして指定する方法があります。
1行でまとめて指定する方法が使用できるのはPostgreSQLやMySQLなどのPlayが標準で対応しているDBだけでOracleやSQLServerを使用する場合は常にばらした記述方法を使用しなければならないのですが、可能な場合は1行設定を使用することの方が多いかと思います。

ここに罠があります。
1行設定は内部的に4行の個別設定にばらされるのですが、この時にdb.urlが

db.url=jdbc:mysql://host/database?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8_general_ci

のようにエンコーディングのオプションをハードコードで付加された形で設定されてしまうのです。
このためutf8mb4のデータベースを使用する際は1行設定は使用することができず

db.url=jdbc:mysql://host/database?useUnicode=yes&characterEncoding=UTF-8&connectionCollation=utf8mb4_general_ci
db.driver=com.mysql.jdbc.Driver
db.user=user
db.pass=password

のようにutf8mb4を明示してバラに設定する必要があります。

2012年7月20日 (金)

Herokuの負荷テスト

こんにちは。小西です。
Herokuの負荷テストの結果を公開したので興味のある方はご覧ください。

http://excelnote.herokuapp.com/share/note/s91/90bf7b19-d654-40ab-a6c0-640980967ab0/edf9ab2230042e456ca286843763788e

考察は自分用のメモなので文章が荒いのは気にしないように。(Evernoteだし)

えぇ、このエントリの主目的はきっぱりはっきりDEVCUPの宣伝です。(^^;
ちょっとでも役に立ったという方は是非ExcelNoteに一票投じてください。m(_ _)m

ExcelNoteにはシートの一部のみをiframeで表示する機能もあるので、表の部分だけをこちらのブログに貼り付けようかとも思ったんですが、表が少し幅があるためブログにきれいに収まらないことからこういう形をとりました。

背景の白い部分がExcelで作成した資料なわけですがコメントがつけられたりリンクが貼れたりするのは地味に便利です。
ちなみにExcelNoteのサンプル一覧はこちら

https://www.evernote.com/shard/s91/sh/ff42fdc3-a143-4019-a1f6-9828fb03faa9/3f441690243667851b8711e2e82939a3

一般投票期間中はできるだけサンプルを増やそうかと思ってるですが、普段Excelをほとんど使わないのでネタがなくて困ってます。(--

さて、これだけでは何なので負荷テストの結果を踏まえてHerokuとPlay(1系)でアプリを作成する際のポイントを簡単にまとめておきます。

・Memcachedは必須
dynoを増やすとリクエストはラウンドロビンで各dynoに割り振られます。
セッションは考慮されないのでセッション変数的なものを使用する場合はMemcacheが必須になります。
(Playのsessionの実体はCookieなので文字列しか保存できないしセキュリティ的に使えないことも多い)
ちなみにHerokuのアドオンとしてはMemcacheとMemcachierの2つがありますが、無料枠が大きいのでMemcachierの方がお得です。

・パフォーマンスは金で買える
単純なラウンドロビンなので基本的にはDynoを増やせばそれだけで負荷分散できます。
もちろんアプリの中でstaticな変数を使ってはいけないなどスケールさせるために考慮しなければならない事項はありますが、それ以外はアクセス数やメモリ使用量に関してそれ程シビアに考える必要はなさそうです。

・負荷はNewRelicで計測
Web transactions -> Slowest average response time
Dynos -> Average memory usage per dyno

あたりを眺めていれば、なんとなくDynoの増減のタイミングはつかめそうです。

・ログはPaperTrailがお勧め
Herokuのログ管理アドオンはやたらとたくさんあって、いくつか試してみたんですが個人的にはPaperTrailがダントツでお勧めです。
WebUIも見やすいですし、APIでログを自由に取得できるのも良いです。
Herokuのアクセスログには処理時間やDyno番号など結構な情報量があるので、いずれはこのログを解析して負荷や傾向を分析するツールも作成しようと思っています。
あと地味に日時表示のタイムゾーンを変換してくれるのもありがたいです。

・application.confに「XForwardedSupport=all」を必ず設定する
Herokuへのアクセスがhttpsであっても、そこから各dynoへのリクエストはhttpで行われます。
そのため、この設定がない場合リダイレクト時に元がhttpsであってもhttpにリダイレクトされてしまいます。
これは知らないと気がつきにくいので注意が必要です。

とりあえずはこんなところですかね。
他にもいろいろあるんですが、それはまたおいおい。(^^;

2012年7月 9日 (月)

ExcelをHTML5Canvasに描画するお話

こんにちは、小西です。

FLECTではExcelをWebブラウザ上に描画する技術(Excel2Canvas)を開発しており、そのサンプルアプリケーションを公開していますが、この技術は非常に応用範囲の広いものだと考えています。
その応用例のひとつとして現在Evernoteで行われているプログラミングコンテスト(DEVCUP)にEvernoteに添付したExcelファイルをブラウザ上でインラインに表示/共有できるアプリを出品しています。

http://devcup.evernote.com/submissions/8567-excelnote

元々はExcel2Canvasを何に使おうかなということを考えていた段階でたまたまEvernoteでDEVCUPをやっていることに気がついて、じゃこれに出してみようかと軽い気持ちで作成したものです。
なので準備期間も短く、ドメインもherokuappのままなのでどうかとは思いますが実用性は実はエントリ作品の中でもかなり高いほうなんじゃないかと思っています。(ちなみにDEVCUPへの出品自体は個人活動ですが、heroku上で動作するアプリケーションやAddOnがどの程度使えるかを検証することは業務です。)

現在絶賛一般投票中なので、もしよろしければ左上のVoteボタンをクリックしてやってください。(^^;
1日に1回投票できるので毎日投票してくれても良いです。(^^;;;

これだけではなんなので今日はExcel2Canvasが中でどういうことをやっているかについて解説してみたいと思います。

★サーバーサイド

サーバーサイドではApache POIを使ってExcelの情報を抜き出しています。
取得する情報は以下の4つに分解しています。

背景色情報
  - セルの背景色
  - 網掛けなどのパターン種別
  - パターンの色

罫線情報
  - セルの4辺のどこに罫線が引かれているか
  - 罫線の種別(太線、ダッシュ線など)
  - 罫線の色

画像情報
  - 添付されている画像(jpeg,png)のバイナリとその位置

文字(セル)情報
  - 書式設定を適用したセルの値(計算式の場合はその計算結果)
  - 右寄せ、左寄せなどの位置情報
  - フォントと文字装飾と色
  - セルの結合情報

これら4種の情報をひとつのJSONにまとめてクライアントに返しています。

★クライアントサイド

クライアント側ではサーバーから返された情報をCanvasに描画しています。
具体的には以下の順序で処理を行っています。

1、背景色情報でCanvasを塗りつぶし
2、罫線情報でラインを引く
3、画像情報をimgタグでCanvas上に絶対位置で配置
4、文字情報をセルごとにdivタグにして絶対位置で配置

右寄せや左寄せなどのセル内での位置はそれぞれCSSでclass定義しています。

ちなみに背景色や罫線は現時点ではサーバー側から情報は取れていてもすべてを描画はしていません。
たとえば背景色の場合現在行っているのは単色での塗りつぶしのみでパターンの描画はしていません。
もちろん網掛けなんかは自分で少しずつ位置をずらしながらlineToを繰り返せば描画できるわけですが、Excelのサポートする描画パターンを調べ上げてそれに一つずつ対応するというのはさすがにちょっと。。。。めんどくさいんですよ!(言っちゃった。。。(--)
同様に罫線についても長線・短線・短線のような3組で1パターンとなるような線種については未実装です。(シンプルな単線になります。)

若干言い訳くさいですが、サポートするパターンが増えればそれだけjsファイルは肥大化するので、いずれにせよどこかでこういう線引きは必要です。
(もちろん使用頻度の高そうなものを今後実装するのはやぶさかではありません。)

以上、実際には罫線の情報をある程度まとめたり、セルをはみだした長い文字列を結合したりなどの最適化処理も行っていますが、基本的にはこれだけです。

★POIの話

POIのAPIドキュメントを見ると上に挙げた情報はAPIで普通に取れそうに見えます。まぁもちろんそう思ったからこそ作り始めたわけですし、実際最初のプロトを作るまでには2日とかかりませんでした。
が、実際にはそこから先が茨の道です。

以下いくつかはまりどころをあげてみます。

色の取得の仕方がxlsとxlsxで異なる

背景などの色の持ち方はxlsの場合IndexedColorと言って「1番は何色、2番は何色」というようにワークブックごとに番号と色の対応が決まっています。
一方xlsxの場合はIndexedColorの他にRGBでの指定やテーマでの色指定など複数のデータの持ち方があります。
が、POIのxls/xlsx共通インターフェースから取得できるのは多くの場合IndexedColorだけなのでxlsxの場合はキャストして専用APIを使用して色を取得する必要があります。
(ちなみにテーマを使用した場合の色の取得方法がMSのドキュメントを見てもどうしてもわからなかったので現在未対応です。)

日本語日付書式全滅

Excelでは内部的に日付データはDoubleで持っており、どんなライブラリを使用する場合でも日付の扱いは鬼門となるんですが、POIでの日本語日付の扱いはお話にならない位ひどいです。(--
仕方がないので

http://support.microsoft.com/kb/883199/ja

を参考に日付書式のパーサーを全部自分で書き直しましたが、今度は逆に日本語以外の書式設定が正しく扱えていないのではないかという不安はあります。

列幅の計算がやっかい

Excelではセルの列幅を「デフォルトフォントの文字何個分」というデータの持ち方をしています。例えば日本語版Excelの場合は初期状態で列幅は「8.38」となっていますが、これは「MS Pゴシック11ptで数字が8.38文字収まる幅」という意味です。
英語版Excelの場合はデフォルトフォントは(おそらく)Arial10ptなので、同じ数字であってもセル幅は異なります。
しかもデフォルトフォントからセル幅を計算する方法も結局地道に実測して割り出したので非常に面倒です。(GraphicsContextに描画してstringWidthを取るという方法も試しましたが、結局微妙な幅があわずにあきらめました。)

現状対応しているデフォルトフォントは「MS Pゴシック11pt」と「Arial10pt」のみなのでそれ以外をデフォルトフォントとするファイルがある場合はセル幅が微妙にずれるはずです。(--

計算式がどの程度サポートされているのか謎

何故かWeekday関数がサポートされていなかったり。。。
Subtotal関数がものすごく根本的なところでバグっていたり。。。
と正直計算式がどの程度ちゃんと動くのかは未知数です。
直せるところは自分で直したりPOIにバグレポをあげたりもしていますが、おそらくこの辺りはPOIの中でもあまりたたかれていない部分のような気がするので他にも色々と問題はありそうです。

などなど。
他にもいっぱいありますが、それ以外にもまだ気がついていない問題もたくさんあるだろうとは思っています。

★Excel2Canvasの今後

FLECTの主業務はSIなのでとりあえずはその方向での活用していくことになります。具体的なターゲットとしてはまず帳票を考えていて、Excelで作成した帳票フォーマットがそのままブラウザで表示できてさらにブラウザから印刷までできるとなるとかなりニーズはありそうです。

Excel2Canvas自体の機能としては今後、グラフや条件付き書式に対応できると良いなと思っていますが時期は未定です。また、それらは対応するとしてもおそらくxlsxのみの対応となります。(POIにはそれらを取得するためのAPIがないので、ooxmlから直で情報を取得することになるからです。)

グラフは一度トライしかけたんですが、そもそもExcelで思ったとおりのグラフを作ることができなくてコードを書く以前のところで挫折しました。(^^;;;

正直その辺まで来ると自分ひとりの手には余ると思っていて、オープンソース化なども検討していますが、当面そのための作業の優先順位は低いです。

2012年7月 2日 (月)

Play1とPlay2の比較 - まとめ編

ども。小西です。
ちょっと間が空いてしまいました。

その間に世の中ではplay2.0.2がリリースされました。

https://groups.google.com/forum/#!msg/play-framework/Z97GQ2VnR5M/T-STGaeuN68J

リリースメールを見る限り大きな変更点はなく、バグ修正といけてないコードのリファクタリングが主なんではないかと思います。
手元のアプリをバージョンアップしてみても特に差は感じませんでした。

さて、数回にわたって書いてきたPlay1とPlay2の比較記事もそろそろたたんでしまいたいと思います。
今回は使いながら気がついた細かい点をつらつらと書いてみます。




★heroku編
Play2は普通にherokuで動作しますが、新規アプリケーションを作成して1行もコードを書かない状態でpushしてもいきなりSlugサイズが40MBを超えます。
Apache POIなど大き目のjarファイルをいくつかインクルードするとそれだけで60MB超。困ったことにpushにかかる時間は約2分です。

herokuのドキュメントには「Slugサイズが50MBを超えたら構成を見直せ」みたいなことが書かれているんですが、フレームワークだけでそのサイズを超過するのでもはやユーザーにできることはありません。。。(--

ちなみにPlay1でもイニシャルで20数MBになるので、こちらも重いフレームワークではあるんですけどね。

いずれにせよherokuで使うことを考えたらPlay2はちょっとお勧めできません。

 

 

 

★WS編
前にも書いたと思いますがPlay2のWebServiceクライアントであるWSクラスでは同期APIが削除され非同期APIのみとなっています。
非同期APIの方がスレッドを効率的に使えるという理屈はわかりますし、今後は非同期APIが主流になっていくというのもそうなのかもしれません。
でも

http://www.playframework.org/documentation/2.0.2/ScalaWS

のサンプルを見ると結局同期でレスポンスを返しているので意味ないんでは。。。と思ってしまいます。(--

実際JDBCをはじめGoogleやAWSのSDKもほとんど同期APIなので、ここだけ非同期にすることにどの程度の効果があるのかは疑問です。
結局のところWebサーバーの仕事はクライアントに対して何らかのレスポンスを同期で返すことなんで、複数の外部サービスにすべて非同期でアクセスして待ち合わせするようなケース以外では非同期のメリットは享受できない気がします。

であれば、WSから同期APIを削除したメリットはほとんどなくて先のサンプルのようにユーザーに非同期プログラミングを意識させなければいけないというデメリットだけが残っているように見えます。

個人的にはWSの同期APIは復活してほしいです。

 

 

 

 

★JSON編
JSONを扱うためのライブラリがGoogleのgsonからjacksonに替わっています。
ざっとドキュメントを読んだ感じだと、使い勝手はそれほど変わらない様だしパフォーマンスに関してはjacksonの方が大分速いようです。

これだけであればjacksonへの変更はむしろ歓迎なわけですが、フレクトでは社内のライブラリでgsonをメチャメチャ多用しているのでPlay2にあげた場合でもgsonを使い続けるという選択になります。(--

パフォーマンスという観点ではPlay1.2.4ではgsonのバージョンが1.7.1だったのが、Play1.2.5では2.2にあがるようなのでそこはちょっと期待しています。(2012/07/02時点の最新版は2.2.1です)

 

 

 

 

★その他のライブラリ編
これを書くに当たってBuild.scalaを見直していて思い出しましたが、log4jも標準では入っていません。
デフォルトのLoggerはslf4j+logback。
log4jの開発は事実上終了しているので新たに起こしたプロジェクトとしてはこの選択は妥当だと思います。

そうはいっても、なんかライブラリ入れるとすぐにlog4jも一緒に入っちゃいますけどね。

 

 

 

 

★まとめ
大体持ちネタは以上です。
今回Play2のソースはまぁまぁ読みましたが、実際にはそれ程多くのものを作ってはいないので、色々と勘違い等もあるかもしれませんがこうした技術系のブログを読む場合はそのすべてを鵜呑みにしてはいけないというのは基本だと思うので、そのつもりで軽く読み流していただければ幸いです。(^^;;;

読んでてわかると思いますが、現状では僕のPlay2の評価はそれほど高くはありません。良いところもたくさんあるんですが、それらはほとんどPlay2の長所というよりもScalaの長所なんですよね。
Scalaは好きな言語なんでそれを使って開発したいという気持ちはあるんですが、当面はPlay1を使うことになりそうです。

採用情報

株式会社フレクトでは、事業拡大のため、
Salesforce/Force.comのアプリケーション
開発
HerokuやAWSなどのクラウドプラッ
トフォーム上でのWebアプリケーション開発

エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみた
い方、是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、
セールスフォースパートナーです。
heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。
Powered by Six Apart