2012/05/08

さくらVPS 新プランへの移行


先日(といっても結構日が経ってしまいましたが)、さくらVPS に「絶対お得な新プラン」が登場しましたね。



開始当初は申し込みが殺到し、一次申込み停止になりましたが現在は安定しているようです。


というわけで、旧プラン の 「さくらのVPS 512」を、同じ金額でグレードアップした「さくらのVPS 1G」に移行してみました。


新プランでは CentOS 6 がインストールされています。新OSも気になりますが、ひとまずココは旧プランの CentOS 5 の環境をそのまま移行することにしました。


作業の流れ


作業の流れは大体下記のような感じになります。


  1. DNS の TTL を変更
  2. OS再インストール
  3. データ転送
  4. 調整
  5. 動作確認
  6. 再データ転送
  7. DNS の A レコード を変更
  8. 後始末


前提条件・事前準備


ここで紹介する方法は、まるごと移行してしまう方法ですので、下記の前提条件と、事前準備を実施します。


前提条件


  • 両サーバとも同じOS及びバージョンで行うこと(ここでは CentOS 5)

事前準備 作業時間:15分程度


DNS の TTL を変更


サーバ切り替えが即座に反映されるようにするため、DNS の TTL を短め(60など)に設定しておきます。

この DNS の設定変更タイミングは、現在設定されている TTL を目安に考えます。

例えば、現在の TTL が 3600 だとすると、3600秒前(1時間前)までに DNS の変更をしておくのが望ましいです。


OS再インストール


両サーバとも同じOS及びバージョンで行うことが条件なので、まずは VPS コントロールパネル から OS再インストール を実施します。

カスタムOSインストール から、 CentOS 5 x86_64 を選択して OS 再インストールを実行します。


カスタムOSインストール は、ブラウザの Java アプレット上から手動で実施します。公式サポートマニュアルを参考に進めてください。


なお、カスタムOSインストール実行中に表示される、ホスト名やIPアドレスなどが記載された画面は、後ほどまで確認するので閉じないようにします。念のためメモ帳などにコピペしておくのがいいです。


カスタムOSインストールガイド|さくらのVPS|さくらインターネット公式サポートサイト


再インストールが完了したら、VPS ホームよりサーバを起動しておきます。


移行作業


データ転送 作業時間:約1G の転送で30分程度


サーバの再インストールが完了したら、いよいよデータの移行です。

データの移行は、旧サーバ の root ユーザから下記のコマンドで一括転送します。

[new_server_ip] は新サーバの IP アドレスに置き換えてください



# rsync -rtlzvogpHAX --exclude /boot/ --exclude /dev/ --exclude /proc/ --exclude /sys/ --exclude /var/run/ --exclude /var/lock/ --exclude ifcfg* --exclude ssh_host_* --exclude fstab --block-size=4096 -e ssh / new_server_ip:/

コマンドの意味やオプションなどについては、下記を参考にしてください。


オプション
動作内容
-r
ディレクトリ内容を再帰的にコピーします
-t
更新日時を保持します
-l
ソフトリンクを保持します
-z
転送時に圧縮します
-v
処理状況を表示します
-o
所有者を保持します
-g
グループを保持します
-p
パーミッションを保持します
-H
ハードリンクを保持します
-A
ACLを保持します
-X
拡張パーミッションを保持します
--exclude
除外するファイルの名前を指定します
--block-size=
チェックサムをとる際のブロックサイズを指定します
-e ssh
ssh経由でコピーします

転送が完了したら、VPS コントロールパネルよりサーバを再起動します。


新サーバのネットワーク設定 作業時間:5分程度


GATEWAY の追記


再起動後、SSH で接続できない場合は、VPS コントロールパネルの リモートコンソール から下記のようにネットワークの設定を修正します。

GATEWAY の設定を追記します。

[GATEWAY=***.***.***.***] は新サーバの ゲートウェイ アドレスに置き換えてください


/etc/sysconfig/network-scripts/ifcfg-eth0

# vi /etc/sysconfig/network-scripts/ifcfg-eth0

# Intel Corporation 82540EM Gigabit Ethernet Controller
DEVICE=eth0
BOOTPROTO=static
DHCPCLASS=
HWADDR=**:**:**:**:**:**
IPADDR=***.***.***.***
NETMASK=255.255.254.0
ONBOOT=yes
GATEWAY=***.***.***.***

# /etc/init.d/network restart

SSH の許可


旧サーバの SSH の設定は、外部からの接続は 鍵認証のみ root ログイン不可 になっているので、一時的にこれを変更します。


/etc/ssh/sshd_config

#vi /etc/ssh/sshd_config

PermitRootLogin yes
PasswordAuthentication yes


/etc/hosts.allow


/etc/hosts.allow, deny で接続制限をしている場合は、こちらも旧サーバを許可する。


/etc/hosts.allow

# vi /etc/hosts.allow

sshd: 旧サーバのIPアドレス

IP アドレスに依存する設定の修正 作業時間:それぞれ


ネットワークの設定が完了したら、IP アドレスに依存する設定などを修正していきます。

旧サーバのユーザ情報などそのまま移行しているので、SSH クライアント の設定も IP アドレスの変更だけで OK でした。


  • NameVirtualHost での Apache 設定
  • MySQL の pid 置場

バックアップ無し

$ sudo find /etc/httpd/conf.d -type f -name '*.conf' | xargs sudo perl -i -pe 's/xxx\.xxx\.xxx\.xxx/xxx\.xxx\.xxx\.xxx/g'
$ sudo find /var/www/vhosts -type f -name '*.conf' | xargs sudo perl -i -pe 's/xxx\.xxx\.xxx\.xxx/xxx\.xxx\.xxx\.xxx/g'

バックアップをとっておく場合(*.bak というバックアップファイルが作成されます)

$ sudo find /etc/httpd/conf.d -type f -name '*.conf' | xargs sudo perl -i.bak -pe 's/xxx\.xxx\.xxx\.xxx/xxx\.xxx\.xxx\.xxx/g'
$ sudo find /var/www/vhosts -type f -name '*.conf' | xargs sudo perl -i.bak -pe 's/xxx\.xxx\.xxx\.xxx/xxx\.xxx\.xxx\.xxx/g'

/var/run 以下は転送から除外しているので、/var/rub/mysqld を作成しておく

