2012/05/15

サマーインターン開催と募集のお知らせ

こんにちは。ミツバチワークスの諸富と申します。
今日は「サマーインターン」の実施と参加者募集のお知らせをします。


最初に、なぜインターンをやろうかと思ったのかをちょっとご紹介しようと思います。

学生生活が終わると、ほとんどの人が社会に出て、そのほとんどの人がどこかの会社に就職することになると思います。

就職活動では、主に
・自分が何をやりたいのか?
・どんな会社だと、その自分のやりたいことができるのか?
ということをベースに、なるべく自らの意図に沿う会社を探すわけですが、たぶん、この辺のことが感覚的にわかっていて、判断できる人は小数派だと思います。少なくとも僕は全くわかっておらず、就職活動もよくわからなくなって途中でやめてしまった派でした。
何事もやってみなければわかりませんよね。

インターンとは、ざっくり言えば、「就業体験」のようなもので、
実際と近い形でオフィスに通い、業務を体験することで上記の答えを出すヒントを得ることができる、かなり有効な手段だと思います。

ミツバチワークスは現在社員40人ほどの小さい会社ですが、そんな当社でも、そのヒントを提供することができるのではないかと思います。

・大きな会社だからできること
・小さな会社だからできること
それぞれありますが、ことインターネットが絡んだ世界では、この境界はなくなりつつあります。

ご存じない方もいらっしゃるでしょうが、ミツバチワークスではWEBとリアルを絡めたDECOLOGという国内でも類をみないタイプの大きなサービスを運営しています。

つまり「ミツバチワークスしかできないこと」というのもあるんです。
そのことを実体験を通して知っていただくことは今後のみなさんの視野を広げるという意味で、価値のあることだと思っています。

また、一方で僕たちもみなさんとのこの体験を通して、自分たちの立ち位置を再確認するという良い機会になると思っています。


というわけで、ミツバチワークスでは初めての試みですが、楽しいイベントにできると思うので、ご応募、お待ちしてます!

以下の募集要項をご確認の上、ご応募ください。




募集要項

【期間・場所】
期間:8月20日〜8月31日 の平日10時〜19時
場所:恵比寿本社

※期間の延長については応相談



【応募資格】
以下のすべての条件を満たす方
  • 18才以上
  • 上記期間中、基本的には全日参加可能な方(ここは応相談です)
  • 開発用のPCを自分で用意できる
  • プログラミングスキル、デザインスキルなど、WEBサービス開発に関するなんらかの技能を持っている。(いわゆる「エンジニア」に限りません)
    • 例)Photoshop,Illustratorでの制作経験やRubyやJavaなどのプログラミングの経験(言語問わず)、HTML5・CSSでの製作経験など
  • 学生、もしくは正社員としての就業経験がない
    • 大学4年生やM2の方など、今年度卒業予定の方も大歓迎です!

※宿泊場所の用意はございません。

【内容】
  • ミツバチワークスの事業・業務紹介
  • デザイン・プログラミングなど、サービス開発・運用に必要なスキルに関する講義および実践
  • テーマに沿った開発・制作

※内容は応募状況によって変更される可能性があります。


【待遇】
  • 往復交通費(上限あり)
  • 日当1万
  • 期間中、僕達が相談にのれることは何でものります


【選考方法】
書類選考→面接(東京・恵比寿)→採用
※面接の交通費はご負担ください

【書類選考の参加方法】
以下の内容を含んだ書類(書式不問)をメールでintern[at]328w.co.jpまでお送りください。
※[at]を@に読み替えてください
その際、メールの件名に「インターンシップ応募」とご明記ください。

<応募書類内容>
  • 履歴書
  • なぜ応募してみようと思ったのか、その理由。
  • WEBサービス開発に関して保有しているスキル
  • 前項のスキルをどうやって学んだか、そのスキルを使って何をしたか

※実際に制作物を見せていただける方は書類のどこかで

2012/05/08

Blocksでバックグラウンド処理を楽にしよう!


どうも taka です。

Objective-Cの事も書いておかないとiPhoneアプリ技術者だと思ってもらえないのでは?
と思い、今回はObjective-Cのネタを書きたいと思います。

内容は『Blocksでバックグラウンド処理を楽にしよう!』です

slidropでは色んな所でバックグラウンド処理を使っています。

このネタの効能は、

  1. 可読性があがった!
  2. 楽に使えるようになった!

です。是非使ってみて下さい。

■普通に書くと?



という感じになります。

ちょっとした処理をバックグラウンドに回したい時、
メソッドをわざわざ書かないといけないのが残念…。

そして、バックグラウンド処理に回す場合は

@autoreleasepool

でくくっておかないとメモリリークします。

■NSObjectを拡張してみる

そこで、Blocksを使えるようにNSObjectを拡張します。

NSObject+Extensions.h


NSObject+Extensions.m


■使ってみる!



2012/03/12

写真共有サービスslidropの裏側



どうも taka です。

新サービスが公開され楽しくドタバタしてます。

一緒にドタバタしたい人はこちら。 → 仲間募集

【今回、紹介するモノ】

さて、今回は3/6に無事公開された写真共有サービス


で使っているAWSのサービスやソフトウェアを紹介しようと思います。

今回は、コードはいっさいありません!

  • うんうん
  • だよね!
  • えっ!こっちの方がいいだろ!
  • 普通だなぁー

とか思って頂ければ。

【そもそもslidropって何?】

slidrop(スライドロップ)は、写真を最大12枚までのslideという1つの塊として投稿できる写真共有サービスです。

iPhoneアプリでは、友人が投稿したslideが縦のタイムラインとして表示されます。
そして、同時に投稿した写真は横方向にスライドする事でみることができます。

という事なのですが、百聞は一見にしかず!

こちらからダウンロードしてみて下さい!(笑)

【AWSのサービス】

slidropは以下のサービスを使っています。

EC2
RDSMulti AZ
S3画像だけでなく、アクセスログなども期限付きで置いてます。
CloudWatchRDSの監視
Route53

これらのサービスを使って以下のような構成にしています。

Gateway/デプロイ/管理サーバEC2外部からのssh/デプロイ/インスタンス立ち上げ
WebサーバEC2
DBサーバRDS
監視用サーバEC2各EC2インスタンスの監視
監視用DBサーバEC2

まずまず王道な構成だと思います。

負荷が増えてきたら、

2012/03/05

DECOLOGの絵文字変換処理

こんにちは tommy です。今回は絵文字シリーズ後半ということで、DECOLOG サイトでの絵文字処理方式について解説したいと思います。正直な話誰得な感じもしますけれども、滲み出るカオス感を楽しんでいただければ幸いです。なお絵文字そのものの仕様については、適宜前回の記事を参照ください。

1. 携帯時代

まずはスマートフォン登場以前の話です。
絵文字を DB に格納する
DECOLOG の携帯版のサイトでは、ブラウザの入出力の文字コードは Shift JIS、アプリケーション (PHP) およびデータベース (MySQL) の内部コードは UTF-8 としています。よってアプリケーション内で Shift JIS - UTF-8 間の変換を行っています。文字コード変換には CP932 のマッピング (PHP では "SJIS-win") を使います。ここいら辺は割と定番だと思います。
さて、これで 3 キャリアの絵文字のコードを入力するとどうなるかというと、絵文字コードの範囲は CP932 では「利用者定義領域(95区-114区)」または「IBM 拡張文字(115区-119区)」のいずれかに収まるため、一応 1:1 の関係で UTF-8 のコードに変換されます。これはキャリアが定義した Unicode マッピングとは別物 (但しDoCoMoに限っては一致します) であるためシステム外部との運用性はありませんが、内部コードとして使うことはできます。以下これを便宜上「DECOLOG絵文字コード」と呼ぶことにします。
とりあえずここまでは特に何もしなくても、同一キャリア間であれば絵文字を扱うことができることになります。
3キャリア間の絵文字変換
3キャリア間で絵文字をやり取りできるように、出力時に端末のキャリアに応じて文字の置き換えを行います。変換テーブルは
  • キャリア間で同じような絵文字があれば、それに置き換えて表示
  • 該当する絵文字がなければ、対応する言葉で置き換えて表示
といったルールで作成します。DoCoMo、au、SoftBank それぞれ相互に変換できるようにするので、変換テーブルは全部で 6 種類つくる必要があります。DECOLOG では自力で変換表を作りましたが、今はフリーのライブラリが充実しているので割と簡単に用意できると思います。処理の順番は、
  1. ユーザーが入力した文字列に対し、上記の変換テーブルを適用して変換
  2. 出力全体を UTF-8 から Shift JIS に変換する
  3. ブラウザへ送出
としています。
ここで問題となるのは、ユーザーが入力した文字列がどのキャリアの端末から入力されたのか知る必要があるということです。前回の記事の通り、Shift JIS 上の各キャリアの絵文字のコードポイントは一部重複しているため、ある一文字のコードポイントだけを見てそれがどのキャリアの文字かを判別することができません。
そんなわけで DECOLOG のデータベースでは、ユーザーが絵文字を入力できるテキストを含むテーブルそれぞれに、それがどのキャリアの端末で入力されたのかを保持するためのカラム (「text_mode」という名前です) を一つ用意するという割と力技でこの問題を解決しています。たまにカラムを作るのを忘れたために絵文字の変換がされない箇所が発生することがありますが、いつか直しますので許してください。
携帯時代の DECOLOG 絵文字対応まとめ
ここまでの内容をまとめると、以下のようになります。
  • ブラウザから入力された文字列は、そのまま UTF-8 に変換して DB に格納
  • DB 格納時に、キャリア情報を専用のカラム (text_mode) に保存
  • DB に格納された文字列を表示するときに、専用の変換テーブルを用いて表示しようとしている端末に応じた絵文字に変換

2. スマートフォン時代

DECOLOG では、2010年10月に (割とひっそりと) 携帯以外のアクセスを受け入れるようにしてから、少しずつスマートフォン対応を進めてきました。絵文字の扱いに関しても、やはり少しずつ改善しつつ今に至る、という感じです。現時点では、従来の携帯端末/iPhone/Android間でおおむね絵文字の相互変換ができるというところまで実現できています。
DECOLOG のスマートフォン対応について
DECOLOG のスマートフォン対応は大きく 2 段階で行われています。
  1. まずはスマートフォンからモバイルサイトにアクセスできるようにする(モバイルモード)
  2. 次にスマートフォンに表示最適化されたページを用意する(スマートフォンモード)
