EC2上でLVMによるディスクの統合
Amazon EC2で、Instance StoreタイプのLarge Instanceにした場合、使えるディスクの容量は、850GBとなっている。
だけど、dfのコマンド叩いてみても、/ と /mnt 合わせても、420GB程度にしか見えない。
どういうことかと、さんざん調べた結果、/mnt にマウントされてる、/dev/sdb の他に、/dev/sdc ってのがあって、
それを、適当なとこにマウントすれば、合わせて、820GBになるとのこと。
確かに、合計サイズとしては、850GBなんだけど、どうしても420GB×2じゃ、都合が悪かった。
そこで、2つのディスクを1つのディスクに見せかけて何とか、デカイ容量にしようと企んだ。
LVM2を使ってやったので、以下は、その作業ログ。
環境は、Ubuntu 10 Server(x86_64)。
- まずは、LVMをインストール
$ sudo apt-get install lvm2
- モジュールのロード
$ sudo modprobe dm-mod
- 物理ボリューム(PV)の作成
$ sudo pvcreate /dev/sdb Can't open /dev/sdb exclusively. Mounted filesystem? #マウントされんじゃねーの?って怒られた # マウント解除 $ sudo umount /mnt # 改めて、/dev/sdb と /dev/sdc のPV作成 $ sudo pvcreate /dev/sdb Physical volume "/dev/sdb" successfully created $ sudo pvcreate /dev/sdc Physical volume "/dev/sdc" successfully created # 確認 $ sudo pvscan PV /dev/sdb lvm2 [419.97 GiB] PV /dev/sdc lvm2 [419.97 GiB] Total: 2 [839.93 GiB] / in use: 0 [0 ] / in no VG: 2 [839.93 GiB]
- ボリュームグループ(VG)の作成
# vkvsって名前で、/dev/sdv と /dev/sdc でグループ作成 $ sudo vgcreate vkvs /dev/sdb /dev/sdc Volume group "vkvs" successfully created # 確認 $ sudo vgs VG #PV #LV #SN Attr VSize VFree vkvs 2 0 0 wz--n- 839.93g 839.93g
- 論理ボリューム(LV)の作成
# lkvsって名前で、LV作成(サイズは、適当に) $ sudo lvcreate -L 835G -n lkvs vkvs Logical volume "lkvs" created # 確認 $ sudo lvscan ACTIVE '/dev/vkvs/lkvs' [835.00 GiB] inherit
$ sudo mkfs.ext3 -j /dev/vkvs/lkvs
- さて、いよいよマウントしてみる
$ sudo mount /dev/vkvs/lkvs /mnt $ df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 9.9G 1.4G 8.0G 15% / 〜〜略〜〜 /dev/mapper/vkvs-lkvs 822G 201M 780G 1% /mnt
よし。成功だー!
あとは、残作業。
- fstab に書き込んで、次回起動時からマウントされるように設定
$ cp /etc/fstab /etc/fstab.old $ emacs /etc/fstab # /etc/fstab: static file system information. # <file system> <mount point> <type> <options> <dump> <pass> proc /proc proc nodev,noexec,nosuid 0 0 /dev/sda1 / ext3 defaults 0 0 /dev/vkvs/lkvs /mnt auto defaults 1 2 # <= 追記
- module を起動時に、loadされるように設定
$ sudo emacs /etc/modules # /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. # LP: #450463 acpiphp dm-mod # <= 追記
- 再起動してみる
$ sudo reboot $ df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 9.9G 1.4G 8.0G 15% / 〜〜略〜〜 /dev/mapper/vkvs-lkvs 822G 201M 780G 1% /mnt
やった。これで、次回起動時から(AMI作ってたら?Rebootしても?)850GBに近い容量のディスクをマウントした状態で使えるぞ!
第3回 HTML5+α勉強会@福岡
今回も始まりましたHTML5。
いやー、1月って忙しいですよね。そんな言い訳からはじめました。
みなさん、ごめんなさい。。予定してた内容の半分でのLTでしたが、
Web Socketsには、多くのニーズや興味があり、途中でサーバー側の
デバッグしている間にも、多くの議論が行きかってました。
結果的には、良いセッションになった!?(笑)
そんなこんなで、調査不足なんぞもありましたが、参加者の皆さん、ありがとうございました。
次回は、他の方の会話も含めて、もっとプロトコル寄りな議論ができそうです。
ただし、次回は、マークアップ側の勉強会の予定ですので、その辺はLTにて。
第2回 HTML5+α勉強会@福岡
参加してきました。
今回は、メインでやらせてもらいましたが、直前までデモ作ってたりしました・・
そのせいで、LTを先にやってもらうなど、皆さんには、感謝の至り。
id:re_shikajiro さん、id:kimpo さん、ありがとうございました。
そんなこんなで、調査不足なんぞもありましたが、参加者の皆さん、ありがとうございました。
まだ先かもしれないけど、クラウド技術の発展によって、オフラインアプリケーションの重要性は増してくると思ってます。
MA5とクロスドメイン
http://mashupaward.jp/に作品応募しました。
1.5ヶ月程前のHTML5@福岡の勉強会の懇親会の中で、MA5参加しようって話になって、実装し始めたのが、応募の締め切り2日前・・(なにかと思うけど、追い詰められるまでやらないの何とかしなきゃw)
結局、そんなこんなで、想定したものは、作れず妥協しまくった結果、なんか普通のWebアプリになっちゃいましたが、なんとか応募締め切り4分前に応募が完了できました。
でも、『参加したことに意義がある』と勝手に思ってます。(次回こそ)
さてさて、そんな中で、各種APIを使うのがMashupですが、Flex+APIで実装したこともあり、Flashのセキュリティエラーに幾度となくAPIが利用できない場面に遭遇しました。
それは、使いたいAPIのドメインに"crossdomain.xml"が設置されていなかったり、APIのドメイン自体には設置されてるけど、レスポンスで返ってきた値の中の画像のURL先ドメインには、設置されてなかったりと、実装中、一番苦しみました。
また、出来たアプリケーション(swfファイル)をサーバーにデプロイすると、ローカル環境では、OKだけど、NGだったりと。。
前置きが長くなりましたが、サーバーにFlexアプリケーションをデプロイする際には、以下のようにFlex側のコードには、"crossdomain.xml"のURLを指定して読み込ませるのが、楽チンのようです。(というか指定しなくてもいけるか分かんないけど)
Security.loadPolicyFile("http://ドメイン名/どこか/crossdomain.xml");
この一番のメリットは、"corssdomain.xml"の設置箇所が、ドメイン名の直下でない場合です。
実際の"crossdomain.xml"のある場所を指定できるのです。
いつかどこかで困った際には、思い出してください(笑)
Flex開発では、UI設計に気をつけて!
拝啓、Flexを始めて採用しようとしているWebアプリケーション開発者の方々へ。
ActionScriptが、他の言語と違う点として、後付で、UI系の言語実装を追加したのではなく、UI系ありきで、設計された言語といわれています。
そして、これを実感したのは、Flexを始めて採用したプロジェクトをやったときの話・・
画面設計時に、ButtonやCanvasなんかの配置としての画面構成は、概ね決まっていました。
ですが、コンポーネントの階層までは、意識しておらず、つまりは、平面1枚の画面構成だけが、決まっている形でした。
そして、イベントを拾うコンポーネントは、どの階層のコンポーネントで、やるかは深く考えずに、対象コンポーネントに登録して、実装していった結果。。。
といった具合に、メンテナンス性が抜群に悪いモノが出来てしまったのでした。
(加えていうなら、View部分以外にも、問題はあったんだけど、それはまた別のお話)
では、次に、以下のサンプルコードを試してみてください。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" layout="absolute"> <mx:Script> <![CDATA[ import mx.controls.Alert; private function init():void { exeButton.addEventListener(MouseEvent.CLICK, buttonClick); msgLabel.addEventListener(MouseEvent.CLICK, labelClick); mainCanvas.addEventListener(MouseEvent.CLICK, canvasClick); mainPanel.addEventListener(MouseEvent.CLICK, panelClick); } private function buttonClick(event:MouseEvent):void { Alert.show("button"); } private function labelClick(event:MouseEvent):void { Alert.show("label"); } private function canvasClick(event:MouseEvent):void { Alert.show("canvas"); } private function panelClick(event:MouseEvent):void { Alert.show("panel"); } ]]> </mx:Script> <mx:Panel id="mainPanel" title="『ここはパネル』" width="100%" height="100%" layout="absolute"> <mx:Canvas id="mainCanvas" width="80%" height="80%"> <mx:VBox height="20%" borderColor="blue" borderThickness="2"> <mx:Label text="階層構造は以下の通り" /> <mx:Label text="<panel ⇒ canvas ⇒ label ⇒ button>" /> <mx:Spacer height="100%" /> <mx:Label id="msgLabel" text="『ここはラベル』" /> <mx:Button id="exeButton" label="ボタン"/> </mx:VBox> </mx:Canvas> </mx:Panel> </mx:Application>
Flexというか、ActionScript3では、イベントを発生させると、最上層のコンポーネントであるstageから順に最下層にあるコンポーネントまで、全てイベントを通知し、最下層に到達したら、さらに逆の順を辿って、最上層のstageまで通知が返っていく仕組みになっています。(上記のサンプルコードは、それが少し体感できるものじゃないかと思います)
では、想像してみてください。仕様上、このサンプルコードで書かれたコンポーネントの全てに、マウスのクリックイベントが必要だった時のことを。。
あなたなら、どうやって、それぞれのコンポーネントでクリックイベントを拾って実装しますか?w
と、何か、変な話になってしまいましたが、私の経験からは、少なくとも以下の点を考慮した設計をやった方がよい気がします。
この辺、Webディレクターの方々には、当然のことなんでしょうけど、Webアプリケーション開発者の視点から伝えたかったのは、Flex(RIA)開発の際には『UI設計は、しっかりやろう』ということです。
FlexでViewStackの子コンポーネントのインスタンス生成のタイミング
Flexで「ViewStack」を使って子コンポーネントを複数の画面として、切り替える場合には、その子コンポーネントの、creationCompleteを利用して、対象となる子コンポーネントを参照するのが、理想的です。(というか、そうでないと、インスタンス生成のタイミングがわかんないし。。)
で、creationCompleteを利用して、参照できない場合、子コンポーネントの「callLater」で対象のFunctionを呼び出したりするっていう手も、あるけれど、毎度、callLaterで参照するわけにも行かないので、ViewStackに、creationPolicyの属性を設定してあげよう。
<mx:ViewStack creationPolicy="all" >
Flex + Ruby (on Rails) でAMF通信とHTTP通信
クライアント側をFlexにし、サーバーをRailsで作成した通信に、
AMF通信とHTTP通信をそれぞれやってみました。
- Railsプロジェクトを作成
Project Name : FlexServer
Use Database : sqlite3
rails FlexServer -d sqlite3
Rails Plugin : rubyAMF
ruby script/plugin install http://rubyamf.googlecode.com/svn/tags/current/rubyamf
- rubyamf_config.rb の編集
> config/rubyamf_config.rb
ClassMappings.translate_case = true ClassMappings.assume_types = true
- 確認
サーバー起動
ruby script/server
- rubyAMFのgatewayへアクセス
http://localhost:3001/rubyamf/gateway
- user の Controller/Model/View を生成
scaffold(rubyamf_scaffold もあるけど、今回は、利用せず)
ruby script/generate scaffold user
- migration ファイルを修正
> db/migrate/xxxxxx_create_users.rb
def self.up create_table :users do |t| t.string :firstName t.string :lastName t.string :nickName t.integer :age, :limit => 3 t.string :email, :default => 'anonymouse@gmail.com' ・・・・
- DBとテーブルを生成
rake db:create rake db:migrate
- UsersControllerの編集
> app/controllers/users_controller.rb
def index @users = User.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @users } format.amf { render :amf => @users } end end
- mimeTypeの設定と修正
split ってメソッド を to_s に委譲(delegate)します(通信時エラーになるので)
> config/initializers/mime_types.rb
Mime::Type.register "application/x-amf", :amf Mime::Type.delegate :split, :to => :to_s
- crossdomain.xmlの設定
セキュリティエラーでるので。。
> public/crossdomain.xml
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <site-control permitted-cross-domain-policies="all" /> <allow-access-from domain="*" /> </cross-domain-policy>
- UserList.mxmlの実装
最後に、FlexのMXMLの実装
> src/UserList.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" layout="absolute"> <mx:Script> <![CDATA[ import mx.rpc.http.HTTPService; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; private var amfFormat:Boolean; private function init():void { getAmfButton.addEventListener(MouseEvent.CLICK, getListForAmf); getHttpButton.addEventListener(MouseEvent.CLICK, getListForHttp); } // AMF通信 private function getListForAmf(event:MouseEvent):void { this.amfFormat = true; var request:RemoteObject = this.userService; request.index(); request.addEventListener(ResultEvent.RESULT, onResult); request.addEventListener(FaultEvent.FAULT, onFault); } // Web通信 private function getListForHttp(event:MouseEvent):void { this.amfFormat = false; var request:HTTPService = new HTTPService(); request.url = "http://localhost:3001/users.xml"; request.resultFormat = HTTPService.RESULT_FORMAT_E4X; request.send(); request.addEventListener(ResultEvent.RESULT, resultHandler); request.addEventListener(FaultEvent.FAULT, faultHandler); } private function resultHandler(event:ResultEvent):void { trace("onResult : " + event.result); if (amfFormat) { userList.dataProvider = event.result; msgLabel.text = event.result.toString(); } else { userList.dataProvider = event.result.user; msgLabel.text = event.result.user.toString(); } } private function faultHandler(event:FaultEvent):void { trace("onFault : " + event.fault); msgLabel.text = event.fault.faultString; } ]]> </mx:Script> <mx:RemoteObject id="userService" destination="rubyamf" endpoint="http://localhost:3001/rubyamf_gateway/" source="UsersController" /> <mx:VBox width="100%"> <mx:DataGrid id="userList" width="100%"> <mx:columns> <mx:DataGridColumn dataField="id" headerText="ID"></mx:DataGridColumn> <mx:DataGridColumn dataField="firstName" headerText="FirstName"></mx:DataGridColumn> <mx:DataGridColumn dataField="lastName" headerText="LastName"></mx:DataGridColumn> <mx:DataGridColumn dataField="age" headerText="Age"></mx:DataGridColumn> <mx:DataGridColumn dataField="nickName" headerText="NickName"></mx:DataGridColumn> <mx:DataGridColumn dataField="mail" headerText="Mail"></mx:DataGridColumn> </mx:columns> </mx:DataGrid> <mx:Button id="getAmfButton" label="Get for Amf" /> <mx:Button id="getHttpButton" label="Get for Http" /> <mx:Label id="msgLabel" /> </mx:VBox> </mx:Application>
Rails側のformatに対応したボタンをそれぞれ準備しました。
Rails側の
format.amf { render :amf => @users }
が、Flexの「Get for Amf」のボタンに対応し、
format.xml { render :xml => @users }
が、Flexの「Get for Http」のボタンに対応してます。
- 実行
データを多く準備して、レスポンスを計測してみると、どちらが早いか検証できると思います。
やって見た方は、是非、レスポンスタイムとか教えて欲しいっす。