$ sudo mkdir /var/run/mysqld
$ sudo chgrp mysql /var/run/mysqld/
$ sudo chmod g+w /var/run/mysqld/
$ sudo /etc/rc.d/init.d/mysqld start

動作確認


ここまでで既に殆どの環境が移行できているはずなので、自分のマシンの hosts を設定して動作を確認してみます。

なお、 hosts ファイルは管理者権限で起動したメモ帳などで編集します。

スタートメニュー > 全てのプログラム > アクセサリ > メモ帳 から右クリックで管理者として実行。その後メニューの開くからファイルを開きます。

C:\Windows\System32\drivers\etc\hosts

新サーバIPアドレス   ドメイン名
xxx.xxx.xxx.xxx   www.test.com

再度データ転送


確認作業をしている間などの差分ファイルを転送します。

転送中にファイルが変更されないように、旧サーバの主要なサービスは予め停止しておきます。


サービスを停止している間は、外部からの閲覧もダウンしている状態になります。


コマンドは最初の転送と同じですが、旧サーバで SSH のポートを変更している場合はポートの指定を入れます。

# /etc/init.d/httpd stop
# /etc/init.d/mysqld stop

# rsync -rtlzvogpHAX --exclude /boot/ --exclude /dev/ --exclude /proc/ --exclude /sys/ --exclude /var/run/ --exclude /var/lock/ --exclude ifcfg* --exclude ssh_host_* --exclude fstab --block-size=4096 -e ssh / new_server_ip:/

ポートを指定する場合
# rsync -rtlzvogpHAX --exclude /boot/ --exclude /dev/ --exclude /proc/ --exclude /sys/ --exclude /var/run/ --exclude /var/lock/ --exclude ifcfg* --exclude ssh_host_* --exclude fstab --block-size=4096 -e "ssh -p 10022" / new_server_ip:/

IP アドレスに依存する設定の修正


転送で修正ファイルが上書きされてますので、上記の設定を再度実施します。



DNS の A レコードを変更


いよいよです。

DNS の A レコードを変更することで、外部からの接続が新サーバに振られることになります。

各ネームサービスの指示に従って変更してください。

TTL の設定を変更した場合は、ついでに戻しておきましょう。


移行後


SSH の設定などを元に戻す


SSH の設定など、一時的に許可した設定を元に戻すのを忘れずに。


お疲れ様でした!


これで無事に移行が終わったかと思います。お疲れ様でした。

さくらのVPS 新プラン乗り換え優遇施策 は、2012年5月20日(日)までなので、まだ申し込みしていない方はお早めに!




参考サイト:

2011/11/04

#gdd11jp Google Developer Day


11月1日、パシフィコ横浜で Google Developer Day 2011 が開催されました。


毎年参加させていただいており、今年もなんとか参加してきました。


サプライズ


結果的にはとても楽しかった GDD。セッションに迷うのは毎度のことですが、今年は色々「しかけ」が用意されており、楽しめるイベントになっていました。

ただ、恒例?のサプライズ発表は特になかったので、ちょっと残念。


全体を通して、やっぱり HTML5(Chrome) と Android(Ice Cream Sandwich) に力入ってましたね。


今回参加したセッションは次の通り。


  • Android の最新情報
  • Google+ Hangout アプリを作ろう
  • 今までにないサイトを作る:HTML5 による最新ウェブアプリ
  • Google Apps : 新しい API、新機能、ベストプラクティス
  • Google のエンジニアの日常
  • イグナイト ( ライトニングトーク )

改めて見ると、新サービス関連に偏ってます。

セッションの内容も、サービスの説明から入る分、あまりコアな情報はありませんでした。

既存サービスのセッションのほうが割りと濃い内容だったみたいです。


Android の最新情報


気になる Android 4.0 。Android 4.0 からは、テレビ、タブレット、スマートフォンなど、すべてのデバイスをカバーする。

なので、デザインはより慎重に行う必要がある。画面サイズの管理も。

ソーシャルもより重要に。Google + が前面に出ています。インテントを利用した設計がおすすめ。

思った以上に、NFC の Android Beam は面白いですね。今開いているWebページが、相手の端末にも表示されるデモは素晴らしかったです。

それと、Wifi Direct ってのも気になります。端末同士がダイレクトにネットワークでつながるということで、面白い使い方ができそうですね。


Google+ Hangout アプリを作ろう


違うセッションを予定していたけど、基調講演で Hangout が気になったので続きを聞いてみた。


基本的に、iFrame のガジェットで構築。ビデオカンファレンスのようなものを手軽に構築できそう。

デモは、チャットルームのような Hangout で、招待された人とビデオチャットしながら、参加者のロボットアバターがアプリ内で動く。というもの。

データはひとつの Shared データなので、参加者全員にリアルタイムで更新される。

面白そうだけど、どんな使い道があるか?今後に期待です。


今までにないサイトを作る:HTML5 による最新ウェブアプリ


HTML5 のフルスペックである Chrome ならこんなことまでできる!という内容でした。

これからのWebアプリは、ビジュアルも重要だと。

HistoryAPI でシングルページだけど、URLが変わってブラウザの戻るも使える。GitHub みたいなページ遷移。たしかにコレ重要ですね。

FilesystemAPI では、ネイティブとの連携でファイルのドラッグドロップなど、ネイティブファイルを操作できる。

古いブラウザには、PolyfillsChrome Frame を使うのがいいみたい。


ライブラリは、lawnchair , Boilerplate , Modernizr を使うといい。


これらが ブラウザ標準で利用できるのが素晴らしいですね。(まだまだ対応していないブラウザも多いですが)


Google Apps : 新しい API、新機能、ベストプラクティス


DevQuiz での Apps Script が面白かったのでもう少し詳細を期待していましたが、やっぱり、そもそも Apps Script は知名度が低く、触り程度の紹介でした。

しかし、UI Builder や PickerAPI などビジュアル的にも Google UI と統一されたものが揃ってきて、かなり使えるという印象でした。

マーケットプレイスでの公開も拡充してきており、Apps Script は今後本気で勉強したほうがよさそうです。

Google Data API については、これまでの複雑なものをシンプルにすべく [HTTPS] [OAuth2] [JSON] で統一とのこと。これは嬉しいですね。

API の確認には、Google APIs Explorer が便利。


Google のエンジニアの日常


あの有名な yugui さんが登場とのことで、観てきました。

