2010-02-22

  • ago
  • Mon, 22 Feb 2010 00: 00
  • aws
  • rds

こないだ初めてスノボ体験しました。agoです。

弊社ではAmazon Web サービスを利用してmixi、モバゲーアプリを提供していますが、その中でも今日はRDS(MySQLホスティングサービス)の利点と欠点を紹介したいと思います。

利点

  • 設定が容易

my.cnfを設定せずとも各instance classに合わせて各種パフォーマンス項目が設定済みのため、設定を変更せずとも使用開始時からある程度の性能を出すことが可能です。

  • AWSのSecurity Groupsと連携できる

EC2 instanceはサーバ負荷によって台数が増減するため、通常のIP制限では台数を変更するたびに制限するIPを変更する必要があります。

これに関しては通常のEC2 instanceでMySQLサーバを立てるときにも専用のSecurity Groupを用意することで連携は可能ですが、RDSの場合、RDSを使用しているしているアカウント以外のSecurity Groupも指定できるためより柔軟な運用が可能です。

  • 容易にスケールアップができる

コマンドから簡単にRDS intanceのスケールアップが可能です。

通常のEC2 instanceにMySQLサーバをインストールして運用する場合でも、Elastic IP、EBS等を使用して同じように容易なスケールアップを実現することは可能ですが、そういった設定なしに最初からコマンド一行でスケールアップできることが保証されている環境は魅力です。

  • バックアップ、スナップショット等の環境が用意されている

バックアップ、リストアに関して専用手順が用意されているため、特にこちら側で考慮する必要がありません。

  • パッチ等を自動で適応してくれる

必要最低限のパッチのみ自動で適応してくれます。

適応時間は一週間の中でこちらで指定した4時間の間に適応されますが、実際運用していると適応されるのはだいたい一ヶ月に一度程度のようです。

欠点

  • レプリケーションができない

現在大きな問題点としてRDSはレプリケーション設定が行えないことがあげられます。

これに関してはAmazonでも解決に向けて対応しているとのことなので、そう遠くない内に解決することを期待しています。

また、この点が解決されれば以下であげている欠点のいくつかも解決できる可能性が高いため、より選択肢として有望になると考えています。

  • エラーログが見られない

shellが公開されていないため、OSやMySQLのエラーログ等が見えません。

専用環境のため起動不能等でエラーログが重要になる可能性は低いのですが、それでもいざというときに原因を追及できない可能性が高いです。

ただ、slow query logはテーブルに出力することで閲覧可能です。

blog.hori-uchi.com: AmazonRDSでslow queryを出力するようにする方法

  • 設定の変更にInstance rebootが必要

通常のEC2 instanceにMySQLサーバをインストールした状態でもmy.cnfの変更はmysqldのrestartが必要ですが、RDSの場合この変更がInstance rebootになるため反映までに数分のダウンタイムが必要になります。

普段必要な作業ではないですが、「通常のMySQLサーバに比べて設定変更に時間がかかる」というのは覚えておいていいと思います。

  • バックアップが遅い

日毎のバックアップで数分間(20GBで3分程度)のダウンタイムが発生します。

これに関しては実際のデータ使用量ではなく確保したDBのサイズによって時間がかかるようなので、実データの量によっては付近のEC2 instance上からmysqldump等でバックアップした方が早いです。

  • 週一のメンテナンス時間が必須

現状最低でも4時間設定する必要があるためダウンタイムを0にすることができません。

これに関しては実際メンテナンスでダウンする頻度はそれほど多くないのですが、4時間の内いつダウンするかわからないため一週間の内必ず不安定になる可能性のある時間が発生することになります。

  • メモリの使用率が見えない

CPU使用率等は外部サービスのYlasticCloudWatchのパッケージに含まれるmon-get-statsを使用することにより確認できますが、メモリ使用量は確認することができません。
(ただ、YlasticがどうやってRDSのリソースをグラフ化しているかわかりませんでした。RDSCli.zip内に該当するコマンドは確認できなかったのですが。。。)
2010/2/26 社内からの指摘で修正しました。

DBサーバはメモリ使用率も重要なため、この点で負荷が上がってきた場合の原因を追求するのが困難になる可能性はあります。

まとめ

簡単に開始できる点は魅力ですが、ダウンタイム等を考慮するとまだEC2にMySQLインストールする方が利点は大きいと考えています。

容易にスケールアップできる点は魅力と言えば魅力ですが、レプリケーションが使えないため割と早く最上位クラスの限界に達します。

そうなった場合RDSでは打つ手が無くなるため、通常のアプリであればレプリケーションでスレーブサーバを増やす構成の方が性能限界は高くなると感じています。

ただ、欠点に関してはレプリケーションができないことが大きいため、これが解決されればもっと利用できる範囲は多くなると思います。