絵文字の観点からモバイルモードとスマートフォンモードを比較したときに大きく違うのは文字コードです。モバイルモードは従来通り Shift JIS のページですが、スマートフォンモードでは UTF-8 のページとなっています。好みに応じて好きなモードを選べるようになっているため、どちらの文字コードの入出力にも対応する必要があります。
絵文字対応0: 携帯端末以外は絵文字変換しない
厳密には絵文字対応とは言いがたいのですが、PC のブラウザなどからのアクセスについては、絵文字変換を行わないという仕様になっています。絵文字が含まれているテキストを表示する際はそのまま表示し、入力されたテキストを DB に保存する際もキャリアは不明という扱いにしています。
絵文字対応1: スマートフォンからのアクセスでキャリアを判別する
前回の記事で触れたとおり、今のところどのスマートフォンも自社のキャリアの絵文字のみ入力できるという仕様になっています。なお、iOS5 の場合は au の iPhone でもパレットから入力できるのは SoftBank 由来の絵文字なので、正確には自社ではなく単一キャリアの文字ということになります。
このため、アクセスしてきたスマートフォン端末がどのキャリアのものか判別する必要が出てきます。従来の携帯端末に対してはアクセス元の IP 帯域やユーザーエージェントの文字列で簡単に判定できますが、スマートフォンでは簡単な判別手段は用意されていません。そのため、DECOLOG では次の手段で判別を行うことにしました。
iPhone
SoftBank絵文字が入力されたものとして扱う。
Android
ユーザーエージェントの文字列に含まれる機種名と出荷元のキャリアの対応表を用意して判別
ということで、またも力技です。なので Android の新機種が出ると都度対応表をアップデートしているという状況です。
絵文字対応2: スマートフォンへの出力で絵文字が表示できるようにする
端末のキャリアが分かると、まずは従来の携帯端末から入力された 3 キャリア別の DECOLOG 絵文字コードをスマートフォンで変換して表示できるようになります。変換ルールは前回の記事で説明したとおり、
種類 変換先
iPhone SoftBank UTF-8 絵文字コード
DoCoMo Android Google 絵文字コード (の DoCoMo 由来の範囲だけ)
au Android Google 絵文字コード (の au 由来の範囲だけ)
SoftBank Android Google 絵文字コード (の SoftBank 由来の範囲だけ)
となります。
これも変換テーブルを用意するわけですが、3 キャリアの絵文字コードをそれぞれ上の 4 パターンに変換するため計 12 種類のテーブルを作成しました。ただし、Andorid からモバイルモード(Shift JIS)のページにアクセスされた場合は、従来の携帯と同じ扱いとすれば良いので変換テーブルも従来の携帯向けのテーブルをそのまま適用します (それも含めると全 18 種類)。
といっても、これは手で作ったわけではなく、Unicode 6.0 の元になった emoji4unicode プロジェクトが作成した対応表の XML
http://emoji4unicode.googlecode.com/svn/trunk/data/emoji4unicode.xml
からほぼ機械的に作成できます。
例として、DoCoMo の DECOLOG 絵文字コードから au Android のコードに変換するテーブル(の一部)はこんな感じになっています。入力が UTF-8、出力が 16 進の数値参照形式です。

絵文字対応3: スマートフォンからのフォーム入力で絵文字を入力できるようにする
出力側が対応できたので次は入力側の対応です。DECOLOG ではそもそもメール投稿での絵文字利用をサポートしていないため、対応範囲は主にフォームから入力された絵文字ということになります (他に iPhone アプリからの記事投稿にも対応しています)。
スマートフォンから送出される絵文字を DB に格納するにあたって、そのコード体系は携帯時代の 3 キャリアの絵文字コードをそのまま踏襲することにしました。
最大の理由は、MySQL のテーブルが「utf8」で作成されていることです。iOS/Android 共に、送出される絵文字のコードは 4byte UTF-8 を含んでいます。これをそのまま「utf8」で作成されたテーブルに格納しようとすると、該当する文字以降がすべて切れて格納されてしまうという問題が発生します。MySQL で正しく 4byte UTF-8 を扱うためには、
  • MySQL のバージョンを 5.5.3 以降にアップグレードする
  • テーブルの文字コードを「utf8mb4」にする。既存のテーブルの場合、ALTER 文の実行が必要(!)

2012/02/27

おとなの正しいおねだりのしかた

こんにちは!レーシックにより生まれ変わりました!hiroshi改めhiroshi2.0です!(視力が2.0)夏が楽しみ!!

さて、takaがAWSを使ったサービスについてのエントリを書いてますが、AWSを使いたいから採用したわけではないですし、会社組織なので使いたかったら使えるというもんでもないわけです。場合によっては田園調布に家が建つくらいのお金が動きうる話ですので、相応の行動を起こさねばいけません。このギャグ知らないか。

すなわち、意味があるかどうかをキチンと検討し、意味があるという結論になれば、それを理解してもらうべき人に理解してもらうというステップを踏む必要があります。

今回は、そのステップの足がかりのイメージがわかない人向けに、その足がかりが提供できればと思います。誰得なのかわかんないですけど。

本当にAWSが必要なのか?意味があるのか?を検討する

当たり前といえば当たり前ですが、この問いに対して論理的・具体的に答えられる人は少ない気がします。

  1. コスト的側面
  2. 事業スピードの向上的側面
  3. リクルーティング的側面
  4. 技術研究的側面
など、決裁者に対して訴えるべきモチベーションはケースバイケースだと思いますが、こういうケースの場合、最終的には「それっておいしいの?(=儲かるのか?)」というところに終着すると思ってます。

その判断は最終決裁者のみぞ知る所だと思われるかも知れませんが、そこにつながるストーリーの妄想は誰でもできるはずです。妄想しましょう。

妄想して、ある程度のストーリーが描けたら、その妄想が現実に即しているかどうかの裏を取ります。

たとえば、「AWSを使うとコストが抑えれるお!利益増えるどだから使うべきだお!」という妄想をしたのならば、「そうである」ことを具体的なデータを以って現実的(客観的)なものにします。

妄想ポイントはあまりにもケースバイケースなので、今回はこの程度でサクっと通り過ぎます。

妄想の現実化をしたら次のステップです。

紙は大事
妄想したら、その内容を紙に書きましょう。まあ、普通に考えても、こんな話を口頭でいきなり話されても全部理解なんてできないですし、宿題にしようと思っても覚えきれるわけもありません。真剣味も伝わりません。

ぼくが20代を過ごした環境では、「手ぶらだったら会議なんてやらないほうがいい。1枚でもいいから紙もってけ」とか「会議は戦だ。そして戦は準備の段階で勝敗が決まる(←武田信玄のセリフらしいです)」といった具合に交渉ごとや打ち合わせなどの会議においては必ず紙という装備で攻守を固めることを要求されましたが、こういった経験はいろんなところでぼくを助けてくれています。感謝。

ところで、会議の内容にもよりますが、なにもない時でも5分で書ける程度の箇条書きのアジェンダでいいので持って行きましょう。たった一枚の紙が、参加者する人の目的意識を統一し、緊張感を持たせることができたりします。5分でかけるアジェンダもないなら会議をやめたらいいじゃない。

なお、ここでいう「紙」というのは資料のことで、僕にその辺のことを叩き込んだ先輩たちがそういっていたので一般的な言い方かどうかはよくわかんないです。パワポでもKeynoteでも何でもいいと思います。やっぱ何でもよくないかも。状況に応じて適切なものを選んでください。

口頭で言って通るケースもありますが、少なくともお金や時間がかかるものであれば、そういったケースはラッキーだと思うべきでしょう。

というわけで、できたものをふんだんに伏せ字などの加工したものがこちらになります。



この資料で主に訴えているのは、が「コスト効率」と「事業スピード向上」ですが、「リクルーティング」も自動的におまけで少しついてくる気がします。これはたぶん、ほとんどのAWS採用のケースにおいて同じかと思います。

これをベースに進めていきたいと思います。



2012/02/13

キャッシュマニフェストってなんだ

leonです。

ガラケー向けだったDECOLOGも最近どんどんスマートフォン化してます。
ガラケーとスマートフォンではブラウザの表現力が雲泥なので、各ページのHTML書き直し必須です。
これを機にHTMLを勉強しなきゃ、ということでHTML5を新年の抱負にしました。

まずは、HTML5ってなんですかってところなんですが、HTML5が示す仕様って範囲広い。
HTML5に含まれている仕様には以下のようなものがあるらしいです。

  • セマンティックス
  • オフラインとストレージ
  • デバイスアクセス
  • 接続性
  • マルチメディア
  • グラフィック
  • パフォーマンス
  • CSS3


というのも、HTML5はブラウザプラグインで提供されているFlashなどのリッチインターネットアプリケーションをプラグインレスで利用できるようにするために、ウェブアプリケーションのプラットフォームとしての機能やマルチメディア要素をすべて取り込んだものになってる模様。

HTML5を勉強するって決めたもののどこから手を付ければいいのかなと、途方に暮れそうになりましたが、考え方を変えると最近のWEBトレンドを追いかければ大概それはHTML5なんじゃないかと気づきました。
いうことで、気にせず好きなところから始めることにしました。

で、最初に手をつけたのがキャッシュマニフェストです。
キャッシュマニフェストは、HTML5で実装されたWEBアプリケーションをオフラインで実行できるようにするための仕組みだそうです。

ところで、オフラインWEBアプリケーションって自己矛盾した言葉ですよね。
WEBアプリケーションはサーバーにリクエストを投げて、レスポンスとしてHTML、Image、CSS、Javascriptといったリソースをダウンロードしてページを表示する仕組みなので、ネットワークに接続して利用することが前提という先入観を持ってました。

まぁともあれお勉強ってことでこんな本読んだり、こんなとこを読んだりしました。

じゃぁ、キャッシュマニフェストって?

単純にWEBアプリケーションをオフライン実行するには、必要となるHTML、Image、CSS、Javascriptといったリソースファイルが事前にローカルにキャッシュされている必要があります。
キャッシュマニフェストは、オフラインWEBアプリケーションが使用するリソースファイルをページのリクエストとは別契機でダウンロードしておき、リクエストの代わりにキャッシュを返す仕組みです。

キャッシュマニフェストを利用するには、マニフェストファイルと呼ばれるリソースファイルのURLをリストにしたファイルを用意し、このマニフェストファイルをhtmlタグのmanifest属性で指定します。

<!DOCTYPE HTML>
<html manifest="/cache.manifest">
<body>
…
</body>
</html>