オープンソースな人から見た Google というのは面白かった。

オープンソースの世界では当たり前の光景が、Google という巨大な組織でも適用されているのがすごいと。

エンジニア主導、ドキュメント、コードレビュー、ひとつのリポジトリなどは、初めての GDD に聞いた時と変わっていないようで、その徹底ぶりが Google の強みだと改めて感じました。


イグナイト ( ライトニングトーク )



最後のセッションは、おなじみ?Google スタッフによるダンス!合計30時間も練習したんだとか。みなさん、お上手でした。

Chrome の WebAudio と Node.js のデモはすごかったですね。基調講演でも WebAudio が紹介されていて、Javascript と HTML5 で音まで操作できるみたい。昔の MIDI を奏でるサイトをパワーアップできそうです。



初めにもらった、3Dメガネ。結局自分は使わなかったけど、どうやら Youtube が 3D に対応した動画があるようで、帰宅後我が家は大興奮でした。

緑と赤のあのメガネをお持ちの方は、是非御覧ください。




まとめ


世の中、Javascript と HTML5 の世界になるようです。この2つの技術は必修科目ですね。

そして、進化した Android と AppEngine でバックエンドとモバイル。

ソーシャル対応に Google+ 。ビジネス Apps では、Apps Script 。

なんだかんだで、覚えることはイッパイです。

 

最後に、スタッフやボランティアの皆様方、お疲れ様でした!

2011/09/16

Google Apps Script ってすごいね

先日まで、Google Developer Day 2011 の DevQuiz がありました。

その中で Apps Script に関する問題が出題されていました。

個人的に気になっていたもので、ちょっとやってみることにしたのですが、ユーザガイドをみて驚きました。機能がすごく充実しています。

「オラ、わくわくすっぞ!」って感じです。


Google Apps Script ってなに?


Google Apps Script は、JavaScript を使用して Docs, Spreadsheets, Sites などから各種 Google サービスを制御することできます。
Microsoft Office における VBA のようなものです。

Apps Script では、作成した JavaScript のプログラムがサーバ上で実行される、という点が特徴ですね。


まだまだ日本語の情報が少ない Google Apps Script ですが、 Googleを追いかけろ! が参考になります。


Google Apps Script って何が出来るの?


何が出来るのかは、これから見ていきましょうw。

Excel を Apps Spreadsheets に移行する際の障壁は、VBA マクロだと思っていましたが、それが取り除かれた。と思ってもいいくらいなことができそうな予感です。


Google Apps Script を使ってみる


何はともあれ、どんなものかやってみましょう。


お題


よくある Excel マクロのように、CSV ファイルを読み込んで、Spreadsheets に出力してみます。


  1. スクリプトエディタ

    新規に作成した Spreadsheet から、ツールメニューの「スクリプトエディタ」でスクリプトエディタを起動します。

  2. コードを記述

    コード欄に下記を打ち込みます。

    function onOpen() {
      var app = UiApp.createApplication().setTitle("Upload CSV to Sheet");
      var form = app.createFormPanel().setId('frm').setEncoding('multipart/form-data');
      var formContent = app.createVerticalPanel();
      form.add(formContent);
      var file = app.createFileUpload().setName('thefile');
      var button = app.createSubmitButton('Submit');
    
      formContent.add(file);
      formContent.add(button);
    
      app.add(form);
    
      var doc = SpreadsheetApp.getActive();
      doc.show(app);
    }
    
    function doPost(e) {
      var app = UiApp.getActiveApplication();
      var fileBlob = e.parameter.thefile;
    
      var data = fileBlob.getDataAsString();
      if (!data) {
    	return app.close();
      }
      var csvData = data.split('\n');
    
      var sheet = SpreadsheetApp.getActiveSheet();
      sheet.getRange(sheet.getLastRow()+1, 1).setValue(fileBlob.getName());
    
      var startRow = sheet.getLastRow()+1;
      var startColumn = 1;
      for (var i=0,l=csvData.length;i<l;i++) {
    	var csvRow = csvData[i].split(',');
    	for (var j=0,l2=csvRow.length;j<l2;j++) {
    	  sheet.getRange(startRow+i, startColumn+j).setValue(csvRow[j]);
    	}
      }
    
      return app.close();
    }
    		
  3. Script の実行

    フロッピーアイコンでスクリプトを保存し、「関数を選択」より「onOpen」を選択します。

    再生ボタンでスクリプトを実行します。

  4. CSV をアップロード

    表示されたフォームより、適当な CSV ファイルを選択して、Submit です。

  5. CSV がシートに出力される

    CSV の内容がシートに書きだされました!


プログラムの説明を少しすると、[onOpen]という関数が、シートを開いたときに自動実行される関数です。VBA にもありますね。

ここで、アップロードフォームを作成し、表示させています。

もう一つの[doPost]という関数。これはフォームポスト時に呼び出されるもので、データの取得とシートへの書き出しを行っています。

doPost がポスト時に呼ばれるということに気付くまで結構はまりました…。


参考までに、アップロード時に使用した CSV と、Spreadsheet は下記から。参考にしてください。
*スクリプトの実行はできません


Google Apps Script をやってみて


リファレンスとにらめっこが必要ですが、汎用的な JavaScript で記述できるので非常にわかりやすいですね。

これから少しずつ、どんなことができるのか確認しながら、紹介してきたいと思います。

2011/09/12

Google AppEngine の新料金体系

とっても久しぶりのブログ更新です。皆さんお元気ですか?僕は元気です。


最近、AppEngine の料金体系変更によって、大幅に料金が増えるという話題をよく目にします。

気になって自分も確認してみました。
そして、多分にもれず驚いたのでメモしておきます。


AppEngine 新料金体系


AppEngine の新料金体系は、従来(現行)の CPU Time での課金から、Instance Hours での課金に変更されます。


料金の詳細は、 Google cloud services – App Engine に記載されています。


また、気になる、新料金体系ではどのように見積もられるのか?は、Admin Console の Billing History から確認することができます。



via Managing Your App's Resource Usage - Google App Engine - Google Code

今なら半額キャンペーン中!


上記のレポートの一例では、 Frontend Instance Housrs は、 $12.41 となっています。

為替レートが 1米ドル /円 = 77.089115 (ほんと円高ですね)ということなので、約956円/日。一ヶ月で 28,700円です。