カヤックではクラウド好きな技術者を募集しています!

2010-02-01

KAYACモバゲー参入に伴いAmazon Web Serviceと格闘中のagoです。

弊社ではPC版mixiアプリもいくつか作成しておりますが、今回そこで得られたノウハウを集めてmixiアプリ フレームワークを公開しました。

ソースコード github

opensocialに関しては過去にjquery.opensocial-simple.jsを公開しておりますが、社内からも「JSなしでmixi appを作りたい」と言う要望もあり、今回frameworkの形で公開いたしました。

コンセプト

JSを書かなくてもそこそこリッチなmixi appが作れるフレームワーク

機能

  • OWNER、VIEWER情報の取得
  • マイミク情報の取得
  • 指定mixi IDユーザ情報の取得
  • 画面遷移の制御
  • 表示領域の自動調整
  • 「日記に書く」リンクの自動設定
  • アクティビティの発行
  • 「友達を誘う」機能の追加

詳細はgithubをご覧ください。

ソースコード github

カヤックではフレームワークを造ることが好きな技術者を募集しています!

2010-01-25

時が経つのは早いもので、ぼーとしてたらもう1月も終わりそうですね。外村です。

先日リリースされたjQuery1.4で新しく追加されたメソッドや新しい使い方ができるようになった機能を全部ではないですがいくつか紹介します。以下に変更点が全て掲載されているのでそちらも参照するといいと思います。

Version 1.4 – jQuery API

新規で追加されたメソッド

1. nextUntil()、prevUntil()、parentsUntil()

指定したセレクタまでの要素を返します。以下の例ではitem3とitem4の後ろにテキストが追加されます。

<ul>  
    <li id="item1">item1</li>  
    <li id="item2">item2</li>  
    <li id="item3">item3</li>  
    <li id="item4">item4</li>  
    <li id="item5">item5</li>
</ul>

$('#item2').nextUntil('#item5').append('[foo]');

nextUntil()は後方、prevUntil()は前方、parentsUntil()だと親要素を探します。

2. delay()

指定の時間処理を遅らせます。アニメーションの途中などに挟んで使うようです。下記のようにするとsilidUpとfadeInのあいだに1000ms時間が空きます。

$('#foo').slideUp(300).delay(1000).fadeIn(400);

.delay() – jQuery API

3. has()

指定したセレクタの要素がるかどうかを調べます。セレクタが存在したら元のjQueryオブジェクトを返します。

以下のようにした場合、#fooの子要素にli.barがあった場合#fooにbazというclassが追加されます。li.barにつくのではないというのがポイントです。

$('#foo').has('li.bar').addClass('baz');

.has() – jQuery API

4. unwrap()

親要素を削除します。wrap()の反対ですね。

$('#foo').unwrap();

.unwrap() – jQuery API

5. detach()

要素を削除します。remove()と同じような感じですが、remove()と違うのはイベントや$.dataは残るということです。

以下の例ではdetach()を使っているので、DOM要素は削除されますが、detachする前に設定したイベントや$.dataにデータは残っています。

var $div = $('#foo');
var div = $div.get(0);

$div.click(function() { alert('foo') });
$.data(div, 'foo', 'bar');

$div.detach();
$('#hoge').append($div); // => 再度追加してもクリックイベントは残ってる
console.log( $.data(div, 'foo') ); // => bar

.detach() – jQuery API

6. focusin()、focusout()

focusin、focusoutというイベントが新規で追加されています。基本的には以前のfocusとblurと同じようなものですが、focus、blurと違うところは指定した要素だけでなく、子要素にもイベントが適用されるというところのようです。

<div id="foo">
    <input type="text" />
    <input type="text" />
</div>

$('#foo')
    .focusin(function() {
        // focus時の処理
    })
    .focusout(function() {
        // focusout時の処理
    });

7. first()、last()

first()は最初の要素、last()は最後の要素を返します。セレクタの指定で:first-child、:last-childとつけるのと同等ですね。

<ul id="foo">
    <li id="item1">list1</li>
    <li id="item2">list2</li>
    <li id="item3">list3</li>
    <li id="item4">list4</li>
    <li id="item5">list5</li>
</ul>

console.log( $('#foo li').first().attr('id') ); // => item1
console.log( $('#foo li').last().attr('id') );  // => item5

8. toArray()

jQueryオブジェクトを配列にして返します。get()と等価で、get()を引数なしで呼ぶと内部ではtoArray()が呼ばれているようです。get()よりもこっちのほうが直感的でいいですね。

<ul id="foo">
    <li id="item1">list1</li>
    <li id="item2">list2</li>
    <li id="item3">list3</li>
    <li id="item4">list4</li>
    <li id="item5">list5</li>