するとこのページにアクセスした際、オンラインの間にオフライン実行に必要なリソースをダウンロードしてローカルにキャッシュしてくれます。
なお、マニフェストファイルはMIMEタイプtext/cache-manifest使って送信するので、Apacheの設定ファイルにAddTypeディレクティブを追加しく必要があります。

AddType text/cache-manifest .manifest

マニフェストファイルのリソースリストは以下のように記述しておきます。

CACHE MANIFEST
/hoge.css
/hoge.js
/hoge.jpg

オフラインWEBアプリケーションでもローカルにキャッシュしたくないリソースもあると思います。
マニフェストファイルにはそんなリソースを定義する構文がいくつか用意されてます。

マニフェストファイルは3つのセクションヘッダで分けられるようになっています。先のようにセクションヘッダがない場合は全体がCACHEセクションとして扱われます。

2012/02/06

スマートフォンブラウザの絵文字事情

こんにちは。tommy です。どういうわけか名前だけは時々出ていたと思うのですが、自分でエントリを書くのは初めてです。よろしくお願いします。
さて、DECOLOG では、ユーザーが投稿したテキストに含まれる絵文字を各キャリアに合わせて適宜変換して表示しています。携帯サイトでは当たり前にやっていることではありますが、DECOLOG の場合はそれに加えて携帯-スマートフォン間についても相互変換を実現しています。ここではそれをどのように実現しているかを 2 回に分けて解説していきたいと思います。
まず今回は、現状のスマートフォンのブラウザがどのように絵文字を扱っているのかを整理し、次回それに対して実際にどのような仕組みで対応しているかを説明したいと思います。

1. 携帯絵文字の仕様のおさらい

古き良き(?)携帯の絵文字の仕様については既に解説が既に多くありますので詳細は省略します。(きちんとした用語を使って)解説しているページとして、以下を挙げておきます。
http://coderepos.org/share/wiki/Mobile/Encoding
なお、スマートフォン上の絵文字の仕様を理解する上で必要となる知識は、
  • Shift JIS の空き領域 (85区〜120区) に絵文字が配置されている。具体的な位置 (コードポイント) はキャリアによって異なる。
    DoCoMo112区〜114区
    au101区〜103区
    107区〜110区
    SoftBank109区〜110区
    113区〜114区
    117区〜118区
    例えば「晴れ」の絵文字は、DoCoMo: 0xF89F, au: 0xF660, SoftBank: 0xF98B となる
  • 上記の絵文字を Unicode で表すためのマッピング定義が各キャリアで公開されている。これもコードポイントはキャリアによって異なるが、いずれも基本多言語面の私用領域 (PUA, U+E000〜U+F8FF) 上に配置されている。
    DoCoMoU+E63E - U+E757
    auU+E468 - U+E4E3
    U+E4E5 - U+E5DF
    U+E82E - U+E82F
    U+EA80 - U+EB1D
    U+EB1F - U+EB2D
    U+EB30 - U+EB8E
    SoftBankU+E001 - U+E05A
    U+E101 - U+E15A
    U+E201 - U+E25A
    U+E301 - U+E34D
    U+E401 - U+E44C
    U+E501 - U+E53E
    例えば「晴れ」の絵文字は、DoCoMo: U+E63E, au: U+E488, SoftBank: U+E04A
となります。まあコードポイントの詳細はともかく、見事に定義がバラバラなためキャリア間で絵文字をやり取りするためには変換が必要な事、また各キャリアの絵文字は1対1に変換できるわけではないことを押さえておけば良いと思います。

2. Unicode 6.0 の絵文字について

現在では各キャリアの絵文字のほとんどが公式に Unicode に収録されています。よって、対応するフォントデータがあれば PC 等携帯電話以外の環境でも絵文字を扱うことができるようになります。仕様策定の中心となったのが Google と Apple という今のスマートフォンのメインプレイヤーであるため、スマートフォンの絵文字を理解する上でこの仕様を押さえておくことが非常に重要となります。
特徴は以下のようになっています。
  • もともと Unicode にあった記号に割り当てられたものと、新たなコードポイントが割り振られたものが存在する。
  • 新たなコードポイントが割り振られた文字の多くは追加多言語面に配置されている。
  • 一部の文字 (国旗など) は結合文字によって表現することになっている。
  • 例示図形が絵文字っぽくないものも……(笑)
「晴れ」の絵文字は U+2600 に割り当てられています。
なお、各キャリアの絵文字との互換性は以下のようになっています。
  • 商標の問題がある文字は収録されていない (i-modeのロゴなど)
  • 各キャリアで共通の (ということにした) 絵文字は同じコードポイントに配置されている
  • 仕様策定の際に使われた、各キャリアが定義した PUA 上のコードポイントとの間の対応表が公開されている
    http://www.unicode.org/~scherer/emoji4unicode/snapshot/full.html
すべての携帯/スマートフォンが Unicode 6.0 の絵文字コードでの入出力に対応すれば、環境差を一切気にすることなく絵文字をやり取りすることができるようになるわけです。
※ もちろん現時点ではそのようになっていないのでこの記事が存在するわけなんですが。

3. iOS 4 以前の絵文字対応

iPhone OS 2.2 から SoftBank 絵文字が取り扱えるようになりました。ソフトウェアキーボードからの入力は、i.softbank.jp や SMS/MMS に限られますが、Webブラウザでもメールアプリで入力してコピー&ペーストすることによって入力・表示が可能です。
絵文字のコードポイントは SoftBank の Unicode マッピングに準拠しています。
またどこかのバージョンから、Unicode 6.0 で定義された絵文字のうち SoftBank 絵文字の範囲についても対応するフォントデータが用意されており表示が可能になっています。
ブラウザで絵文字を表示する方法
SoftBank の Unicode マッピングの絵文字コードを表示可能です。
UTF-8 で記述されたページの場合は、 UTF-8 のコードをそのまま記述できます。もちろん HTML の数値参照形式で記述しても良いです。「晴れ」なら 0xEE818A または "&#xE04A;" となります。
Shift JIS で記述されたページの場合は、HTML の数値参照形式で記述すれば良いです。「晴れ」なら "&#xE04A;" となります。
HTML のフォームから送られるコード
SoftBank の Unicode マッピングの絵文字コードが送られてきます。
UTF-8 で記述されたページの場合は、UTF-8 のコードがそのまま送られてきます。「晴れ」なら 0xEE818A です。
Shift JIS で記述されたページの場合は、UTF-8 のコードが SJIS コードに変換されて送られてきます。このコードは通常の SoftBank の Shift JIS コードとは異なり、いわゆる Unicode から CP932(Windows-31J) への変換ルールによって変換されたものとなります。「晴れ」なら 0xF08B です。

4. iOS 5 の絵文字対応

iOS5 で全てのアプリで絵文字入力が可能になると同時に、標準的に使われる絵文字のコードが SoftBank の Unicode マッピングから Unicode 6.0 の絵文字に変更されました。ドラスティックな変更を思い切って行うあたりがとても Apple らしく開発者泣かせではあります。
  • Unicode 6.0 の絵文字全てのフォントデータが用意され、SoftBank 絵文字以外の、DoComo/au に由来する絵文字も表示できるようになりました。ただし白黒表示です。仕組み上はカラー表示にできるはずなので、データの準備が間に合わなかったのかやる気がなかったのかどちらかでしょう。
  • ソフトウェアキーボードから入力される絵文字のコードも Unicode 6.0 のコードになります。
  • 今のところソフトウェアキーボードから入力できる絵文字は SoftBank 絵文字由来の文字種に限られているようです。ほかの絵文字は白黒で見栄えが悪いからでしょうか。
ブラウザで絵文字を表示する方法
Unicode 6.0 の絵文字コード、SoftBank の Unicode マッピングの絵文字コードのどちらも表示可能です。記述の方式は iOS 4 以前と変わりません。「晴れ」なら、UTF-8 で 0xE29880、0xEE818A、数値参照形式で "&#x2600;", "&#xE04A;" のいずれかとなります。
HTML のフォームから送られるコード
Unicode 6.0 の絵文字コードが送られてきます。
UTF-8 で記述されたページの場合は、UTF-8 のコードがそのまま送られてきます。「晴れ」なら、0xE29880 です。
Shift JIS で記述されたページの場合は、UTF-8 のコードが HTML の数値参照形式(10進)に変換されて送られてきます。これは PC のブラウザでは一般的な挙動です(よく考えるとおかしいんですけどね……)。これは Unicode 6.0 の絵文字コードから Shift_JIS へのマッピングが存在しないからでしょう。「晴れ」なら、"&#9728;" です。

5. Android の絵文字対応

Android では、絵文字は Google が定義した内部コードで管理されることになっているようです。実際のコードは上で触れた Unicode 6.0 の対応表で「Google」と書いてある列が該当します。特徴としては
  •  3 キャリア分すべての絵文字が Unicode の私用面 (第15面) 上に配置されている (U+FE000 - U+FEEA0)
  •  Unicode 6.0 で結合文字の組み合わせで表される絵文字も独立したコードポイントが与えられている
  •  Unicode 6.0 の絵文字とはほぼ 1 対 1 で変換できる
と、いかにも内部コードっぽい性質を持っています。「晴れ」の絵文字をこのコードで表すと U+FE000 となっています。
ただし Android 全体としての対応はここまでのようで、実際にこの絵文字を使うためには、

2012/01/30

Chefサーバーの容量不足になった時の対策メモ



はじめまして。hiroshiの部下、yoshitoです。


僕の主な仕事は、ここだけの話、hiroshiのゴキゲンをとることですが、稀にコードを書いたり、サーバーをいじったり、hiroshiの弁当を買ってきたりしています。


僕はとくに技術力が高いわけではなく、難しい事は他の方々がさくっとやってくれるので、僕はみなさんがゴキゲンよろしくお仕事ができるようにサポートしています。


技術的なものはあまり書けないと思いますが、社内の雰囲気をお伝えできればと思います。


しかし。
ネタが無いので、今回は技術ネタにしましたさーせん!!!!


:Chefサーバーのディスク容量が増えすぎて困ったですの巻

以前の記事で紹介されているように、DECOLOGではChefというサーバー管理ツールを使ってサーバーを管理しています。
今回は、そのChefサーバーがディスク容量不足になってしまった時のことを紹介します。


DECOLOGのサーバーは、Zabbixというサーバー監視システムで監視されていて、サーバーの状態がおかしくなるとメールを送ってくれたりします。


今回の場合も、
「Chefサーバーのディスク使用量が90%を超えましたよ」
的なアラートメールが届いて、問題が発覚しました。


調べてみると、chef.couchというファイルがHDDのほとんどを占めている状態。