でもよくみると、「Frontend Instance Hour costs reflect a 50% price reduction active until November 20th, 2011.」となっています。

11月20日までは半額キャンペーン中みたいです。

確かに Frontend Instance Hours: $0.04/Hour となっています。正規の料金は $0.08/Hour ですよね!


キャンペーンが終了したらどうなるのでしょうか?

単純に倍なので、約1,912円/日。一ヶ月で 57,400円です。


これ、みんな気づいているんでしょうか?僕は最初気がつかなかったです。

ダブルでビックリしますね。


新料金体系対策


今まで無料枠で気軽にアップしていたアプリが、突然金食い虫になったらたまりません。


App Engine アプリケーションのリソースを管理する方法 - Kay's daddy のリソースの管理方法が参考になります。


要は、ちゃんとリソース意識してアプリ作ってね、ということですが、

一番手軽な方法は、Admin Settings にある、 Max Idle Instances を 1 にする ということでしょうか。


近頃は、フリーミアムモデルからフリーの部分がなくなる、もしくは縮小される傾向が強いように思います。

手軽な環境がなくなっていくのは残念ですね。

2011/02/23

Rails 3, MySQL, jQuery, Shoulda, FactoryGirl

Rails 3 で、MySQL, jQuery, Shoulda, FactoryGirl を使うときのプロジェクトメモ。

MySQL でプロジェクトを作成

デフォルトでは Sqlite3 を使用するので、オプションで MySQL を使用するように指定。

$ rails new appname -d mysql

jQuery, Shoulda, FactoryGirl の設定

jQuery, Shoulda, FactoryGirl を使用するために、各ファイルを編集する。

environment.rb
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
Gemfile
gem 'jquery-rails'
gem 'rails3-generators', :group => :development
group :test do
  gem 'shoulda'
  gem 'factory_girl_rails'
end
application.rb
config.generators do |g| 
  g.test_framework :shoulda, :fixture => true
  g.fallbacks[:shoulda] = :test_unit
  g.fixture_replacement :factory_girl, :dir => "test/factories"
end

インストール

$ bundle install

Shoulda / FactoryGirl が適用されているか確認。

$ rails g scaffold --help
...

Shoulda options:
  [--dir=DIR]                   # The directory where the model tests should go
                                # Default: test/unit
  [--fixture-replacement=NAME]  # Fixture replacement to be invoked
                                # Default: factory_girl

jQuery をインストール

generator で jQuery に置き換えます。

$ rails g jquery:install

2011/02/14

Rails 3 で OpenSSL::SSL::SSLError

Rails 3 でプロジェクト作成後、まずは jquery を使うようにしようと思い

$ rails g jquery:install

すると、早速エラー発生。

    fetching  jQuery UJS adapter (github HEAD)
c:/ruby/lib/ruby/1.8/net/http.rb:586:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)

ソースを github から取得する際に、SSL 接続でエラーということか。

Rails3 で jQuery を使う を参考に、environment.rb に下記を追記。

require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

無理やり SSL 非接続にしてなんとか回避。とりあえずは、よしとします。

2011/02/09

Google Maps API v3 でカスタムマップを作成

暫く前に、「googlemapでドラクエ」ということで、ドラゴンクエストの世界地図を Google Maps で表示するサイトが話題になりました。
当時、コレを見て感動したのを覚えています。

今では Google Maps API も v3 となり、v2 は正式に廃止され、アップデートすることが推奨されています。

ということなので、カスタムマップの作成を v3 でやってみます。

大きい画像の用意

まずは、拡大時に耐えるような大きな画像を用意します。

1900年に作成された日本の世界地図 から拝借しました。

タイル(tile)を作成

Google Maps は、それぞれのズームレベルに合わせて 縦横 256px の画像(タイル)を地球全面に覆う仕組みになっています。
例えば、ズームレベル 1 では、256x256 px の画像を縦横 2枚、計 4枚のタイルにより構成されます。
ズームレベル 2 では、縦横それぞれ 2 倍の、計 16枚のタイルで構成されます。

GMIC - The GMap Image Cutter

というわけで、多数のタイルが必要になるのですが、自力でカットしていくのははっきり言って無理があります。

そこで GMIC というとても便利なツールの登場です。

このツールを使えば、用意した画像を Google Maps に合わせたタイルにカットしてくれます。しかも、解像度から最大ズームレベルまで判断してくれます。

使用方法も簡単で、ダウンロードした zip を解凍し、GMapImageCutter.batを実行(Windows の場合。その他は .sh)して起動させます。

起動したら、File を Open して、 Create するだけ!簡単です。動作も高速であっという間に作業が完了します。

出力ファイルには、タイル画像だけではなく、作成したタイルを表示するためのサンプル HTML も出力されます。
大きな画像を Google Maps 的に見たい!というなら、これだけで OK ですね。

V3

GMIC より出力された HTML は、残念ながら今現在は v2 の Google Maps API を使用しています。

そこでやっと本題の、カスタムマップを v3 で書き換えてみます。

ポイントは、ImageMapType というクラスを使うことで、一から MapType インターフェースを実装する手間を省いています。

サンプルは下記リンクから!

Google Maps API v3 カスタムマップサンプル

 

参考:

2011/02/02

さくら VPS で Wordpress のチューニング

さくら VPS はメモリが 512M とちょっと少なめです。Swap が有るためメモリオーバーで即ダウンするとこはありませんが、すぐに Swap メモリに手を出し極端なパフォーマンス低下を招いたりします。

Wordpress でサイト構築した際は、チューニングを事前に実施しておくことで、Swap を食いつぶして Apache がアクセス不能になって焦る、ということがないようにしたいものですね。

APC - PHP アクセラレータ

Wordpress は PHP, MySQL を使用しています。
まずは PHP のチューニングということで、定評のある APC をインストールします。

APC(Alternative PHP Cache) は、PHPの中間コードのキャッシュや最適化を行う拡張モジュールです。

インストールは、 yum で。Remiリポジトリからインストールするので、予め有効にしておきます。

$ sudo yum search php-pecl-apc
php-pecl-apc.x86_64 : APC caches and optimizes PHP intermediate code

$ sudo yum install php-pecl-apc

設定(/etc/php.d/apc.ini)はデフォルトを使用し、インストール後は httpd を再起動します。

$ sudo /etc/rc.d/init.d/httpd restart