</ul>

console.log( $('#foo li').toArray() ); // =>  [li#item1, li#item2, li#item3, li#item4, li#item5]

.toArray() – jQuery API

9. $.proxy()

例えば以下の様なコードがあったときに、click時に呼ばれるclickHandlerメソッドのthis.nameのthisは#fooになってしまうので、this.nameはundefinedになっていしまいます。

var app = {
    name: 'app name',
    clickHandler: function() {
        alert( this.name + ' clicked.' );
    }
};

$('#foo').click(app.clickHandler);

そこで$.proxyを使って以下のように書くととclickHandlerメソッドのthisをappとして扱うことができます。

$('#foo').click( $.proxy(app, 'clickHandler') );

もしくは

$('#foo').click( $.proxy(app.clickHandler, app) );

のどちらでも同じように動作します。

jQuery.proxy() – jQuery API

10. $.isEmptyObject()、$.isPlainObject()

空のオブジェクトか判定するメソッドとオブジェクトかどうかを判定するメソッドが追加されています。挙動は以下のようになるようです。

$.isEmptyObject({});          //=> true
$.isEmptyObject([]);          //=> true
$.isEmptyObject('');          //=> true
$.isEmptyObject(0);           //=> true
$.isEmptyObject(null);        //=> true
$.isEmptyObject(undefined);   //=> true
$.isEmptyObject('foo');       //=> false
$.isEmptyObject({foo:'bar'}); //=> false
$.isEmptyObject(new Object);  //=> true

$.isPlainObject({});          //=> true
$.isPlainObject([]);          //=> false
$.isPlainObject('');          //=> false
$.isPlainObject(0);           //=> false
$.isPlainObject(null);        //=> false
$.isPlainObject(undefined);   //=> false
$.isPlainObject('foo');       //=> false
$.isPlainObject({foo:'bar'}); //=> true
$.isPlainObject(new Object);  //=> true

新しい使い方ができるようになったメソッド

11. bind()で複数イベントをまとめて指定

bind()にオブジェクトを指定することで複数のイベントをbindできるようになっています。

$('#foo').bind({
    click: function() {
        // click event
    },
    mouseover: function() {
        // mouseover event
    },
    mouseout: function() {
        // mouseout event
    }
});

.bind() – jQuery API

12. animate()でプロパティ毎にeasing

animate()のeasingが以下の様にプロパティ毎に設定できるようになっています。これで複雑なアニメーションがより簡単に定義できそうですね。

$('#foo').animate({
   left: 500,
   top: [500, 'linear']
}, 1000);

.animate() – jQuery API

13. live()が全イベントに対応

以前までのバージョンのlive()はsubmitやfocusなど、対応してないないイベントもありましたが、今回全てのイベントに対応したようです。ただしfocus、blurはfocusin、focusoutを指定する必要があります。

$('.input-text').live('focusin', function() {
    // focus時のイベント
});

.live() – jQuery API

14. append()やcss()にfunctionを指定

append()などのDOM操作系のメソッド全般にfunctionが指定できるようになっています。これでどういうことができるようになったかというと、以下のようにthisで自分の要素を取れたり

$('#foo').append(function() {
    return $(this).hasClass('hoge') ? 'hoge' : 'fuga';
});

引数にインデックスと値をとるので、以下のような処理も書けけるようになっています。

$('#foo li').css('color', function(i, val) {
    return i % 2 ? 'red' : 'blue';  
});

以上です。新しい機能だけでなく1.4では速度も劇的に速くなっているようなのでぜひ使ってみるといいと思います。

kayacでは新しいものにすぐに飛びつくミーハーなプログラマも募集しています!

2010-01-22

最近ロフトで買った立体型のアイマスクが個人的にヒットでした。agoです。

今日はgoogle map api+IE6で「未知の実行時エラーです。」が出る場合の対応をご紹介したいと思います。

まず、IE6の場合、一部の要素のinnerHTMLが書き換え不可になっており、他のブラウザと同じようにinnerHTMLで内容を書き換えられない場合があります。

私が遭遇した状況では<p>に追加しようとしたためエラーになっていたのですが、他にもhtmlの文法上<div>を追加できない要素に対してnew GMap2を行うのは問題となるかもしれません。

他の状況であれば問題となる箇所の切り分けも楽なのですが、後々また「google map api "未知の実行時エラーです"」的な検索をしそうなのでエントリにしてみました。

カヤックではアイマスクにこだわりを持つ技術者も募集しています!

2009-12-22

週末料理をしていて足を切ってしまいました。agoです。

以前Perlは書いていたんですが、その頃以下の記事を読んで非常に感銘を受けました。

Perlプログラマのレベル10 - Perlプログラミング救命病棟より - naoyaのはてなダイアリー