Google先生に聞いてみると、Chefが使っているCouchDBというデータベースシステムのファイルだということがわかりました。


ChefサーバーはCouchDBを使って、クライアントの情報を管理しており、今回はそのデータベースのファイルが大きくなりすぎていたようです。

教訓:
Chefサーバーが容量不足になったら
CouchDBを疑ってみる!
の巻

CouchDBは、ドキュメント管理に特化したデータベースです。(ってここに書いてありました)


特徴として、データが更新されるたびに、新しくリビジョンを作成するという特徴があります。
つまり、過去のデータをまるっととっておくわけです。


Chefで管理しているクライアントの情報がアップデートされるたびに、
CouchDB上ではそのデータが複製されて、情報を更新すれば更新するほどDBは肥大化してしまいます。


そこで、Compactionの出番です。


Compactionは、CouchDBに保存されている過去のデータを削除する機能。
Compactionを実行しましょう!


CouchDBは面白くて、RESTfulなAPIでアクセスできるんです。
URLを叩けば、お手軽にDBを操作できます。

例えばDBの情報を見たければ、Curlコマンドを使って、

$ curl http://localhost:5984

とすると、

{"couchdb":"Welcome","version":"0.11.2"}

こんな感じで情報を取得することができます。

ChefのDBの情報は、こんな感じです。

$ curl http://localhost:5984/chef
{"db_name":"chef","doc_count":3875,"doc_del_count":99,
"update_seq":5139079,"purge_seq":0,
"compact_running":false,"disk_size":455128299901,
 "instance_start_time":"1287986483011849","disk_format_version":5}

らくちんですね。

ということで、早速Compactionを実行してみましょう。

$ curl -H "Content-Type: application/json" -X POST http://localhost:5984/chef/_compact
{"ok":true}

OK!

確認してみましょう。

$ curl http://localhost:5984/chef
{"db_name":"chef","doc_count":3875,"doc_del_count":99,
"update_seq":5139107,"purge_seq":0,
"compact_running":true,"disk_size":455131086952,
"instance_start_time":"1287986483011849","disk_format_version":5}

おおお!
compact_running:true
になってます。うまくいってそうです。

Compactionが終了すると、
compact_running:false
になります。


結果
 Before
$ df
 Filesystem           1K-blocks      Used Available Use% Mounted on
 /dev/sda2            564436604 481904116  53398212  91% /


 After
$ df
 Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda2            564436604  37030504 498271824   7% /

効果絶大。 めでたし めでたし。


で、隠してましたが実は僕が紹介した内容は
すべてここに書いてあります。
僕がよくtommyさんにRTFM(*1)って怒られますが、そういうことですね。


ちなみに、CouchDBの読み方はカウチです。

*1 : Read The Fucking Manualの略。「マニュアル読んで」的な。実際、大抵のことはマニュアルに書いてあります。




2012/01/24

EC2インスタンス管理の極意



2012/01/17

[新春特別企画]2012年 女子のスマホ事情徹底解析!!


どうもこんばんわ。目で負かし、心で伝える、変幻自在のエンターテイナーhiroshiです。

というわけで今回は新年特別企画ということでDECOLOGから見えてくる最近の女子のスマホ事情を予測してみました。

といってもこういうタイトルつけたらブクマが100ついたり100RT超えたりするかもしれないからつけただけで、実際はapacheの生ログからおもむろに100万行抽出して、そのユーザーエージェントから機種情報を整理しただけなのでかなりテキトーな数字です。そのテキトーな数字に僕のテキトーな分析を添えてあなたにお届けします。

iOSバージョン別

表1. iOSバージョン分布



図1.iOSバージョン分布グラフ

過半数が5以上です。個人的にはiTunesを使ったバージョンアップのハードルの高さはそれなりに高いと思っていたのでiPhone4Sとauの参入をきっかけに乗り換えた人が多いのかな、と考えましたが、iOS5がリリースされた10月以前のiPhoneのPVを鑑みるとiOS4からのアップデート組もそれ相応にいるように思いました。

Androidキャリア別


DoCoMo 57.41%
au    37.89%
SoftBank 4.66%

全体(docomo6割強,au3割,SB1割弱)の割合と比較するとauの多さとSBの少なさが目立ちますが、SBの少なさは特に説明はいらないでしょう。auが多めなのは嵐のおかげなのでしょうか。データがテキトーなのでいろいろ考えるのにはちょっと微妙な数字です。


Android OSバージョン別


表2. Android OSバージョン分布



図2. Android OSバージョン分布グラフ


2.3系がほとんどですね。まあこれはなんていうかそれ以上のコメントはないです。


Android 機種別ランキング
表3.Android機種別ランキング

Galaxy SⅡが2位以下を大きく引き離しての1位です。4位のGalaxy Sと合わせてブランド別でもGalaxyが1位のようで、現在のモバイルメーカー情勢を表した結果と言えるのかもしれません。

それを追うのがXperiaシリーズですね。ここで気になったのは、「そういや”女子向けスマホ”としてプロモーションされていたXperia-rayはどこぞ?」ということでした。探してみたところ45位と意外な位置に。個人的にも、昨年9月末に機種変更をしたさい、今の愛機であるIS05の対抗馬として考えた機種で、おサイフケータイさえ付いていればおそらくrayにしてたであろう、思い入れのある機種だったのでちょっと驚きでした。上位の機種を見ているとなんとなく昨年の夏休みにAndroidに乗り換えた方が多いように思いますので、発売時期が8月末ということで、夏休みの終わりごろだったのも1つの要因なのかもしれません。

その後、僕の愛機でもあるIS05などシャープ製の機器が目立ちますが、やはりここで注目すべきはIS04が4%あまりのシェアを持つことでしょう。様々な伝説を持つこの機種ですが、「HTML上のmailtoリンククリックでメーラーを立ち上げたときに、宛先アドレスの全長が30数バイト(正確なのを忘れた)を超えるとメーラーが宛先を拾わない」という地味すぎる仕様は他のメジャーな仕様に隠れてあまり知られていないかと思いますが、会員登録を始めメール送信ありきな機能が多いDECOLOGにおいては致命的な仕様だったため、日増しに増える問い合わせを背にその対応に追われたのも今では良い思い出です。

なお、現在ではケータイアップデートを行なっていただくことにより、この問題は解決しますので、もし万が一DECOLOGユーザーの方かつIS04をご利用の方がこちらをご覧になっていましたならば何卒ケータイアップデートをしていただきますようお願いいたします。


その他

IE
31875 
IE 9
20962
IE 8
3359
IE 7
2339
IE 6


これはナウいですね。StatCounter Global Statsを見ればこれがどれだけナウいことかがわかると思います。

ゲーム機

1695
Mozilla/4.0 (PSP (PlayStation Portable); 2.00)
1284 
Opera/9.50 (Nintendo DSi; Opera/507; U; ja)
764
Mozilla/5.0 (Nintendo 3DS; U; ; ja) Version/1.7455.JP
614
Mozilla/5.0 (PLAYSTATION 3; 1.00)
211
Opera/9.30 (Nintendo Wii; U; ; 3642; ja)
116
Opera/9.50 (Nintendo DSi; Opera/446; U; ja)
104
Mozilla/5.0 (PlayStation Vita 1.51) AppleWebKit/531.22.8 (KHTML, like Gecko) Silk/3.2


PSPはXperia-rayより多いです。

windowsモバイル

110
Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; FujitsuToshibaMobileCommun; IS12T; KDDI)
3
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Toshiba/X02T; Windows Phone 6.5)
1
Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile 6.5) T-01B


家電量販店の店頭でIS12Tは触ってみましたが、思っていたより操作性がよくて驚いた記憶があります。が。。。

それにしても見事1を叩き出したT-01Bはすごい。笑っていいともだったらタモさんストラップ10000個くらいもらえるレベルだと思います。



というわけで、いかがでしたでしょうか。繰り返しますがこのレポートはけっこうテキトーにとったデータを元に僕がテキトーにコメントしています。どれだけテキトーなのかは僕が統計学を学んでないのでよくわかりません。もしかしたら統計学的には冒頭に紹介したデータの取り方でもよいのかもしれませんが、そんなことはないでしょう。

また、なんとなくDECOLOGでの「機種別所有者」の割合っぽく書いてしまいましたが、正確には「機種別アクティビティ」の割合になると思います。

日常生活においてもエンジニアリングにおいても、数字を客観的に読む力というのは大事だと思うので、こんなお遊びでも実際やってみると良いトレーニングになると思います。お手元にウェブサーバの生ログがある方はぜひやってみてはいかがでしょうか。


最後に、データ抽出して整理してくれた上に僕にブログネタとして書く権利を譲ってくだすったtommy氏にはテキトーテキトーいったことを深くお詫び申し上げたいと思います。


それでは、みなさん、また会いましょう。



2011/09/27

るびまに寄稿しました。

ご無沙汰しております。意外と何も知らないことには定評のあるhiroshiです。

今回は簡便ながら、るびまにchefについての記事を寄稿しましたのでお知らせです。


Rubyist Magazine 0035 号


なんでも7周年記念だそうで、おめでとうございます!
こういった活動を7年続けるということはすごいことだと思います。

ちなみにDECOLOGはまだ5年目です。確か。

2011/06/27

第1回 DevOpsカンファレンスのお礼と話したことの補足



こんにちは。「ふいんき」と書いて「なぜか変換できない」の流れをやろうとしたらgoogle日本語入力だと余裕で変換できてしまい、沸き起こる複数の感情と戦っているhiroshiです。

去る2011/06/25(金)、DevOpsカンファレンスという勉強会でスピーカーをやらせてもらいました。そのお礼と、お話の補足をさせていただこうと思います。
勉強会での発表は社を代表した内容にしたつもりですが、このエントリは、けっこう個人的な想いを多めにしてますので、もし異論反論ありましたら@hiroshi19790209までください><。

去年末の「ZABBIX勉強会」以来のスピーカーで、あのときの参加者が60人くらい、今回も最初は80人くらいの募集だったから「実際くるのは応募人数の8掛けで60人くらいだろうから、このくらいの人数だったら経験済みだぜ!」と思って立候補したら、参加枠が120人まで伸びた上に当日もほとんどまんま120人近くの方が参加してきて、@marqsさん恐るべしな感じでした。