APC の動作確認用ファイルをコピーして、ブラウザから動作チェックできるようにします。
なお、管理者情報はデフォルトから変更しておきます。

$ cp /usr/share/doc/php-pecl-apc-3.0.19/apc.php /var/www/html/www.domain.com/
$ sudo vi /var/www/html/www.domain.com/apc.php
defaults('ADMIN_USERNAME','apc');
defaults('ADMIN_PASSWORD','password');

MySQL のチューニング

次は、MySQL の設定を変更し、キャッシュとバッファの設定をします。

$ sudo vi /etc/my.cnf
[mysqld]
query_cache_limit=1M
query_cache_min_res_unit=4k
query_cache_size=24M
query_cache_type=1
key_buffer = 16M
sort_buffer_size = 1M
read_buffer_size = 256K

$ sudo /etc/rc.d/init.d/mysqld restart

Apache のチューニング

次は、Apache の設定の見直し。

$ sudo vi /etc/httpd/conf/httpd.conf

Timeout 45                  #接続を切るまでの時間
KeepAlive On                #接続の継続を許可
KeepAliveTimeout 3          #継続時間

StartServers       5        #起動時のプロセス数
MinSpareServers    5        #待機プロセス数の最小個数
MaxSpareServers   10        #待機プロセス数の最大個数
ServerLimit       64        #プロセス数の上限
MaxClients        64        #稼動プロセスの最大個数
MaxRequestsPerChild  4000   #一つのプロセスが実行するリクエスト数


$ sudo /etc/rc.d/init.d/httpd restart

ついでに、PHP の設定で、 zlib を有効にし、転送速度を向上させておきます。

$ sudo vi /etc/php.ini

zlib.output_compression = On

WP Super Cache - Wordpress プラグイン

最後に、Wordpress 自身のチューニングで、WP Super Cache というプラグインをインストールします。

プラグインのインストールは、Wordpress のダッシュボードからインストール出来ます。

インストール後は、設定ページから Caching On にすると有効になります。

まとめ

  • APC で PHP のチューニング
  • キャッシュとバッファの設定で、MySQL をチューニング
  • メモリに合わせて、Apache をチューニング
  • WP Super Cache で、Wordpress をチューニング

これで、かなり高速・軽量になったかと思います。
あとは、状況に合わせて細かな設定変更をしていくといいと思います。

 

参考
AKIBE - さくらのVPS CentOSでサーバ構築 13 – パフォーマンス

2011/01/24

[WordPress]ウィジェットのメタ情報デフォルト値を編集する方法

ウィジェットのメタ情報

WordPress のウィジェットで「メタ情報」というのがありますが、これをどうにか編集できないか?というわけで、その方法の Tips です。

デフォルトのメタ情報

  • サイト管理
  • ログイン/ログアウト
  • 投稿の RSS
  • コメントの RSS
  • WordPress.org

default-widgets.php

デフォルトのメタ情報の内、コメントの RSS と、WordPress.org へのリンクは不要だったのでコレを削除。

wp-includes の default-widgets.php がウィジェットのデフォルト値を管理しているので、こちらを修正すれば OK です。

wp-includes/default-widgets.php 300行目あたり
      <ul>
      <?php wp_register(); ?>
      <li><?php wp_loginout(); ?></li>
      <li><a href="<?php bloginfo('rss2_url'); ?>" title="<?php echo esc_attr(__('Syndicate this site using RSS 2.0')); ?>"><?php _e('Entries <abbr title="Really Simple Syndication">RSS</abbr>'); ?></a></li>
      <li><a href="<?php bloginfo('comments_rss2_url'); ?>" title="<?php echo esc_attr(__('The latest comments to all posts in RSS')); ?>"><?php _e('Comments <abbr title="Really Simple Syndication">RSS</abbr>'); ?></a></li>
      <li><a href="http://wordpress.org/" title="<?php echo esc_attr(__('Powered by WordPress, state-of-the-art semantic personal publishing platform.')); ?>">WordPress.org</a></li>
      <?php wp_meta(); ?>
      </ul>

ちなみに、デフォルト値を変更せずに、各サイトごとに修正するにはどうするんだろうか…?知ってる方がいましたら教えてください!

WordPress レッスンブック 3.x対応
エビスコム
ソシム
売り上げランキング: 874

2010/12/31

End Of 2010

ついに 2010 年も最後の日になりました。
お世話になった皆様方、本当にありがとうございました。

今年は、Android の本格的な普及や、iPad や Android タブレットなどモバイル環境が劇的に変化してきました。
また、Twitter や Facebook など、日本でも海外標準のものがどんどん普及していきました。

来年はどんなことが起こるのかと、わくわくする反面、流れについて行けるのかと不安な面もありますね。

新しいことにどんどんチャレンジし、常にエッジでいたいものです。
そしてそれを仕事にフィードバックできると最高ですね。

それでは、皆様、良いお年を!

2010/09/29

[GDD2010JP]Google Developer Day 2010 に行ってきた

今年も恒例の、Google Developer Day に参加してきました。

今年は東京会場に 1,000 人の参加があったらしく、すごい人数でした。

発表している技術の内容は主に、 HTML5, Android, AppEngine で、気づけば去年とあまり変わっていません。 しかし、その内容は確実に変化していて、HTML5 は主要モダンブラウザではすべてサポートされ、 Android 端末もぞくぞく登場しています。AppEngine でのアプリケーションも、ものすごい勢いで増加しています。

Apps も Marketplace が整備され、ビジネスの土台が整いました。Chrome も、 Extension や WebApps が登場し、ますますクラウドが加速しています。

まさに、次のフェーズに突入したと感じるものでした。

Web は HTML5 / CSS3 に置き換わり、Android, iPhone などのスマートフォンが主力になる。PC はより専門的なツールになり、一般には Android タブレットや iPad になっていくのだと感じます。

今回の GDD での、HTML5, Android, AppEngine, Chrome そして Apps 、これらは全てつながっており、そしてその土台となるものは既に整っているのだと、強く認識しました。

また、これらの技術はほとんどがオープンソースプロジェクトとして存在しています。そこに、 Google の強さを感じます。

自分としては HTML5 以外はほとんど、なんらかの開発経験がありますが、気がつけば blogger のテンプレートも HTML5 になっていたりと、早急に HTML5 にも注力していかなければならないです。