当時あまりコミュニティとのつきあいがなかったので、「自分のスキルの絶対位置」、「次のレベルへ行くために必要なもの」を知ることで非常に安心感を感じた記憶があります。

いま確認したところ、「JavaScriptプログラマのレベル10」はないようなので書いてみました。


レベル0 : JavaScriptがプログラミング言語だと言うことは知っているが、JavaとJavaScriptの区別が付かない。
(Webプログラマの自己紹介を聞いて)「Javaやってるんだ?」

レベル1 : 「JS」がJavaScriptの略称であることを知っている。JavaScriptはWeb Siteを作成するための言語と理解しており、alertやチカチカしたものはJavaScriptで作られたと思っている。自分でコードを記述することは出来ないが、Dreamweaver等が埋め込んだコードを壊すことなくhtmlを編集することが出来る。
(何度も出るalertを見て)「またJavaScriptか!」

レベル2 : 広く公開されているライブラリを自分のサイトへ組み込むことが出来る。各ライブラリには相性があることを理解しており、あるライブラリとあるライブラリが衝突することは知っているがどういう条件で衝突するかは知らない。ライブラリの呼び出し部分に関してサンプルコードを修正し、自分のサイトに合わせたid、class名に変更することが出来る。
「カチカチカチ」(「xxするためのライブラリまとめ100」とかをブックマークしている)

レベル3 : 変数、条件分岐、ループを理解しており、簡単なコードであれば0から記述することが出来る。デザインとロジックの分離は出来ないが、ブラウザのuser agentで切り分けることでクロスブラウザのコードを記述することが出来る。公開されているライブラリに埋め込まれているhtml部分を好きな形へ書き換えることが出来る。
(次の仕事の仕様説明を聞いて)「そこもJavaScriptつかうんですか!?」

レベル4 : 自作のライブラリ群に限界を感じ、jQuery、Prototype.js等に手を出す。簡単なアニメーションを行うことが出来、デザインとロジックの分離を行うことができる。firebugがないとデバッグする気が起きない。GreaseMonkey等のUserScriptを作成し、既存のサイトを修正する事が出来る。
(ユーザから「動かない」と呼ばれて)「ごめん。まずfirebug入れていい?」

レベル5 : 正規表現、再帰、無名関数を使いこなせる。jQuery、Prototype.js等の普段使用しているライブラリに沿った記述が可能になる。.prototypeを使用して既存のオブジェクトを拡張することが出来る。コードを記述するときに速度をきにしだす。普段からlocal proxyが起動している。
(IEだけ非常に遅いのを見て)「IE爆発しろ!」

レベル6 : this, .apply, instanceOf等の効果を他人に説明することが出来る。各種外部APIを連動させてJavaScript単体では出来なかったことを実現する。JavaScriptではサポートされていない機能を実装するためにJavaScriptから呼び出されるだけのswfを作成したことがある。速度的な問題から各要素に直接イベントを設定するのではなく、上位要素にイベントを設定し独自のディスパッチャでイベントの処理を行う。
(Yahoo! pipesを使って)「Yahoo! いいじゃん!」

レベル7 : 各ブラウザが独自実装している機能に関して、共通部分を抜き出してライブラリ化する。HTML5を試してみる。profileでいくつかのコードをテストし、一番早いものを採用する。速度的な問題から、あえてライブラリを使用しない。
(できあがったコードを見て)「半分がIE対策か。。。」

レベル8 : JavaScriptでDSLを作成する。ブラウザのextensionを作成し、addons.mozilla.org等で公開する。広く公開されているライブラリに限界を感じ自作することを思い立つ。カンファレンス、勉強会等でLightning Talkを行う。
(Lightning Talkにて)「どうもxxのnnです」

レベル9 : サーバサイドJavaScriptに手を出す。カンファレンスにスピーカーとして呼ばれる。JavaScriptの仕様に限界を感じ、仕様を変更できないか考える。作ったライブラリが広く使われるようになるが、本人のやる気がついてこらず放置気味になる。
(自作ライブラリへの問い合わせに対して)「次のバージョンでは修正予定です!(いつ出るかわからないけど)」

レベル10 : JavaScriptの実装を開発している。次世代のECMAScriptに関しての提言が受け入れられる。自作したライブラリがOSやブラウザ等の実行環境に標準で取り入れられる。JavaScriptに関する書籍を出版し、コミュニティから「バイブル」と呼ばれ読書会が開かれる。
(始めてあった人から)「もしかしてnnさんじゃないですか?はじめまして!いつもお世話になっています!」


各レベル内容はどれか一つでも当てはまればクリアと想定しています。

ただ、内容はかなり偏っていると思うので、皆さん独自の「レベル10」を作ってみてください。

カヤックではすごいエンジニアを募集しています