謝辞
@marqsさん、@kuwa_twさん、ぼくにしゃべらせてくれてありがとうございました!また呼んでください!
@さん、「こんな感じの内容であってるのかなぁ」、とビクビクしていたのですが、「カルチャー」の話のおかげで、気楽に話せました。気楽過ぎたかもしれません><
@riywoさん、僕もシャイボーイなのでちょっとしかお話できなかったです。またゆっくりお話したいです。
CAのみなさん、会場提供・設営などお世話になりました!
ご参加くださったみなさん、ご清聴ありがとうございました。あえて苦言を呈させていただくと、カイジをご存知のかたは「圧倒的閃き・・・!」のところでもっと笑ってもらいたかったです。


お話の補足
僕は今回、せっかくだから楽しいほうがよかろーと思ったのと、根がシャイボーイなのでああいう感じじゃないと恥ずかしくて話せないので、結果ネタっぽい感じになってしまいましたが、本筋を外したつもりはありません。

すべては
それはみんながよろこぶことなのか
というところにつながります。

そして、「みんな」とはユーザーのみなさん、クライアントさん、協業さんだけでなく、自分たちも含んでいます。「自分たち」です。「自分」じゃありません。でも「自分たち」の中には「自分」も含まれています。


僕たちは別に少数でやることがポリシーなわけでもなんでもないので、これはただの制約にしか過ぎません。
この制約の中でサイトを安定させるだけでなく、進化させていかなければなりません。

って、そんなのどこだって同じ、あたりまえの話だと思うんですよね。6人が多数か少数かは状況によって違うわけで、人手なんてどこももっと欲しいと思ってると思います。
だから(人手の募集はなんとかするとして)そんな中どうやったら一番アウトプットが最大化するか、っていう話なんだと思います。

それを僕達は、6人いるメンバーをDevに寄らせたりOpsに寄らせたりしてやっているつもりです。

アウトプットを最大化するためにはいろいろなアプローチがあると思います。
  • 作業の効率化(自動化)
  • タスクの取捨選択
  • アウトソース
  • 情報共有
  • etc..

それぞれの中で
  • やらなければいけないこと
  • やるべきなこと(ベキ論的な意味で)
を冷静に見極めなければいけないと思っています。

特にIT界はベストプラクティスと言われる「あるべき事例集」みたいなものがたくさん流通している気がします。
僕の心が汚れているせいだとわかっていますが、それらからはなんとなく「これをやらないから、おまえんところはデスマになるんだ!」的なオーラがただよっているように思えます。
※それを提唱している人や、推し進めようとしている人からでているオーラではなく、ただ単に僕の汚れた心がWeb上あたりからそういうオーラを感じているだけです。念のため。

が、それらはすべては考え方の話で、前提条件が揃わなければそれは最高の選択肢でありうることは少ないと思っています。
※提唱している人や、推し進めようとしている人は、考え方の話をしているはずです。

特に収益を得ることの手段としてのITであればなおさらだと思います。

たとえばテストは書くべきだと思います。テストは拡張性、保守性、可読性を高めます。確実に入るであろう今後の変更を考えたらやらない手はありません。でも、常に今後のことを考えた選択肢が正しいとは限らないと思います。「今、ここで、リリースできないと今後なんかない!」というノリの状況は少なくないと思っています。そんな状況ではTDDの採用は正しいとはいえない選択肢だと思います。(テストを書いても開発スピードが落ちないという人しかいない場合を除く)

「今、ここで、リリースできないと今後なんかない!」という考え方を理解しようせず「TDD!TDD!」とか言っている人は、ユーザーのよろこびに比べ、自分のよろこびにかなり重きを置いている、といえると思います。

そして、よろこびが偏った選択肢は、サービス全体として非効率な選択肢になります。


DevとOpsの対立みたいな話の具体例は残念ながら(?)うちにはありません。DevとOpsの分けがないから。
でもサービス開発にあたって、技術チームとディレクションチームといった分けはあります。この分けも、「同じものを作ってるけど、やっていることがちょっと違うチーム」といった意味ではDevsとOpsの分けとそう性質は変わらないと思います。

が、やっぱり対立みたいなものはありません。

きっとお互いのことを尊重できているからだと思います。

同じものを作っているのになぜ対立が起きるのか、はいろんなきっかけがあると思いますが、たぶん会話が足りないからじゃないかなと思います。

「わかるけど、そうコトはシンプルじゃないんだよ」と言う人もいるかもしれませんが、もうこれくらいしか推すアイデアがないんです。

同じサービスを支えているのに対立するって、おかしいじゃないですか。

会話といっても、酒場に行って飲むとかだけじゃないと思うんです。
なんだったら、DevsとOpsで短期交換留学みたいのしてもいいかもしれないです。

今回のDevOpsに参加された方しかわからないかもしれないですが、家族の理解の件ででてきたBBQの話もこれと同じノリだと思ってます。

ところで、家族の理解の話は、「アラートの監視体制は全員。深夜休日は当番制」といった体制から「家族の理解が得られるのか」といった質問がきたと記憶しており、BBQの提案をついしてしまいましたが、そもそもうちのアラート運用はそんなきっつい運用であると思っていません。

発信されるアラートの閾値や種類の出しワケなど、工夫を重ねていけば、少なくとも家族の理解の話になるような事態にはならないと思っています。
たとえば、ハード障害とかは無理ですけど、同種のアラートはきっちり対応していけば確実に減らせます。
@riywoさんもプレゼンの中でおっしゃっていましたが、それをきっちりやると、本当にメールを見ただけで障害の内容がだいたいわかるようになってきます。

なので、現在のDECOLOGではそのルールがキツイといった状況ではないと思っています。
少なくとも、うちのredmineの数あるタスクの中には「改善するべき」というチケットは切られていません。


冒頭で「みんなよろこぶの『みんな』には自分たちも含まれる」と言ったように、もし、このアラート運用が実際キッツいものであれば、全然ダメダメだと思います。
アラート受け取る側が多くの犠牲を払って成立するサービスなんてどうかと思います。

スライドでは「よろこびの最大化」といったことも書きましたが、これはみんなのよろこびを数値化したらもっとも大きい選択肢を採るということではないです。

最近マイケル・サンデル先生の「これからの「正義」の話をしよう」という本を読んでいますが、この中にオメラスという町の話がでてきます。
"オメラスではすべての人が飢え、貧困、病気もなく、幸せに暮らしているが、その幸せはたった一人の子供が窓もない地下に閉じ込められていることが前提となっている"
といった町です。

こんなの絶対ナシだと思っています。速攻で改善です。
あと、長期的な自己犠牲も禁止です。ダメ。


そんな選択肢を採らなくても、みんなの知恵で工夫を重ねることができれば、一時的にはつらいことはあっても、DevOps的な問題はだいたいなんとかなるもんだと思います。

そして、みんながよろこぶ選択肢を選び続けていれば、たった数人で数十億PVのサイトを運営していても、それなりにやりたいことができる環境が作れると思います。作れていると思います。今のところ。


ここまでの話の具体例とかは、どうしても自分が今WEBサービスをやっているので、その視点になってしまいますが、WEBサービスじゃなくても同じことだと思います。なんならITじゃなくても同じだと思います。

DevOpsのあとがき的な内容として、あっているのかだんだんよくわからなくなってきましたが、言いたいことは言った感はあります。ほんと、すみません。

最後に、会場設営のときのCAの方がたの若々しいふいんき(変換できるけど変換しない)はなんとも楽しそうな感じで「こういうふいんき(ry)が大事なんだよなーって思いました。今度飲みに誘ってください。ということをもって僕の挨拶とかえさせていただきます。
おわり。


2011/06/14

Chefでサーバのセットアップ・管理作業を楽チンにしよう~実践編その2~


前回紹介したスパムメールがさらに進化して「メアド変えたのでよろしく!」的な内容になってて、この人らPDCA実践してるわ―、と感心してしまったhiroshiです。

「3.レシピを書いたりする」の途中で終わった前回の続きです。

phpのインストールに必要なパッケージをインストールするところで終わっていましたので、次はphpのインストールです。

ここでphpをインストールする条件として
  • インストールされてない
  • 規定のバージョンと違う
  • 想定のコンパイルオプションと違う
場合にインストールし直してね、と定義したいと思います。

主なところはこんな感じです。

{chef-repo}cookbooks/php/recipes/default.rb
# バージョンのチェックを行い、バージョンが想定と違っていたらインストールを実行する
# サーバ稼働中の予期しないアップグレードを防ぐため、/usr/local/src/PHP_VERSION_CHECK_REQUIRED
# というファイルが存在する場合のみ処理が行われる。
buildtool_check_version "php" do
  action :check
  input '|/usr/local/bin/php -v'
  regex /^PHP ([0-9.]+)/
  version node[:php][:version]
  only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED"
  notifies :create, "cookbook_file[/usr/local/src/#{node[:php][:tarball]}]", :immediately
  notifies :install, "buildtool_make_install[php]", :immediately
  pecl_packages.each do |package_name, install_name|
        if node[:php][:extension][package_name.to_sym] then
        notifies :run, "execute[pecl-install-#{package_name}-force]", :immediately
        end
  end
end

# PHPのコンパイルオプションが変わっている場合はインストールを実行する
# サーバ稼働中の予期しない再コンパイルを防ぐため、/usr/local/src/PHP_VERSION_CHECK_REQUIRED
# というファイルが存在する場合のみ処理が行われる。
# ただしPHPがインストールされていない場合は必ずインストールが実行される。
file "/usr/local/src/PHP_CONFIG_OPTION" do
  content node[:php][:config_option]
  only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED || ! /usr/local/bin/php -v"
  notifies :create, "cookbook_file[/usr/local/src/#{node[:php][:tarball]}]", :immediately
  notifies :install, "buildtool_make_install[php]", :immediately
end

cookbook_file "/usr/local/src/#{node[:php][:tarball]}" do
  action :nothing
  source node[:php][:tarball]
  mode "0644"
end

buildtool_make_install "php" do
  action :nothing
  tarball node[:php][:tarball]
  srcdir "php-#{node[:php][:version]}"
  config_option node[:php][:config_option]
  notifies :restart, "service[httpd]"
end



4ブロックありますが、それぞれ以下の役割です。
  • バージョンチェック
  • コンパイルオプションチェック
  • インストールファイルの展開
  • インストール

最初のブロックのバージョンチェック部分からいってみます。
buildtool_check_version "php" do

とありますが、buildtool_check_versionは自前で定義したResourceです。
自前定義のResourceです。で終わるのもなんなので、ここでまた横道にそれてbuildtoolの説明をサックリしてみたいと思います。

buildtoolもcookbookのひとつです。
{chef-repo}/cookbook/buildtool/
に定義があります。