それと、ソーシャルウェブの話で 伊藤直也 さんが言っていた、「単なる繋がりの仕組みではなく、その深さもコンピューティングする」「繋がりのリニューアル」といったより実際の人間関係に近い仕組みが次のフェーズ。という話は印象的でした。

気がつけば、初開催より参加し今回で 4度目になる GDD ですが、毎度のことながら非常に刺激的なものでした。
モチベーションをひどく向上させてくれます。

時間と共に次第に薄れていくモチベーションが、こうやって定期的に向上できるのはとてもありがたいこと。

素晴らしいイベントを開催してくださった Google スタッフさん、ボランティアの方々ありがとうございました!

2010/06/22

ドーナツをエクレアにしてみました

Android 2.2 がリリースされ、iPhone 4 も発表され、ますますスマートフォンが勢い付いてきましたね。
そんな中、せめてマルチタッチを体験してみたいと思い、GDD フォンを Android 2.1 にアップしてみました。

前回、Android 1.6 である Donut にしたわけですが、その際は HTC より提供されたロムを使用しました。
Android 2.2 (Froyo) のアップデートも HTC よりまもなくリリースされるとのウワサもありますが、その前に有志による Complete Eclair というロムを使用し、Android 2.1 にしてみました。

手順はほとんど GDD PhoneにComplete EclairというROMを入れてみた - stnard.jp を参考にしていますので、詳しくはそちらを参照してください。
なお、Android は 1.5 に戻さずとも、root 化することが出来ます。

そして更に、せっかく root 化したので、オーバークロックにも挑戦しました。
GDD フォン (HT-03A) は、最大 512MHz の CPU ながら、電池消耗のためか 384MHz までしか使われてないそうで。電池の消耗は気にせずにフルで動いてもらいましょう。
これは、root 化が済んでいるので、Android Market から OverclockWidget をダウンロードし、ウィジェットとして配置後、クロック数の設定するだけで OK 。本当に動いてるのかは不明。というかその程度の違いなんでしょうか・・。
Complete Eclair にしてみて、正直動作が快適になることはなかったです。 OverClock を含めてもほとんど変わらずで、相変わらずのモッサリです。
しかし、しっかりバージョンアップはされていて、1.6 に戻す気にはなりません。やっぱりマルチタッチはいいですね。
また、なぜかビデオデバイスがおかしなことになっていて、動画を撮影することができなくなってしまいました。これは非常に残念。単にデバイスが故障しているのかもしれませんが・・・。

Android 2.2 では、非常に高速になるとのことなので、果たして 512MHz の GDD Phone でどのくらいサクサクになるのか、期待せずにはいられません!

2009/11/28

Gmail Template Switcher for Chrome Extension

しばらく前から、Gmail Template Switcher が Google Chrome の User Scripts で動かなくなっていました。
Google Chrome 4 からの仕様変更の影響で、ページ側のコンテキストにアクセスできなくなったことが原因でした。

時間を見つけては対応策を検討しましたが、結局、Extension に移行するのが早い。ということです。

というわけで、Chrome Extension 版の Gmail Template Switcher を作成しましたので、 Extension が有効な Chrome をお使いの方はどうぞお試しください。

update: Google Chrome Extensions Galleryからのインストールはこちらからどうぞ。

Gmail Template Switcher for Chrome Extension

参考:

2009/10/27

Android 1.6 にバージョンアップ

Android 1.6 Donut

先日 docomo の android 携帯「HT-03A」がバージョンアップし、Android 1.6 になりました。

そこで、手元の GDD携帯もバージョンアップしてみました。

Android GDDJ-09 システムイメージ 1.6アップデートまとめ | 開発 を参考に、数ステップで完了です。

途中 手順5の、イメージファイルをダウンロードし本体に転送する際に、下記のメッセージが表示された場合は、SDカードをアンマウントしてから再度実行します。

>adb push signed-jdd-ota-14721.zip /sdcard/update.zip
failed to copy 'signed-jdd-ota-14721.zip' to '/sdcard/update.zip': Permission denied

Android 1.6 では、Androidマーケットや YouTubeアプリなどのインターフェイスが刷新されかっこよくなっています。
また、全体的に動作が軽快になっていて、いい感じです。
ハードの性能アップなしにソフトをバージョンアップすると重くなると思っていたので、バージョンアップで動作が軽快になるのはとてもうれしいですね。

参考:

Android GDDJ-09 システムイメージ 1.6アップデートまとめ

htcのサポートページに書かれた手順を参考に行った。縦に長めのページだが、実際に必要なのはその一部なので以下に抜き出してまとめる(「fastboot 方式の場合のみ」必要な手順の記述が多い)。
「概要」では2つの方法が提示されているが、おすすめ通りに「リカバリ イメージ方式」で行った(逆に1.6から1.5へ戻すには、「リカバリ イメージ方式」では無理なので「fastboot 方式」を使う必要があるようだ)。

Android GDDJ-09 システムイメージ 1.6アップデートまとめ | 開発

2009/10/16

[rails] Mysql で Incorrect datetime value が発生

Rails 2.3.4 と Mysql 5.0 (Windows) の環境で、Unit Test を実行すると下記のエラーが発生。

>rake test:units
  1) Error:
test_should_authenticate_user(UserTest):
ActiveRecord::StatementInvalid: Mysql::Error: Incorrect datetime value: '2009-10-16 07:56:13 UTC' for column 'remember_token_expires_at' at row 1: INSERT INTO `users` (`salt`, `updated_at`, `crypted_password`, `remember_token_expires_at`, `id`, `remember_token`, `login`, `created_at`, `email`) VALUES ('356a192b7913b04c54574d18c28d46e6395428ab', '2009-10-15 07:56:13', '39e3509c8a1dff4e5b35850d970992321c4f1358', '2009-10-16 07:56:13 UTC', 1, '77de68daecd823babbb58edb1c8e14d7106e83bb', 'quentin', '2009-10-10 07:56:12', 'quentin@example.com')

Mysql の sql-mode を空白に設定することで解決しました。

my.ini
# Set the SQL mode to strict
#sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
sql-mode=''

参考:

Now, open the my.ini file located at c:program files/MySQL/MySQL
Server X.x/my.ini.
Add a # at the begining of the line: sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
Type sql_mode='' on the next line and save the file.
restart mysql

fixed it

[Rails] Re: restful_authentication rspec failures "Mysql::Error: Incorre

2009/10/15

[User Heat]ヒートマップ・ツールを試してみました

先日話題になった、訪問者がWebのページのどこの段落を注目して読んでいるのかを可視化する、 User Heat を試してみました。

ユーザーヒートでは、「マウスの軌跡」、「クリック場所」、「読まれた場所」の3つを分析可能です。
上の画像は、「クリック場所」を示す Click Map で、クリックした回数が多い箇所ほど赤く表示されるようです。

しばらく前から仕込んでおいたのですが、分析には十分なアクセスが必要なようで、残念ながらまだヒートマップは見れないようです・・。

サイトがどのように見られているのかが可視化できるのはいいですね!
ただ、あまりアクセスがないサイトだと、分析結果が出るまでに時間がかかりそうです・・・。

2009/09/07

Google App Engine Oil で twitter もどき STEP 1

前回、Webアプリケーションをさくっと手軽に構築できてしまう Google App Engine (GAE) を試してみましたが、今回は、もう少しまともなアプリケーションを作ってみます。

作成する前に、つい先日 GAEO が 0.3 にバージョンアップしているようなので、早速最新のリリースを試してみましょう。

バージョンアップ作業は、環境変数のパスを新しいバージョンのものに変更しただけです。

Twitter

Twitter は、140文字以下の短いメッセージをつぶやきあうシンプルなサービスです。現在とても注目されているサービスですね。
シンプルでわかりやすいですので、今回は Twitter もどきのアプリケーションを作成してみます。

mockker

それでは、Twitter もどきの「mockker」というプロジェクトを作成します。
とりえあず今回は、データの登録ができればOKとします。また、アカウントは Google App Engine の ユーザーサービスを使用し、Google アカウントと連携させます。

gaeo.py mockker
cd mockker

まずは、つぶやきの scaffold を作成します。

gaeogen.py scaffold status create show "text:StringProperty()" "user:UserProperty()" "created_at:DateTimeProperty(auto_now_add=True)"

ルーティング

デフォルトのルートへのルーティングを、welcome/index から status/index へ変更します。

gaeo/dispatch/router.py
class Router:

  """ Handles the url routing... """


  class __impl:

    def __init__(self):
      self.__routing_root = {'controller': 'status',
                   'action': 'index'}

model

scaffold により、 application/model/status.py が作成されます。

application/model/status.p
from google.appengine.ext import db
from gaeo.model import BaseModel, SearchableBaseModel

class Status(BaseModel):
  created_at = db.DateTimeProperty(auto_now_add=True)
  text = db.StringProperty()
  user = db.UserProperty()

controller

scaffold により作成された status コントローラを次のように修正します。

application/controller/status.py
import cgi
import logging

from google.appengine.ext import db
from google.appengine.api import users

from gaeo.controller import BaseController

from model.status import Status

class StatusController(BaseController):
    def create(self):
        r = Status(
            # Uncomment all required properties here.
            # text = self.params.get('text', None),
            # created_at = self.params.get('created_at', None),
            user = users.get_current_user(),
        )
        for prop in Status.properties():
            if prop in self.params:
                setattr(r, prop, self.params.get(prop))
        r.put()
        self.flash['notice'] = u"独り言を更新したよ"
        self.redirect('/')

    def index(self):
        notice = self.flash.get('notice', '')
        self.msg = notice
        if self.current_user:
            query = Status.all().filter('user = ', self.current_user)
            query.order("-created_at")
            self.result = query.fetch(limit=10)

    def show(self):
        r = Status.get(self.params.get('id'))
        if r:
            for prop in Status.properties():
                setattr(self, prop, getattr(r, prop))
        else:
            self.redirect('/')

ユーザー認証のため、base コントローラの before_action を次のように修正します。
これにより、全てのアクションの前にユーザー認証が実行されます。

gaeo/controller/__init__.py
from google.appengine.api import users

  def before_action(self):
    self.current_user = users.get_current_user()
    if not self.current_user:
      self.signed_in = False
      self.login_url = users.create_login_url(self.request.uri)
      #self.redirect(users.create_login_url(self.request.uri))
    else:
      self.signed_in = True
      self.logout_url = users.create_logout_url(self.request.uri)
      self.nickname = self.current_user.nickname()

view

view を次のように修正します。

application/templates/base.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>{% block title %}{% endblock %}</title>
  <link rel="stylesheet" href="/css/common.css" type="text/css" media="screen" />
  {% if signed_in %}
  <link rel="stylesheet" href="/css/login.css" type="text/css" media="screen" />
  {% endif %}
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
  <script type="text/javascript" src="/js/application.js"></script>

</head>
<body>
<div id="header">
  <div id="header_inner">
  <h3><a href="/" title="Mockker">Mockker</a></h3>
  {% if signed_in %}
  <ul id="nav">
    <li><a href="{{ logout_url }}" title="Logout">Logout</a></li>
  </ul>
  {% else %}
  <ul id="nav">
    <li><a href="{{ login_url }}" title="Login">Login</a></li>
  </ul>
  {% endif %}
  </div>
</div>
<div id="content">
  <div id="content_inner">
  {% if msg %}
  <div class="flash">
    <div class="notice">
    <p>{{ msg }}</p>
    </div>
  </div>
  {% endif %}
  {% if signed_in %}
  <div id="update">
    <form method="post" action="/status/create">
    <span id="countdown">140</span>
    <label for="text">何か言いたいことは?</label>
    <textarea id="text" name="text" rows="10" cols="10"></textarea>
    <input type="submit" name="update" value="Update" />
    </form>
  </div>
  {% endif %}

  {% block content %}{% endblock %}
  </div>
</div>

<div id="footer">
  <div id="footer_inner">
  <div class="column">
    <ul>
    <li><a href="/" title="Home">Home</a></li>
    </ul>
  </div>
  </div>
</div>
</body>
</html>
application/templates/status/index.html
{% extends "../base.html" %}

{% block title %}StatusController#index{% endblock %}

{% block content %}

<div id="statuses">
{% for r in result %}

  <div id="status_{{ r.key }}" class="status">
  <div class="info">

    <p class="who_when">
    {{ r.user.nickname }}<br />
    {{ r.created_at }}
    </p>

    <p class="actions">
    </p>
  </div>

  <div class="text">
    {{ r.text }}
  </div>
  </div>
{% endfor %}
</div>


{% endblock %}