上述のbuildtool_check_versionについては、
{chef-repo}/cookbook/buildtool/resources/check_version.rb
actions :check
# バージョンチェックをする Resource の定義

attribute :input, :kind_of => String, :required => true
attribute :regex, :kind_of => Regexp, :required => true
attribute :version, :kind_of => String, :required => true
とresourcesに定義をし

{chef-repo}/cookbook/buildtool/providers/check_version.rb
action :check do
  begin
    versionstring = IO.read(new_resource.input)
    if new_resource.regex =~ versionstring
      version = $1
      if version != new_resource.version
        Chef::Log.info("Version check for #{new_resource.name}: expected=#{new_resource.version}, actual=#{version}")
        new_resource.updated_by_last_action(true)
      end
    else
      Chef::Log.info("Version check failed: '#{versionstring}' is not match #{new_resource.regex}")
      new_resource.updated_by_last_action(true)
    end
  rescue
    Chef::Log.info("Version check failed: #{$!}")
    new_resource.updated_by_last_action(true)
  end
end
とprovidersに実際の動作を記述します。

providersにあるnew_resourceにはresourcesで定義したattributeがあり、その中身は
buildtool_check_version "php" do
  action :check
  input '|/usr/local/bin/php -v' #ココ!
  regex /^PHP ([0-9.]+)/     #ココ!
  version node[:php][:version]  #ココ!
と、利用時に指定した値が入ります。

このあたりの構成が分かれば、check_version.rbが何しているかはrubyがわからなくてもなんとなくわかるかと思います。ぼくもrubyわかんないし。

ちなみに最後の
version node[:php][:version]
は

{chef-repo}cookbooks/php/attributes/default.rb
default[:php][:version] = "5.x.x"
default[:php][:tarball] = "php-" + default[:php][:version] + ".tar.bz2"
default[:php][:config_option] = "--with-libdir=lib64 \
~後略~
とここに書いた値が基本的には入ります。node[]で取れるの値ですが、設定できる場所は複数箇所あって優先順位があるので気をつけてください。詳しくは公式のこの辺を参照してみてください。

あと、気づいた人もいると思いますが、このbuildtool自体もRecipeの1つなのでbuildtool_check_versionをここで使うには、事前に
include_recipe "buildtool"
しておく必要があります。

と、横道にそれてたら、このブロックの最初の5行まで追えたので次は

only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED"
ですね。

これはこのブロックのコメントに書いてあるとおりです。

いやー、コメントっていいですね!

ちなみにウチで「変数宣言」とかいうコメント書いたらグラウンド10週か腕立て200回させられるので注意してください。しかもグラウンド探すところからですからけっこうキツイです。


あっ、もうだめ!今日はここまででカンベンしてください!


では、またまた続きは次回に!

2011/05/30

Chefでサーバのセットアップ・管理作業を楽チンにしよう~実践編その1~