あとは、Javascript や CSS などで、見栄えを整えます。

実行

dev_appserver.py .

登録したデータをクリアしたい場合は、「--clear_datastore」オプションをつけて実行します。

dev_appserver.py --clear_datastore .

以上で、自分だけがつぶやくことができる、独り言アプリケーションの完成ですw
次回は、他人のつぶやきを表示できるようにしてみたいと思います。

2009/08/04

Google App Engine Oil

Google App Engine Oil

Webアプリケーションをさくっと手軽に構築できてしまう Google App Engine (GAE) ですが、この Google 製のエンジンに、あるオイルを入れてやると、さらに激速なマシンができるようです。

Google App Engine Oil(GAEO) というこのオイルは、Ruby on Rails を参考にして作られた App Engine 専用の レーシングスペックのエンジンオイル(Webアプリケーションフレームワーク)です。

GAEO をインストール

まず、GAEO は GAE 上で実行されますので、予め Python や、GAE SDK をインストールします。
なお、以下は Windows での解説です。

プロジェクトホーム からパッケージ(gaeo-0.2.1.zip など)をダウンロードし、好きなところに解凍します。

GAEO スクリプトを利用するために、解凍先の bin ディレクトリへのパスを、環境変数 PATH に追加します。

パスを設定しましたら、gaeo.py コマンドを実行し、下記のようになるとインストール完了です。

>gaeo.py
Usage: C:\<install dir>\bin\gaeo.py <project name>

Hello GAEO

では、早速 Hello GAEOプロジェクトを作ってみます

GAEO でのプロジェクトを作成するには、作業ディレクトリで、次のコマンドを実行します。

gaeo.py hello

hello プロジェクトを作成すると、hello ディレクトリには、下記のコンテンツが生成されます。Rails そっくりです。

  • app.yaml, favicon.ico, main.py

    app.yaml と main.py は、GAE のメイン設定ファイルです。

  • application/

    アプリケーションのコードの置き場所。基本的にこの中のファイルを編集していきます。

  • assets/

    javascript や css ファイルの置き場所。app.yaml で設定可能です。

  • gaeo/

    GAEO のコアライブラリ。GAEO のアップグレードは、このディレクトリのファイルを入れ替えるとOKです。

  • plugins/

    プラグインのインストールディレクトリです。

アプリケーションの起動と確認

次のコマンドで GAE を起動し、作成したアプリケーションの動作を確認します。
なお、コマンドはアプリケーションのルートディレクトリで実行します。

hello>dev_appserver.py .
 Running application hello on port 8080: http://localhost:8080

http://localhost:8080/ にアクセスして、「It works!!」と表示されればOKです。

なかなか刺激的な体験ですが、次はちょっとしたアプリケーションを作ってみたいと思います。

Google App Engine Oil で twitter もどき
Google App Engine Oil で twitter もどき STEP 1

参考:

2009/07/16

[Gmail][Greasemonkey]Gmail Template Switcher を Update

しばらくぶりに、Gmail Tempolate Switcherアップデートしました。

変更点は下記の2点です。

  • Google Chrome User Scripts に対応
  • リッチテキストに対応

最近の僕は、Google Chrome がメインブラウザになりつつあります。
Firefox は、Firebug を使いたいときや、動作確認程度になってしまいました。

Chrome は、なんといっても動作速度がお気に入りです。とにかく早いですね。これで Google ツールバーがあれば最高なんですけど。

そんな Chrome ですが、先日、Chrome のバージョンが上がり、これまで Greasemetal 上で動作させていた Greasemonkey Script が動かなくなってしまいました。これはまずいということで、Google Chrome User Scripts 対応にアップデートです。

そして、またまた先日。今度は、右上の返信ボタンから返信しようとすると、強制的にリッチテキスト形式になってしまう現象が発生していました。
テンプレートが反映されず、これはまずいということで、リッチテキスト形式対応にアップデートです。

また、コメントでもご意見いただきありがとうございます。

そんなわけで、最新版の Gmail Tempolate Switcher は、下記からダウンロードしてください。

Gmail Template Switcher - v 2.0

2009/06/15

Google Developer Day 2009

Google Developer Day

今年も Google Developer Day に参加してきました。

すでに恒例のイベントとなっていますが、年々内容が洗練され、とてもすばらしい内容になってきました。

今回の主な内容は、次のもの。

Google Developer Day

なかでも、HTML5Google Wave はあらたな時代を感じさせるすばらしいものでした。
ブラウザだけで(HTML + Javascript)、2D や 3D といったリッチな表現を可能にする、HTML5。
これまでの メール 主体のコミュニケーションを大きく変えてしまうパワーがある、Google Wave。
実際に普及となるとまだ先だとは思いますが、

Android についても、もうすぐ日本でも docomo から発売されますので、これから非常に注目されるものです。

Open Social は、ついに日本最大の SNS である mixi が完全対応ということで、多くのユーザにリーチできるという点で、マーケティング的にも非常に魅力的なものになりました。
Android と Open Social の組み合わせは、非常に刺激的なものです。

そして、Google AppsGoogle App Engine の組み合わせによる、Enterprise なアプローチは、クラウド化する今日において、対企業へ非常に魅力的なソリューションを提供できるようになります。

Google Maps は、久しぶりのバージョンアップにより、Ver 3 になります。
iPhone や、Android といったモバイル端末上で快適に動作するように最適化がなされるようです。
GPS が普及し、地図分野はますます便利になっていきますね。

Google Developer Day 2009 Android

今回の GDD では、Google I/O 同様サプライズとして、Google Dev Phone の新版が無料配布されました。
すでにあった Dev Phone 1 (Android 1.0) を、Android 1.5 にアップデートしようかと思っていたところだったので、ちょうどいいタイミングです。
しかも、ロケールに日本語があって、日本語での文字入力も可能。すばらしいです。
これで、Android 1.5 でも実機テストが可能ですね。

会場でも、iPhone を片手に講演を聴いている方が多数いて、やはり、昨年とは会場の雰囲気も違いました。
来年はきっと、僕も Android を片手に講演を聴いているでしょう・・。

思いついたアイディアが、たとえ先見の明があったとしても、それが時期尚早だったりすることがあります。
しかし、それが今ならなんだかいけそうな気がする!と、今年の GDDD は、そんな気になりました。

今一度、過去のアイディアを整理してみるのもいいかもしれません。