昨日1日ケータイでアラートメール以外に受け取った唯一のメールを紹介します。
「
この前はありがとう!!久々メッチャ楽しかった~
みんながいる前だったからちょっと恥らっちゃったけど、2人っきりだったら私も同じ気持ちだったょ(はぁと

恥ずかしいけど・・・

次は2人っきりで会えませんか??

返事楽しみに待ってます(はぁと
」

「え?誰?誰?これ?」ってどんなに心当たりがないシチュエーションでも、とりあえずその可能性を記憶に見出そうとするのが男なんだなあ、と、スパム道の奥深さを知ったhiroshiです。

前回に引き続きChefについてです。

今回は、DECOLOGで実際に使っているrecipeや運用を紹介しながらの実践編です。
※この記事の元になるChefのAPIのバージョンはv0.9.12です。

その前に、いろいろ準備します。クイックスタートあたりを読んでクイックに準備しましょう。
この辺は環境依存も多いと思うし、僕やってないから華麗に通り過ぎて次行きます。

あと、このくらいの英語は翻訳サイトとか使わずに読めるようになっておいたほうが幸せになれると思います。逃げちゃだめだ!

さて、クイックに準備できたら始めます。

前回の記事でもちょっと触れましたが、chefはソフトウェア単位で扱うイメージです。
なので、今回はphpを題材にしてみます。

phpをchefで扱うまでの手順をおおざっぱに書くと
  1. cookbookを作る
  2. 必要ファイルを調達する
  3. レシピを書いたりする
  4. chef-soloでテストする
  5. cookbookをchefサーバにアップする
  6. gitにコミットしとく
という感じでしょうか。ウチの場合。


1.cookbookを作る
まず、cookbookを作ります。chefで管理するソフトの数だけcookbookを作っていくことになります。

無理やり料理に当てはめると、
この料理人(chef)は食材(ソフトウェア)ごとにレシピ(recipe)をまとめた料理帳(cookbook)を管理しているようです。

さあ、うまいこといったつもりになったところでさっそく実行です。
rake new_cookbook COOKBOOK=php
※ただし「knife cookbook create」を使えと怒られます。が、knifeコマンドはあらかじめセットアップをしておかないと正しく動作しないので、今回はこれで。

とします。すると{chef-repo}/cookbook/php配下にじゃららーと以下のようなディレクトリとファイルが作られます。
attributes
definitions
files
libraries
providers
recipes
resources
templates
metadata.rb
README.rdoc
いらないものもたくさんあるので、いらないことに気づいたタイミングで消したらいいと思います。

ここはこれで終わりです。


2.必要ファイルを調達する
本当にphpだけだったら、php-5.3.x.tar.bz2とphp.iniだけあればいいかと思います。

php-5.3.x.tar.bz2は
{chef-repo}/cookbook/php/files/default
直下に置いておきます。

php.iniはphp.ini.erbという名前にして
{chef-repo}/cookbook/php/templates/default
直下に置いておきます。

いったん終わりです。

3.レシピを書いたりする
ここに書いていきます。
{chef-repo}/cookbook/php/recipes/default.rb

さっきから各所で「default」が目につきますが、細かいことはあとで気にすることにして、ここはおとなしくdefault.rbに書いていきます。

さて、どこから書いていくかですが、その前にchefがどういうものかおさらいします。

chefは
「手でやってたセットアップ手順をrubyで記述すると、定期的にその手順の結果の状態になっているかチェックして、そうなってなければその状態にしようとする」
ツールです。

なので、手でやってた手順をそのまま記述していくことになります。

chef導入以前、DECOLOGではphpをシェルスクリプトでインストールしてたのですが、その内容は大まかにいうと
  • apacheをソースからインストール
  • phpをソースからインストール
  • pearのライブラリいろいろいれる
  • peclのライブラリいろいろいれる
といった感じでした。apacheありきです。

なので、apacheのインストールからやることになりますが、apacheも1つのソフトウェアなのでcookbookから作っていくことになります。というわけで、今回はすでにapacheのcookbookはできあがっている前提で進めます。


まずはapacheありきのphpなのでapacheのセットアップを行います。
include_recipe "apache"
こんな感じでapacheのレシピを発動させます。

次に、phpのconfigオプションで使うことになるrpmパッケージをインストールしておきます。
package "curl-devel"
package "libjpeg-devel"
package "libpng-devel"
~後略~

ここででてくるpackageというのはchef側で用意してくれている便利コマンドみたいなもので、「Resource」と呼ばれています。

<Resource>
Recipe内で行う操作を抽象化して宣言文ぽくしたもの。パッケージ管理、デーモン管理、ファイル管理、コマンド実行などが用意されている。
※前回のエントリ参照

Resourceはいろんなのがあるのでhttp://wiki.opscode.com/display/chef/Resourcesに目を通しておくとよいと思います。

DECOLOGの場合はOSがCentOS環境なので、特に何も指定してなければyum installしてくれることになります。



・・・ああっ、もうガッツが足りなくなってきました。まだまだ途中ですが、最後まで書こうとするとこの倍くらいになってしまうので続きはまた次回にさせてください><


よろしくお願い申し上げます。

2011/05/23

Chefでサーバのセットアップ・管理作業を楽チンにしよう~構成編~


どうもhiroshiです。こんなに更新が早くてすみません。

今回もChefについてです。

前回の選定編に続いて、今回はChefの構成を見てみます。もちろんこれも「tommy report in Oct. 2010」からの抜粋です。

5/26 追記)この記事はv0.9.12に基づいてます。

Chefの構成の概要図
こんな感じです。


ツール群
<chef-server>
情報を集約して管理するサーバプロセス。各ClientとはJSON/RESTスタイルで通信する。

<chef-client>
設定を適用する各マシンにインストールされるデーモン。定期的にchef-serverをポーリングして、その内容に従ってレシピを実行する。

<chef-solo>
サーバ無しでレシピを実行するツール。

<knife>
chef-serverに登録されている情報の取得・変更を行うツール。切り刻むよ。

<webui>
chef-serverのWebインターフェース。なんか上手くログインできないので無視。


ということでうちではwebui使ってません。「それは大いなる損失だよ!」ということがありましたら是非教えてください。


主な構成要素
<Cookbook>
Recipe,Template,Attributeなどをひとまとめにしたディレクトリ。ソフトの種類毎に作るのがお約束ぽい。

<Recipe>
実行内容の定義本体。RubyのDSLで記述する。

<Resource>
Recipe内で行う操作を抽象化して宣言文ぽくしたもの。パッケージ管理、デーモン管理、ファイル管理、コマンド実行などが用意されている。


<Template>
設定ファイルを生成するためのテンプレート。中身は eRuby。


<Attribute>
環境依存の処理を吸収するための変数。


<File>
バイナリファイルなど、単にコピーして使うためのファイルを置くところ。


<Metadata>
Cookbookの説明とかのメタ情報。


<Role>
複数のRecipeをまとめて「役割」として定義するためのもの。


<Node>
chef-serverから見た管理対象のマシンのこと。


<run_list>
Nodeに対して適用するRoleやRecipeを指定したリスト。


<Client>
chef-serverにアクセスするツール類のこと。


なんやらいっぱいありますが、すぐ慣れます。寄生獣の後藤も「何事も慣れだ」と言ってました。これ、言うの2回目ですね。
とにかくRecipeです。普通7割くらいRecipe書くのに時間使います。
TemplateとFileは使い分けが若干微妙なところがでてくるかもしれませんが、書き換え可能なファイル(つまりテキストファイル)はTemplate、そうじゃないのはFileというルールでやってます。

例えばapacheなら、http-2.2.xx.tar.bz2はFileだし、httpd.confはTemplateの下に置いとくって感じです。


Attributeについて
レシピで使える属性値は大きく2種類に分かれます。
  1. Nodeの属性値。Nodeから収集した様々なパラメータ(IPとか)がツリー状のデータとして取得できるので、レシピで条件分けに使う。またknifeコマンドでも参照できる。
  2. 自前で設定する属性値。
    1. デフォルト値はCookbookのattributes/*.rbで定義する。
    2. RoleやNodeに対して、デフォルトの設定値を上書きする値を設定できる。これで一部のマシンだけ別設定みたいなことが実現できる。
1についてですが、具体的にはこんな感じです。
$knife node show {domain}
~前略~
    "platform_version": "5.x",
    "fqdn": "hoge.example.jp",
~中略~
    "domain": "xxx.xxx.xx",
    "os": "linux",
    "idletime": "13 days 13 hours 28 minutes 20 seconds",
    "network": {
      "default_interface": "eth0",
      "interfaces": {
        "lo": {
          "flags": [
            "UP",
            "LOOPBACK",
            "RUNNING"
          ],
          "addresses": {
            "::1": {
              "scope": "Node",
              "prefixlen": "128",
              "family": "inet6"
            },
            "127.0.0.1": {
              "netmask": "255.0.0.0",
              "family": "inet"
            }
          },
          "mtu": "16436",
          "encapsulation": "Loopback"
        },
        "eth0:xxx.xxx": {
          "flags": [
            "UP",
            "BROADCAST",
            "RUNNING",
            "MULTICAST"
          ],
~後略~
該当ホスト上でコマンド打ったら取れるような情報は全部入ってるんじゃないでしょうか。

例えば以下はapacheのconfファイルですが、まいど自FQDN名を設定するところがありますが、そんなときにこんな感じで使えます。
# Server port for sending active checks
ServerRoot      "/usr/local/apache"
ServerName      <%= node[:fqdn] %> ←ココ!!

2について、たとえば基本的にapacheのバージョンは2.2.xxを利用する、ということにします。そういう場合、cookbook/apache/attributes/default.rbに
default[:apache][:version] = "2.2.xx"
と書いておいて、apacheのrecipeに
buildtool_make_install "apache" do
  action :install
  tarball node[:apache][:tarball]
  srcdir "httpd-#{node[:apache][:version]}" ←ココ!!
  config_option configure_option()
  not_if {check_compile_setting}
  notifies :create, "template[/etc/httpd/httpd.conf]"
  notifies :restart, "service[httpd]"
end
と書いておけば、基本的にはこの2.2.xxのapacheをインストールさせることができます。

「そんなんじゃ、わかんねーよ!」って思った方、、、、ですよねー。そうだと思います。。
とりあえず、現時点ではなんとなく、で通り過ぎていただければ幸いです。。

ちょっと今回はこのあたりで切り上げます。

次回は、適当なcookbookを例に取って説明ができたらいいな、という「実践編」を書きたいと思いますが、その際、またこの「構成編」の内容をちょくちょく振り返りつつになる気がします。

chefって、一回やってみないと全体像が見えにくいんですよねー。ぼくは3回くらいやってようやく見えてきました><


というわけで、最後に女子力上げたところでまた次回にさせてください~。

2011/05/16

Chefでサーバのセットアップ・管理作業を楽チンにしよう~選定編~



>>hiroshiの母でございます。この度は(ry

最近お会いしたエンジニアの方から「他社さんのブログとかは規模や難易度が凄過ぎて真似できないことが多いんですが、DECOLOG TECH BLOGは僕らでも利用できるレベルのネタが多いので助かってます!」と言われて今まで感じたことのないキモチになったhiroshiです。

今回はChefのお話です。

去年の10月くらいの話だったんですが、「あっちのwebサーバとこっちのwebサーバ、設定微妙に違くね?」みたいなことが発覚し(いや、前から知ってたけど)、それ自体はその時点で大きな問題ではなかったんですが、「このままだといつかなんかやるよね」と危機感を覚え、システムの構成管理ができるようなツール探しをしました。

つまり、Chefとは上記ような問題点が解決できるツールで、パッケージやミドルウェア(って同じ?)を定義した状態に保ってくれるツールです。「定義した状態に保つ」ということは、定義したソフト等が入っていなかったらインストールしてくれたりするのです!!

オープンソースなものだと他にはPuppetというのがあります。

かねてよりPuppetの存在は存じていたので「じゃあ、噂のPuppetがいけそうか調べてみるかー」といった感じでミツバチの銀の弾丸tommyが調査担当になりました。鉄砲作成を依頼するとキャノン砲ができあがるのがtommyさんです。Puppetを調べてもらったらChefを見つけてきてPuppetと比較してくれました。

以下、「tommy report in Oct. 2010」です。

共通点

  • サーバクライアント構成。構成情報をサーバマシンで一括管理して、各クライアントマシンに配信する。
  • マシンに役割(WebサーバとかDBサーバとか)を設定して、その役割に必要なアプリのインストールとか設定ファイルなどをひとまとめにして管理できる。
  • マシンごとの設定の差異などは変数として管理できる。
  • 設定ファイルはテンプレートから生成できる。マシンごとに一部の値を変えるとか。
  • LDAP連携。LDAP上で各マシンの役割を定義できるみたい。
  • Subversion/Git連携(詳細はまだよく調べてない)。
  • Ruby製。



比較表



※間違っている部分もあるかもだし、当時まとめたものなのでもう変わっているところもあるかもです。

なぜChefにしたか
機能的にはそれほど差はないようでした。
決定打となったのは
tommy「ぶっちゃけChefの方が設定書きやすそうなのでだんぜん好印象ですねー。」
というコメントでしょうか。

その当時の時点で管理対象サーバは400台を超えていたし、稼働しているミドルウェア等もたくさんありました。だから、設定が書きやすいという点は重要なところです。
また、最初にChefの調査導入というフロンティア役を担ったtommyが「設定書きやすそう」っていうんだからChefだね!という感じで決めました。


というわけで今回はChef導入のきっかけのお話でした。次回以降は、Chefの構造や実際の設定例などについて書きたいと思います。

では!

2011/04/11

arpingのススメ

>>hiroshiの母でございます。
このたびは、hiroshiがブログの更新を怠ってしまい、皆様には大変ご迷惑を おかけしております。
深くお詫び申し上げます。
~中略~
どうぞ皆様、hiroshiを暖かく迎えてやってくださいまし。
本当は良い子なんです。

というわけでご無沙汰しておりますhiroshiです。技術ネタは大変ご無沙汰な感じになっておりまして、これはよくないな、ということでtommyのネタ在庫から多忙な本人に代わり、まーひーな僕がちょいと拝借して代筆させていただきます。

さて、今回は最上層でリクエストを受け付けているリバースプロキシ用途のサーバを移動させたいケースなどにおけるTIPSです。

DNSだけ切り替えてもクライアントからリバースプロキシまでの経路のN/W機器のキャッシュはガガッと切り替わってくれないので、元サーバにはリクエストが来続けます。ならば、いっそIPアドレスを移動先のサーバに移動してしまいたくなります。

ReverseProxyA(xxx.xxx.xxx.xxx)→ReverseProxyB

そのときに、上流のルータの ARP キャッシュが残ってると、パケットの飛び先が rev-proxyA の MAC アドレスのままになってしまってしばらく通信ができなくなってしまうことが予想されます(数分〜数時間)。

一方、VRRP で IP を切り替えるとそんなことは起こらないので、VRRP がやってることを手でやれば即時に切り替わるはずです。

ということでちょいと調べてみたら、「Gratuitous ARP」という ARP パケットを投げてやるというのが解でした。


ぐぐると send_arp というコマンドを使った例がいろいろ出てきますが、標準コマンドではないのでインストールが必要です。でも最初から入っている /sbin/arping コマンドでも出来るらしいです。こっちの方がいいですね(こんなコマンドあったのか……)。

IP アドレスを移動した先のマシンでこれを実行すればいいわけですね。

# /sbin/arping -q -A -I eth0 -c 1 (IPアドレス)

ARP ならパケットフィルタで ping を落としてても使えるし、 IP 重複のチェックとかにもping よりこっちの方が有用な気がします。


では!



2011/03/02

仲間大募集中その2-募集要項

こんにちは。hiroshiことTECHチームの採用担当をしている諸富です。
お久しぶりのブログが技術的じゃないもので恐縮です。

かねてより僕たちはエンジニアを大募集していますが、募集要項をきちんと明示していなかったので、ここに募集要項を公開いたします。



募集要項

<勤務地>
東京本社 東京都渋谷区恵比寿南(転勤なし)


<勤務時間>
フレックスタイム制 コアタイム10:00~16:00(所定労働時間8時間)、休日:土日祝日、夏季休暇、年末年始休暇、有給休暇、その他特別休暇


<給与>
年収400万~1000万を想定(経験・能力・前職での給与を考慮の上、規定により応相談)、賞与年2回、昇給年1回


<福利厚生>
健康保険、厚生年金保険、雇用保険、労災保険、定期健康診断、社外研修・勉強会参加サポート(業務時間内、参加費負担)、業務にかかわる書籍代サポート、交通費支給(月額50,000まで)


<その他>
遠方にお住まいの就業希望の方については、引越し費用などのサポートを目的とし、入社支度金を支給(審査あり)、スマートフォン貸与


<雇用形態>
正社員


<応募職種>
プログラマー、インフラエンジニアがわかりやすいキーワードだと思っていますが、システムに関わるエンジニアであれば、まずはお話してみたいです。


<求める人材像>
こちらをご参照ください。


<応募方法>
こちらをご参照ください。



なお、上記は基本的に中途採用を意識していますが、エンジニアという職種は、優れたスキルを持つ新卒の方が少なくない職種だと考えています。これまでに培った「何か」がある方は新卒でもなんでも、ぜひアクセスをお待ちしています。







2011/02/08

redisの実用例。redis速いよredis


こんにちは!hiroshiです!

今回は、最近DECOLOG界隈で大ブームのredisについて、その利用用途や導入方法についてお話ししたいと思います。

今回のお話と関連する過去エントリに以下がありますので、こちらに目を通していただいた上で本エントリを読んでいただくと分かりやすいと思います。



…と、これまでのエントリからは実運用できてるのかどうか微妙なタッチになっているかもしれませんが、結論からいうと実運用できてます!

「redis導入後にトラブル発生、そのレポート」ではTTLを設定した場合にうまくいかないケースがあったのですが、TTLなしのデータでは特に問題なく運用できました。



現在のredisの利用用途


今のところ以下の用途ですね。
  • カウンターデータ
  • 広告配信データ
  • ユーザーのアクティビティ統計データ


最初に導入してみたのは、広告配信データでした。

なぜこれを選んだか、ですが、MySQL以外のツールを探し始めたきっかけが、readよりもwrite負荷、つまりmaster負荷が原因でスループットがあがらない処理がいくつかあり、そこをなんとかしたかったんです。

shardingすれば済むし、実際にそうやって対応していましたが、処理内容(カウントアップするだけ)や保持しているデータ(前述のデータはkey-value形式なデータで、valueは数値のみ)を考えると、なんとも「サーバがもったいない。富豪エンジニアリングになってしまってるなあ。」という感を強く持っていました。
※「富豪エンジニアリング」は必ずしも悪だとは考えてないです。念のため。

余談ですが、金をかければだいたいのことが解決するわけです。なので技術陣は他所からの要求をただ実現するだけでなく「低コスト」でやってナンボだと思っています。「サーバ増やせばできるよ」という結論も多々あると思いますが、「サーバを増やさずできる」方法を常日頃から考えておきたいところです。

話を元に戻します。前述の課題となっていたウチのデータ群では広告配信データがもっとも更新負荷が高いデータだったので、「ここがイケれば全部イケル」ということからここを選びました。

更に広告配信データは「DECOLOGでのMySQL Archiveエンジンの使い方」と同じスキームでやっていました。つまり

  1. archiveエンジンを使ってとにかくinsert
  2. 定期的にテーブルスワップし、スワップしたテーブルに対して集計プログラムを走らせる
  3. で、その結果を集計DBに格納


といった按配です。

広告配信データは、1日に1回のテーブルスワップだと半端ないデータ量になってしまうのと、運用側としてもimpressionなどの集計データの本日分が参照できないのはリアルタイム性にかけすぎるので、テーブルスワップのサイクルは1時間に1回でやっていました。

なので、「ここがイケれば全部イケル」という理由に加えて、集計スパンを既存に合わせれば、仮に導入試験中にredisが原因で未集計のデータがぶっ飛ぶようなことがあっても「MAX1時間分のデータがパーになる」というのが想定される最大の被害規模であり、それだったら基本的に内部以外に迷惑かけずに済む、という算段もありました。



設計


設計ってほどのことでもないですが、1台でどこまでいけるのか?というのを試したかったのでredisサーバは1台のみです。仮にぶっ壊れたりしたとしても、プログラムをを2,3行コメントアウトしてリリースすればよいですし。

ところでredisにはdatabaseという概念があります。これは数字で指定する、ちょうど配列の添字みたいなものです。この単位でデータは管理されています。なので、データのflushもこの単位でできます。で、これは上限があるのかどうかわからないんですが、任意の数を指定できます。この添字的なものをdbidと言うっぽいです。

データ構造のイメージとしてはこんな感じ。
[0] {
array(key1 => value, key2 => value, key3 => value ・・・)
},
[1] {
 array(key1 => value, key2 => value, key3 => value ・・・)
}
:
:
[n] {
 array(key1 => value, key2 => value, key3 => value ・・・)
}

※設定ファイルに指定した数-1

広告は1時間ごとに集計したいので、この仕様を利用して、databaseの数を24にしておきます。こうするとDBは0~23の範囲を指定できます。

プログラムでも、この仕様に合わせる形を取っておきます。
<?php
class   My_Redis_AdViewLog extends My_Redis {
    const   KEY_PREFIX = "ad_view";

    function    __construct($last_hour=false) {
        // redisのDBは時間(h)と同期をとる。つまり0~23の範囲をとる。
        $time = strtotime(($last_hour ? "-1 hour" : "now"));
        $index = date("G", $time);

        parent::__construct(REDIS_SERVER_AD_VIEW, $index);
    }

    function logging($ad_id, $carrier) {
        $this->increment($ad_id."/".$carrier);
    }


これはいわゆるDBクラスですね。
parent::__construct(REDIS_SERVER_AD_VIEW, $index);

の$indexがdbidです。

現在時間(h)をdbidとして扱っているため、10時のデータはdbid=10のところに入っているわけです。

KEY_PREFIXは、keyの一部になります。ベースクラスで、このKEY_PREFIXを元に
{ENV}/{KEY_PREFIX}/{KEY}
というkeyを組み立てるようにしてあります。

$this->increment($ad_id."/".$carrier);

のincrementですが、redisにはincrというコマンドがあり、これがチョー便利です。
valueが数値だった場合に$deltaの数だけインクリメントしてくれる、というシンプルなものなのですが、何が便利って該当するkeyがない場合にエラーとしないで、key=$deltaを自動的に作ってくれるんです!

「キーが存在すればupdate、存在しなければinsert」みたいなコードを書かなくていいのはすごく気持ちがいいです。

こんな感じでデータを収集していきます。

24時間経つと、dbidが重複することになってしまいますが、1時間ごとにデータ集計バッチが走るので、そこで現在時間-nのDBをflushする、というコマンドを入れて対応しています。



導入に当たって


新しいものを導入するときのウチの基本なのですが、いきなり切り替えず、既存ロジックと平行させて導入します。
かつ、100分の1で新しい処理を通るようにする、みたいなコードを入れて、グラフを見ながら徐々に100%にあげていきます。

100%になれば、既存ロジックの集計結果と同じになるはずなので、それを確認します。
広告集計結果をストアするsummaryというテーブルがあるとすると、summary_testというまったく同じスキーマのテーブルを用意します。
redisで取得したデータの集計データは、summary_testに格納します。あとは、確認するだけです。

で、これがけっこうあっさりうまくいっちゃったので、苦労話とか特に無いです。いや、これをやること自体がそれなりに苦労するんですけど。

しかもこれまで7台でやっていたものを1台で受けきってかれこれ数ヶ月問題も起きていません。


感想


いやー、7台が1台になっちゃいました!
正確にいうと、7台で構成されていた既存DBは、actionlog、ランキングデータ、広告配信データが格納されており、いずれもそれぞれ別のredisサーバに分けられたので「7台が3台になった」が正しいですね。ただ、こう書くと約半分程度なので、ちょっとインパクトに欠けるかもしれません(?)が、この例ではないところで4台が1台にできたのは確認できています。

実際は、valueにオブジェクトも格納でき、それを利用しているところもあるのですが、がっちり使っているのはvalueに数値を持ち、カウントアップしていく性質のデータを対象としています。

っていうか、そういうデータだったらかなり最強の部類に入るのではないか、と思っています。

また、redisの開発はかなり活発です。あまりにも活発すぎて燃え尽きないか、と心配になるくらいです。
DECOLOGが使っているphpクライアントのphpredisの開発も活発です。

こういうのは多くの人が使えば、今後ももっともっと活発に活動し続けてくれると思うので、みなさん奮ってご利用ください!!

see also:「仲間大募集のお知らせ」

ではでは!

2011/01/31

Hadoopのslaveの増やし方、減らし方の続き


xperiaにskypeをインストールしたらバッテリーが1日持たなくなってしまいました。
今は充電ケーブルに行動範囲を縛られてるleonです。

今回は、前回の続き「ご紹介したHadoopサーバーの増やし方、減らし方」のハマり話です。

ハマったのはincludeファイル、excludeファイルの記述する方法です。

答え、先言っちゃいますね。
includeファイルと、excludeファイルにはサーバーのFQDNを記述しなきゃ行けなかったんです。

最初、slavesファイルと同じホスト名を記述したんですが、Hadoopサービスを再起動するとslaveサーバーが接続されないんです。

「hadoop-hadoop-jobtracker-hdmaster.log」を見ると以下のようなログが出てました。
2010-10-20 14:05:35,769 INFO org.apache.hadoop.ipc.Server: IPC Server handler 15 on 9001, call heartbeat(org.apache.hadoop.mapred.TaskTrackerStatus@51c293f8, true, true, -1) from 192.168.0.xxx:44035: error: org.apache.hadoop.mapred.DisallowedTaskTrackerException: Tasktracker denied communication with jobtracker: tracker_hdslave1.domain.jp:localhost.localdomain/127.0.0.1:44034
org.apache.hadoop.mapred.DisallowedTaskTrackerException: Tasktracker denied communication with jobtracker: tracker_hdslave1.domain.jp:localhost.localdomain/127.0.0.1:44034
    at org.apache.hadoop.mapred.JobTracker.heartbeat(JobTracker.java:1246)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:481)
    at org.apache.hadoop.ipc.Server$Handler.run(Server.java:890)
はて?jobtrackerからクラスタへの接続が許可されないとな?includeファイルが読めてない?
Haddop設定ファイルのdfs.hostsプロパティとmapred.hostsプロパティの値を見直しても間違ってませんよ。って感じであれこれ試行錯誤しました。

で、ホスト名をFQDNにしてみたらなんとslaveサーバーと接続されるじゃないですか。

前回説明した通りmasters/slavesファイルとinclude/excludeファイルは役割が異なる。役割が異なるから設定も異なるってことなんでしょうね。
masters/slavesファイルはHadoop起動制御のシェルスクリプトが参照し、include/excludeファイルはHadoopのjavaプロセスが参照しています。

これ、わかんないですよねー。

あと、masterサーバーとslaveサーバーのネットワーク接続状態を確認したところ、hadoopのjavaプロセスはIPv6でバインドされてました。

$ sudo netstat -plten | grep java
tcp        0      0 ::ffff:192.168.0.5:9000     :::*                        LISTEN      220        2464200901 8483/java
tcp        0      0 ::ffff:192.168.0.5:9001     :::*                        LISTEN      220        2464201589 8766/java
(省略)

弊社のネットワークはすべてIPv4で構築してます。なので、HadoopもIPv4でバインドするように変更しました。具体的には、hadoopコマンドのスクリプトを編集して明示的にIPv4で接続するしました。

258 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.root.logger=${HADOOP_ROOT_LOGGER:-INFO,console}"
    259 if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
    260   HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH"
    261 fi
→  262 HADOOP_OPTS="$HADOOP_OPTS -Djava.net.preferIPv4Stack=true"
    263
    264 # run it
    265 exec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH" $CLASS "$@"
262行目の1行が編集した部分です。

hadoopを再起動して、ネットワーク接続状態を確認すると・・・

$ sudo netstat -plten | grep java
tcp        0      0 192.168.0.5:9000            0.0.0.0:*                   LISTEN      220        2480561580 29797/java
tcp        0      0 192.168.0.5:9001            0.0.0.0:*                   LISTEN      220        2480562441 30112/java
(省略)

IPv4でバインドされてますね。OKです。

ではでは