Quantcast
Channel: サイバーエージェント 公式エンジニアブログ
Viewing all 161 articles
Browse latest View live

cocos2dを使ったアプリ開発

$
0
0

はじめまして。
サイバーエージェントでスマートフォンアプリエンジニアをしています、甲斐と申します。
私は2011年5月にサイバーエージェントに入社致しました。
入社して初めて手がけた開発がiOSアプリ「つりポン!by アメーバピグ」です。

前職では主に携帯端末のプリインアプリやミドルウェアなどの組み込み開発に携わっておりました。
その時にAndroid開発経験はありましたが、iOSアプリ開発は未経験でした。
また「つりポン!by アメーバピグ」は"cocos2d for iPhone"を採用して開発しています。
その為、iOS開発言語のObjective-C、iOS開発技術 、 cocos2d for iPhoneを習得して開発する事が初めての挑戦となりました。

cocos2dは社内でも「興味はあるけど、触る機会がなかなかない…」といった話を聞くことがあります。
確かに開発技術として採用して触らないと、なかなか覚える機会はないと思います。
そこで、今回はcocos2dを使ったアプリ開発について「つりポン!by アメーバピグ」の開発を例に簡単にご紹介したいと思います。

まずは開発したアプリと"cocos2d for iPhone"についてご紹介致します。

「つりポン!by アメーバピグ」とは
自分のピグが登場する新感覚つりゲームです。
東京湾、瀬戸内海、オホーツク海、有明海、日本海の5つのステージがあり、合計100匹を超えるさかなが登場します。各ステージにはヌシが潜んでいます。
$サイバーエージェント 公式エンジニアブログ

「cocos2d for iPhone」とは
2Dゲームを構築する為のフレームワークです。
(※以後、「cocos2d」と記載)

cocos2dの特徴
・オープンソース
  オープンソースなので無償で手に入れる事ができます。

・ゲーム開発に必要な環境が集約されている
  cocos2dにはゲーム開発に必要とされる要素が搭載されています。
  ・高度なグラフィック処理を行うOpenGL ES
  ・ゲーム表現に必要となる物理エンジン、Chipmunk、Box2D

・情報交換できるコミュニティがある
  http://www.cocos2d-iphone.org/forum/
  $サイバーエージェント 公式エンジニアブログ
  
  ※Twitterの日本語ファンアカウントもあります。
  ファンアカウント

「つりポン!by アメーバピグ」にcocos2dを導入した理由
・objecttive-Cで書かれている
cocos2dはiPhoneアプリ開発言語であるObjective-Cで書かれています。
私にとっては初めて触れる言語だったので特に感じませんでしたが、
iPhoneアプリ開発者がゲームアプリを作りたいと思った時にObjective-Cを習得していれば
すぐに取りかかれるフレームワークがあるというのは魅力的だと思います。

・Flasherがアプリ開発に取りかかりやすい
開発チームの中にはFlasherが2名いました。
cocos2dの書式がActionScriptに似ていて、Flasherがアプリ開発に取りかかりやすいのでは?という意見があり「つりポン!」で採用することになりました。

・ゲーム表現に必要な物理エンジンを搭載している
"cocos2dの特徴"でも挙げた通り、cocos2dには2つの物理エンジンが搭載されています。
iPhoneアプリに組み込める物理エンジンは何かと探すより、すでに搭載されているフレームワークがあるというので使わない手はないですね。


次に、cocos2dの基本構成と実装について触れていきます。


cocos2d基本構成
cocos2dではアプリを構成する画面を下記4つの基本要素を使って実装しています。
(※ここではcocos2dの画面構成をする上で必要となる基本要素についてあげています。アニメーションやエフェクトといった部分については触れません。)

(1)Director
cocos2dフレームワークの中心部となります。
主にシーン(画面)管理、ゲームの一時停止・再開・終了、ビューへのアクセス等重要な役割を担っています。

CCDirectorはシングルトンで、ゲーム中は常にメソッドを介してオブジェクトにアクセスすることができます。
CCDirectorにアクセスするメソッドは以下の通りです。

static CCDirector *_sharedDirector = nil;
+ (CCDirector *)sharedDirector
{
if (!_sharedDirector) {

//
// Default Director is TimerDirector
//
if( [ [CCDirector class] isEqual:[self class]] )
_sharedDirector = [[CC_DIRECTOR_DEFAULT alloc] init];
else
_sharedDirector = [[self alloc] init];
}

return _sharedDirector;
}


この他にも"shared"から始まるシングルトンクラスへのアクセスメソッドが用意されています。

(2)Scene
シーンは画面(場面・状態)を表現します。
「つりポン!」では、タイトル画面、ゲームプレイ画面、そうび画面などゲーム構成に必要な画面をそれぞれSceneで用意しています。
それをCCDirectorを介して状態を切り替えることにより画面遷移が実行される事になります。
またCCDirectorはアプリを実装する際に、最低1つのSceneを必要とします。

  $サイバーエージェント 公式エンジニアブログ


(3)Layer
LayerはScene上に配置するシートです。
画面の構成要素の1つであるSpriteを配置する土台になります。
Layer上にはLayerを配置する事も可能であり、画面タッチや加速度センサーのイベント検知も行います。

  $サイバーエージェント 公式エンジニアブログ

(4)Sprite
Spriteは画面に表示される背景画像やキャラクター、タイトル等のオブジェクトです。
Spriteは基本Layer上に配置されますが、Sprite上にSpriteを配置することも可能です。


実装
画面構成要素1つ1つの実装手順について書いていきたい所ですが、
今ではcocos2dのプログラミング本が書店に並んでいるので、そちらを見ていただければ実装について理解を深める事ができると思います。

  $サイバーエージェント 公式エンジニアブログ

「つりポン!」開発当時はこういったプログラミング本がなかった為、
cocos2d公式サイト(英語)のガイドラインを読み解いたり、ソースコードを解析しながら実装していました。

そんな中、実装に苦労した画面の1つがそうび画面です。
  $サイバーエージェント 公式エンジニアブログ

その理由は…
・画面内に表現するオブジェクトが多い
・スクロール操作での画面表現が必要
・ゲーム内パラメータによって変更が必要なオブジェクトが多い(装備アイテム、アイテム数etc…)
などが挙げられます。

この中でも赤点線で囲っているスクロール操作部分の実装部分には手こずりました。
  $サイバーエージェント 公式エンジニアブログ

cocos2dにはスクロール表現できるクラスがなく、自前で実装する必要がありました。
しかし、タッチイベントの検知、座標オフセット処理などを一から実装し、滑らかなスクロール操作を実現する難しさは試しの実装段階で痛感しました。
スクロール操作はできるものの、1スクロールでスクロール領域の端から端へ一直線という…滑らかさには遠い出来で、スクロールの滑らかさを出すにはスクロールのクッション処理や速度のチューニングなどが必要でした。

結論を言うと…一から実装する労力をかけるよりもUIKitフレームワークのUIScrollViewクラスを使う方が早い!ということで、「つりポン!」ではスクロール部分は全てUIScrollViewを使っています。

iPhone開発者ならご存知の通り、UIKitフレームワーク内にはスクロール表現可能なUIScrollViewクラスがあります。ただ、cocos2dでこのクラスを使うにあたっては1つ問題があります。
LayerにUIScrollViewはaddSubViewできないという事です。

まずはcocos2dとUIKitを融合してビュー表現できる方法を探す必要がありました。
cocos2dで画面表現に使用するLayerやSpriteといったノードは全て、CCDirectorのopenGLView上に描画されます。その為、UIKitのUIScrollViewクラスをopenGLViewにaddSudViewする事でビュー表示が可能ではないかと考えました。

・UIScrollViewクラスでスクロール実装
soubiScrollView = [[UIScrollView alloc] init];
soubiScrollView.frame = CGRectMake(92, 80, 355, 170);
soubiScrollView.backgroundColor = [UIColor clearColor];
soubiScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

soubiScrollView.pagingEnabled = NO;
soubiScrollView.contentOffset = CGPointMake(-100, 0);
soubiScrollView.contentInset = UIEdgeInsetsMake(0,0,0,100 );
[soubiScrollView flashScrollIndicators];

soubiScrollView.showsHorizontalScrollIndicator = YES;
soubiScrollView.scrollsToTop = NO;

・実装したUIScrollVieクラスをopenGLViewにaddSubView
[[[CCDirector sharedDirector] openGLView] addSubview:soubiScrollView];

UIScrollViewクラスでスクロールを実装して、openGLViewにaddSubViewしてみたところ問題なく表示できました!
今ではあたり前のように実装できる画面でも、当時は情報が少なく1つ1つに手がかかっていました。

最後に
cocos2d開発で利用すると便利なサードパーティツールがあります。
それについてはcocos2d開発支援ツールの紹介で色々紹介されているので読んでいただくと、より効率的な開発ができると思います。

また、「つりポン!」のゲームプレイ部分のアニメーション実装についてはPiggをiPhoneで動かすまでをご覧下さい。

参考文献
[1]cocos2d公式サイト
http://www.cocos2d-iphone.org/

[2]cocos2dで作る iPhone&iPadゲームプログラミング
 作者: Steffen Itterheim,畑圭輔,坂本一樹,加藤寛人,高丘知央,株式会社クイープ
 出版社/メーカー: インプレスジャパン

[3]cocos2d for iPhoneレッスンノート
 作者: 加藤寛人,佐藤伸吾
 出版社/メーカー: ラトルズ

第8回 研究課題レポート 発表会

$
0
0

こんにちは、研究課題レポート実行委員長Tossyです。

研究課題レポートについては、以下エントリをご覧ください。

http://ameblo.jp/principia-ca/entry-10691559933.html
http://ameblo.jp/cair/entry-11194620603.html


少し時間が経ってしまいましたが、研究課題レポート発表会が4/20(金)に行われました。

第8回研究課題レポートはおよそ80ものレポートが提出されました。
提出必須ではない新卒エンジニアも数人提出しており、全体的にとてもレベルが高い印象を受けています。

その中から、
最優秀賞として
「Virident 社製半導体ストレージFlashMax の検証」佐野裕章さん
「MCMCによる少数例からの母集団推定について」和田計也さん

優秀賞として
「最近のHardwareの調査」宇田川聡さん
「SWF バージョン 4においてのテキスト形式によるコンパイル結果の違い及びJavaScriptでのその描画方法に関する考察」小坂和弘さん
「Flash:Stage3Dに対応した3D物理演算ライブラリの検証」松本克彦さん

佳作として
「TokuDBのパフォーマンス検証」松浦隼人さん
「サーバ管理フレームワークbtfly の作成」生沼一公さん
「WebGL 負荷対策について」古谷薫さん
「Google Protocol Buffers ベース RCP ライブラリの実装」朴泰雄さん
「Redis ソート済みセット型を利用したタイムラインのリアルタイム生成アーキテクチャ」寺本隆彦さん

特別賞として
「Hadoop MapReduceのパイプラインジョブ開発のためのCascadingとPigの比較」遠山敏章さん

の計10レポートが選ばれました。


優秀賞以上については、社内のエンジニア全体MTGで発表時間5分のLT形式での発表会がありました。


■SWF バージョン 4においてのテキスト形式によるコンパイル結果の違い及びJavaScriptでのその描画方法に関する考察

ソフトウェアエンジニアの小坂さんの発表です。



swfからjs+html5へのコンバートは今まさにニーズが高いところであり、
おそらくネットにもここまでの検証結果はないことから新規性、信頼性ともに高く評価されました。
また、Swineに限らずFlashを使用している既存サービスなどにも有用な情報が含まれており、とても有用性の高いレポートでした。

LTについても、テンポよく笑いありの発表でした。


■Flash:Stage3Dに対応した3D物理演算ライブラリの検証

Ameba Piggのシステム開発に携わっている松本さんの発表です。



3Dゲーム開発技術における取り組みとして素晴らしく、デモと性能検証もあったので信頼性が高く評価されました。
今後どのようにサービスに活かしていけるかとても期待しています。


■Virident 社製半導体ストレージFlashMax の検証

アメーバのインフラエンジニアの佐野さんの発表。



半導体ストレージは、まだまだ製品数も少なく新規性が高い分野であり、今後の
大規模サービスの要となり得る技術です。検証においても多角的な評価を行
い、プロダクト環境での運用も行なっているため有用性、信頼性が高く評価されました。

佐野さんの独特な空気感でのLTは、とてもシュールで、皆が思わず笑ってしまうような和やかな発表でした。


■MCMCによる少数例からの母集団推定について

秋葉原のラボで、データマイニングをしている和田さんの発表です。

※ 内部情報的要素が強いため、発表資料の公開は控えさせていただきます。

和田さんのレポートは、事業としての収益性を考える上で非常に有用な取り組みでした。
ピグやゲームに取り入れることができれば事業的にも活かしやすいと評価されました。
また、著者のオリジナリティのある着眼や創意工夫による新規性があり、論旨展開も分かりやすく、信頼性も非常に高かったです。


■最近のHardwareの調査

インフラエンジニアの宇田川さんの発表資料です。
宇田川さんは、発表会当日は出張のため不在でしたが、受賞が決まったときは、家族でお祝いをしたそうです。



宇田川さんのレポートは、
I/Oパフォーマンスは、CPUやトラフィックの機能向上に伴い常に求められる部分であり、
その中でも新規性の高い技術を複数検証していることを評価されました。


研究課題レポートは、回を重ねるごとに質が上がっているように感じます。
また、発表会も非常に盛り上がり、運営者としては良かったなと思っています。

これからも、形は変わっていくかもしれませんが、
研究課題レポートを盛り上げていきたいと考えてます。

System Engineer, na-ga-san

$
0
0

こんにちわ。2011年度入社のM.GとM.KとK.Oです。

今回は、アメーバのAPI基盤グループでご活躍されているna-gaさんです。

na-gaさんといえば、チャラそうな見た目とは裏腹に責任感あふれる
犬とお酒が大好きな基盤系エンジニアです。
なんと実家にはパピヨンが6匹もいるとか・・・。
そんなにいたら見分けつかなそうですね!笑

あ、お酒は僕も大好きです。
中でもラム酒がすきなのですが
na-gaさんもラム、それもロンサカパがイイみたいで、
Barで頻繁に頼んでいる姿を見かけたりします。

そんなおちゃめな一面も持っているna-gaさんの今回のタイトルは「はじめてのRabbitMQ」です。
大量アクセスを効率よくさばくための非同期アプローチも弊社では頻繁に行われていますが
MQはその一環としてメール配信・フィルタリングなどに活用されています。

それではどうぞ。

PR: デザイナーの求人情報・転職支援はマスメディアン

はじめての RabbitMQ

$
0
0

アメーバ事業本部 API 基盤グループでプログラマをしている @na_ga です。

API 基盤グループでは、弊社の様々なサービスから利用される共通 API の開発・運用を行なっております。今回は、私が担当した API でメッセージキューとして利用した RabbitMQ を紹介させていただきたいと思います。

はじめに

API 基盤グループで提供している API には、リクエストをリアルタイムに処理する必要がないものもあります。例えばメール配信 API や、投稿内容の有人監視 API などが挙げられます。

これらの非同期処理が可能な API では、大量のリクエストを受け取るためにメッセージキューを使用しています。

メッセージキューを使用した構成では、リクエストを受け取るプログラムが、受け取ったリクエストから生成したメッセージをキューに格納します。キューに格納されたメッセージは、メッセージを処理するプログラムから取り出され、順番に処理が行なわれます。

各プログラムの役目を別けることによって、システムの負荷にあわせて部分的にスケールしやすい構成ができます。

このようなメッセージングのオープンなプロトコルとして Advanced Message Queuing Protocol があり、代表的な実装としては Apache Project の ActiveMQ、iMatix Corporation の ZeroMQ、そして今回紹介する VMware の RabbitMQ があります。

RabbitMQ 入門

RabbitMQ はメッセージのやり取りを中継するミドルウェアです。

個人的には、ActiveMQ より速く、ZeroMQ にはない永続性を備えており、スケールしやすいメッセージキューで、公式サイトのドキュメントが豊富な点も魅力的です。またコミュニティが活発的で 2012/03 にも RabbitMQ 2.8.1 がリリースされており、今後も注目しています。

では、実際に RabbitMQ で Hello World メッセージの送受信をやってみましょう!

環境を構築してみる

RabbitMQ 環境を CentOS 5 がインストールされている rabbitmq0 サーバに構築します。

RabbitMQ は、Erlang バージョン R12B-3 以上が必須となっています。CentOS の場合は yum の DAG レポジトリからバージョン R12B-5 をインストールできますが、RabbitMQ の各種プラグインを動かすために現時点で最新バージョンの R15B01 をソースからインストールします。

★ Erlang インストール
[root@rabbitmq0]# cd /usr/local/src
[root@rabbitmq0]# wget http://www.erlang.org/download/otp_src_R15B01.tar.gz
[root@rabbitmq0]# tar xvzf otp_src_R15B01.tar.gz
[root@rabbitmq0]# yum install ncurses-devel
[root@rabbitmq0]# cd otp_src_R15B01
[root@rabbitmq0]# ./configure
[root@rabbitmq0]# make
[root@rabbitmq0]# make install

★ Erlang バージョン確認
[root@rabbitmq0]# /usr/local/bin/erl -version
Erlang (ASYNC_THREADS,HIPE) (BEAM) emulator version 5.9.1

RabbitMQ は公式サイトで配布されている最新バージョン 2.8.1 の Binary をダウンロードし、/usr/local/rabbitmq 以下に設置します。その後 RabbitMQ を起動する rabbitmq ユーザーを追加し、RabbitMQ の起動スクリプトを作成します。

★ RabbitMQ をインストールディレクトリに配置
[root@rabbitmq0]# cd /usr/local/src/
[root@rabbitmq0]# wget http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.1/rabbitmq-server-generic-unix-2.8.1.tar.gz
[root@rabbitmq0]# tar xvzf rabbitmq-server-generic-unix-2.8.1.tar.gz
[root@rabbitmq0]# cp -a ./rabbitmq_server-2.8.1 /usr/local/rabbitmq_server-2.8.1
[root@rabbitmq0]# ln -s /usr/local/rabbitmq_server-2.8.1 /usr/local/rabbitmq
[root@rabbitmq0]# mkdir /var/log/rabbitmq

★ rabbitmq ユーザーを作成
[root@rabbitmq0]# /usr/sbin/groupadd -g 30105 rabbitmq
[root@rabbitmq0]# /usr/sbin/useradd -u 30105 -g rabbitmq -d /var/lib/rabbitmq -m -c 'RabbitMQ messaging server' rabbitmq

★ rabbitmq ユーザーに rabbitmq コマンドの PATH を追加
[root@rabbitmq0]# cp /var/lib/rabbitmq/.bash_profile{,.bak}
[root@rabbitmq0]# sed -i 's#PATH=$PATH:$HOME/bin#PATH=$PATH:$HOME/bin:/usr/local/bin:/usr/local/rabbitmq/sbin#g' /var/lib/rabbitmq/.bash_profile
[root@rabbitmq0]# diff /var/lib/rabbitmq/.bash_profile{,.bak}
10c10
< PATH=$PATH:$HOME/bin:/usr/local/bin:/usr/local/rabbitmq/sbin
---
> PATH=$PATH:$HOME/bin

★ rabbitmq ユーザーにパーミッションを変更
[root@rabbitmq0]# chown -R rabbitmq. /var/log/rabbitmq
[root@rabbitmq0]# chown -R rabbitmq. /usr/local/rabbitmq_server-2.8.1

★ RabbitMQ の起動スクリプトを作成
[root@rabbitmq0]# cat << 'EOF' > /etc/init.d/rabbitmq && chmod +x /etc/init.d/rabbitmq
#!/bin/bash
user=rabbitmq
run_as_user(){
su - $user -c "$*"
}
start(){
run_as_user rabbitmq-server -detached
}
stop(){
run_as_user rabbitmqctl stop
}
status(){
run_as_user rabbitmqctl status
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop && start
;;
status)
status
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit $?
EOF

RabbitMQ を起動し、キュー情報を取得します。

★ RabbitMQ 起動
[root@rabbitmq0]# /etc/init.d/rabbitmq start
Activating RabbitMQ plugins ...
0 plugins activated:

★ キュー情報取得
[root@rabbitmq0]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
...done.

インストールした直後なので、まだ何もキューが作成されていないことが確認できます。たったこれだけで、とりあえずメッセージを送受信する準備が整いました!

メッセージを送信してみる

"hello" キューに対して "Hello World" メッセージを送信するプログラムを実装します。

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

public class Send {

private static final String QUEUE_NAME = "hello";

public static void main(String[] argv) throws Exception {

// Factory 生成
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("rabbitmq0");

// Conenction & Channel 接続
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

// hello キューを宣言
channel.queueDeclare(QUEUE_NAME, false, false, false, null);

// hello キューに Hello World メッセージを送信
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println("[x] Sent '" + message + "'");

// Channel & Connection 切断
channel.close();
connection.close();

}
}

プログラムを実行し、キュー情報を取得します。

★ プログラム実行
[root@rabbitmq0]# java -cp .:commons-io-1.2.jar:commons-cli-1.1.jar:rabbitmq-client.jar ./Send
[x] Sent 'Hello World!'

★ キュー情報取得
[root@rabbitmq0]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
hello 1
...done.

インストール後は存在していなかった "hello" キューが作成され、1 件のメッセージが格納されていることが確認できます。

メッセージを受信してみる

"hello" キューからメッセージを受信するプログラムを実装します。

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class Recv {

private static final String QUEUE_NAME = "hello";

public static void main(String[] argv) throws Exception {

// Factory 生成
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("rabbitmq0");

// Connection & Channel 接続
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

// hello キューを宣言する (Consumer 側が先に起動する場合を考慮して)
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println("[*] Waiting for messages. To exit press CTRL+C");

// Consumer を宣言する (これにより RabbitMQ からメッセージがプッシュ配信される)
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(QUEUE_NAME, true, consumer);

// 受け取ったメッセージを処理する
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println("[x] Received '" + message + "'");
}

}
}

プログラムを実行し、キュー情報を取得します。

★ プログラム実行
[root@rabbitmq0]# java -cp .:commons-io-1.2.jar:commons-cli-1.1.jar:rabbitmq-client.jar ./Recv
[*] Waiting for messages. To exit press CTRL+C
[x] Received 'Hello World!'

★ キュー情報取得
[root@rabbitmq0]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
hello 0
...done.

さきほど格納したメッセージを受け取り "hello" キューに格納されているメッセージが 0 件になったことが確認できます。

さらに高度な使い方

RabbitMQ はキューおよびメッセージの永続化、メッセージのラウンドロビン配信・一斉配信、RPC 通信など高度な機能を備えています。

こちらに関しては公式サイトのチュートリアルやドキュメントに詳細が記載されていますので、一度ご確認ください。冒頭でも述べましたが、RabbitMQ は公式ドキュメントが非常に豊富な点も魅力のひとつです!

■ RabbitMQ ドキュメント : http://www.rabbitmq.com/documentation.html
■ RabbitMQ チュートリアル : http://www.rabbitmq.com/getstarted.html

RabbitMQ の冗長構成

実際に API に組み込んで使用するには、冗長構成が必要不可欠です。

一部の RabbitMQ に障害が発生した場合でも、API に影響が出ないよう冗長構成を取ります。また、リクエストを受け取ったプログラムは、正常な RabbitMQ に対してメッセージを送信し続ける必要があります。

しかし、RabbitMQ の公式クライアント (現時点の rabbitmq-client-2.8.1) では、1 台の RabbitMQ だけに接続を行なう実装になっています。もし接続している RabbitMQ に障害が発生した場合は、処理を続けられません。

そのため、ここでは複数の RabbitMQ に対して接続を行ない、もしメッセージが送れなかった場合は正常な RabbitMQ に対してメッセージを送信するように拡張しました。

では、拡張したクライアントを使用し、RabbitMQ の冗長構成を紹介します。

実装

拡張したソースコードは Github にて公開しています。

■ Github : https://github.com/na-ga/us-rabbitmq-client/

複数の RabbitMQ を起動してみる

さきほど構築した手順で rabbitmq1 サーバと rabbitmq2 サーバに RabbitMQ 環境を構築します。その後、各 RabbitMQ を起動し、キュー情報を取得します。

★ rabbit1 サーバ上の RabbitMQ を起動
[root@rabbitmq1]# /etc/init.d/rabbitmq start
Activating RabbitMQ plugins ...
0 plugins activated:

★ rabbit2 サーバ上の RabbitMQ を起動
[root@rabbitmq2]# /etc/init.d/rabbitmq start
Activating RabbitMQ plugins ...
0 plugins activated:

★ rabbit1 サーバ上のキュー情報を取得
[root@rabbitmq1]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
...done.

★ rabbit2 サーバ上のキュー情報を取得
[root@rabbitmq2]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
...done.

こちらもインストールした直後なので、まだ何もキューが作成されていないことが確認できます。

複数の RabbitMQ にメッセージを送信してみる

複数の "durable_queue" キューに対して "Hello World" メッセージを送信するプログラムを実装します。

このプログラムでは、キューの宣言時およびメッセージの送信時に永続性オプションを有効にしています。また、第一引数に送信回数を指定できるようにします。

import jp.ameba.us.rabbitmq.client.MqConnectorFactory;
import jp.ameba.us.rabbitmq.client.MqProducer;

public class Send {

private static final String QUEUE_NAME = "durable_queue";

public static void main(String[] args) {

// 送信回数
int count = 0;
try{
count = Integer.valueOf(args[0]);
}catch(Exception e){
System.err.println("Usage: java ./Send [count]");
return;
}

// Factory 生成
MqConnectorFactory factory = new MqConnectorFactory();
factory.addServer("rabbitmq1");
factory.addServer("rabbitmq2");

// RabbitMQ サーバに接続
factory.startup();

// Producer 取得
MqProducer producer = factory.newProducer();

// durable_queue キューに Hello World メッセージを count 回送信
for(int i = 0; i < count; i++){
String message = "Hello World! " + i;
producer.store(QUEUE_NAME, true, false, false, null, message.getBytes());
System.out.println("[x] Sent '" + message + "'");
}

// RabbitMQ サーバと切断
factory.shutdown();

}
}

引数に 5000 を指定してプログラムを実行し、プログラム実行中に rabbitmq1 サーバ上で動作している RabbitMQ を再起動します。その後 RabbitMQ のキュー情報を取得します。

★ 引数に 5000 を指定してプログラム実行
[root@rabbitmq0]# java -cp .:commons-io-1.2.jar:commons-cli-1.1.jar:rabbitmq-client.jar:us-rabbitmq-client.jar ./Send 5000
[x] Sent 'Hello World! 1'
[x] Sent 'Hello World! 2'
[x] Sent 'Hello World! 3'
(snip) ☆ 実行中に rabbitmq1 サーバにて /etc/init.d/rabbitmq restart を実行する
[x] Sent 'Hello World! 4998'
[x] Sent 'Hello World! 4999'

★ rabbit1 サーバ上のキュー情報を取得
[root@rabbitmq1]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
durable_queue 1053
...done.

★ rabbit2 サーバ上のキュー情報を取得
[root@rabbitmq2]# su - rabbitmq -c "rabbitmqctl list_queues name messages_ready"
Listing queues ...
durable_queue 3947
...done.

rabbitmq1 サーバ上の "durable_queue" キューには 1053 件のメッセージが格納されており、残りの 3947 件が rabbitmq2 サーバ上の "durable_queue" キューに格納されていることが確認できました。

RabbitMQ の管理画面

RabbitMQ には多くのプラグインが提供されています。

いままでは rabbitmqctl コマンドでキュー情報を取得していましたが、rabbitmq_management プラグインを導入するとブラウザ上から閲覧できます。rabbitmq_management は、システムの負荷状況・リソース使用量や、RabbitMQ 上のキューや Exchange の管理ができる便利なプラグインです。

では、管理画面の導入手順を紹介します。

プラグインを導入してみる

rabbitmq0 サーバに導入します。

RabbitMQ 環境を構築後に rabbitmq-plugins コマンドで rabbitmq_management プラグインを有効にします。その後、プラグインを反映するために RabbitMQ を再起動します。

★ プラグイン導入
[root@rabbitmq0]# su - rabbitmq -c "rabbitmq-plugins enable rabbitmq_management"
The following plugins have been enabled:
mochiweb
webmachine
rabbitmq_mochiweb
amqp_client
rabbitmq_management_agent
rabbitmq_management
Plugin configuration has changed. Restart RabbitMQ for changes to take effect.

★ RabbitMQ 終了
[root@rabbitmq0]# /etc/init.d/rabbitmq stop
Stopping and halting node 'rabbit@rabbitmq0' ...
...done.

★ RabbitMQ 起動
[root@rabbitmq0]# /etc/init.d/rabbitmq start
Activating RabbitMQ plugins ...
6 plugins activated:
* amqp_client-2.8.1
* mochiweb-1.3-rmq2.8.1-git
* rabbitmq_management-2.8.1
* rabbitmq_management_agent-2.8.1
* rabbitmq_mochiweb-2.8.1
* webmachine-1.7.0-rmq2.8.1-hg

ブラウザで http://guest:guest@rabbitmq0:55672/ に接続しましょう。

RabbitMQ Management Console

このような画面が表示されれば、完了です!

まとめ

今回は、メッセージキューとして利用した RabbitMQ を紹介させていただきました。

RabbitMQ でメッセージをやり取りする流れの雰囲気は掴んでいただけたでしょうか。また、冗長構成を実現するには、RabbitMQ でクラスタリングを組む手法や、ロードバランサーを別途用意して実現することもできますが、シンプルな使い方では今回のような手法も使えるのではないかと思います。

最後になりますが、RabbitMQ は公式ドキュメントは充実していますが、まだ日本語ドキュメントは少ない状態です。RabbitMQ を使ってみた際には、ぜひアウトプットをしていただきたいなと思っています!

Tech Lunch(テックランチ)はじめました。

$
0
0

こんにちは、スマートフォンサービスのエンジニアをしています川畑です。

2011年11月に中途入社し、エンジニアとしてサーバ側やiOS/webアプリのコードも多少書くのですが、最近ではマネジメントが中心になりつつあります。



今日は、3月より新しい試みとして始まりましたTech Lunch(テックランチ)についてご紹介します。

もともとサイバーエージェントでは、各種懇親会の補助制度や、シャッフルランチなど職種を横断した交流制度があったのですが、数多くのエンジニアが中途採用でジョインするなかで、エンジニア同士の情報交換や気軽にコミュニケーションが取れる体制を応援したいという旨で始まりました。

弊社長瀬のブログ
http://ameblo.jp/lionbaby/entry-11166203655.html


具体的には、弊社のセミナールームにエンジニアが集まり7人くらいずつのテーブルを囲んで、お弁当を食べながらわいわいと交流したり議論したりするランチイベントです。





フェーズ1:交流して気兼ねなく話し合える関係づくり


 それでは、Tech Lunchの最初の目的である交流について取り上げたいと思います。いきなり見ず知らずのエンジニアを集めて、「さぁ議論しましょう!」と言ってもなかなか話しづらいものです。

そこで、最初の2週間はあえてアウトプットを求めずに、自己紹介を行なってもらうことにしました。





 今回のTech Lunchはスマートフォンサービスに関係するエンジニアに限定したのですが、それでも110人の大所帯になったため、8テーブル約55人ずつ大まかな言語別に分けて2日開催となりました。


「共通の言語や開発環境」を持っているけど、「名前と顔が一致しない」くらい社歴の様々なエンジニアがそれぞれのテーブルを囲むことで、自分のプロジェクトを紹介しあったり、ここ数ヶ月以内に入社した人は前職時代の経験を紹介することでとても盛り上がったようです。




フェーズ2:テーマを決めて積極的な議論

私もサイバーエージェントに入社する前は、いろいろなゲストにお声がけして、iPhoneやAndroid系の勉強会やセミナーを開催していたのですが、サイバーエージェントには社内に凄腕のエンジニアがゴロゴロいるので、それぞれの分野の得意な人を集めて議論してもらうことで、加速度的に濃い情報が集まって来ました。

一例を紹介すると

・各種Javascriptフレームワークのいいところ悪いところ
・iPhoneやAndroidのUI部分のテスト自動化ツールについて
・node.jsを導入するときによく使うnpmベスト5

などなど、実務で大量の利用者と向き合っているサービス開発者ならではの、とても実践的でその日から役に立つ情報ばかりが集まって来ました。



これらの情報はWikiに議事録として残っていくのですが、参加者からは「ここで詰まったらあの人達に相談してみよう」というプロジェクトを横断したエンジニアの繋がりができたことがとても有益だったようです。

おまけ

今回のTech Lunchの運営も、約15名のエンジニア自身で行いました。大量のエンジニアをどのように効率良くバラけさせて組むか、議論が進むためのテーマの名称はどうするか、机の配置や資材の買い出し(特に後半はスターバックスまで50人分のコーヒーを毎回徒歩で買いに行ったり)など、イベントを盛り上げるために毎回集まってわいわい進めるサイバーエージェントの文化を感じました。
(面倒なことも快くやってくれる運営のみなさん、おつかれさまでした!これからも盛り上げましょうね)


PR: 【新登場】最新のLTE対応ルータならスマホの給電も!

$
0
0
月額3980円からの低料金で高速モバイル通信!最新のルータがお得になる特典も。

Ruby on RailsとApache Solrで構築するドキュメント全文検索システムの開発

$
0
0

はじめまして、アプリケーションエンジニアをしています、たかぎわ (@shun_tak) と申します。
2013年度4月入社予定の内定者で、現在はアルバイトとして週に2日間ほど勤務しております。

今回のエントリーでは、私が業務で開発した社内システムについて紹介しようと思います。


社内システム Tech Search を開発・リリースしました。

Tech Searchのリリースにより、社内に蓄積された知識資産の活用が大幅に改善されました。

Tech Searchとは、

弊社の研究レポート制度を利用して執筆されたテックレポートの全ファイル・全文章を横断的に検索するための社内システムで、Ruby on RailsApache Solrを利用して実現しました。全文検索だけでなく絞り込み検索も実装し、UIにも手を抜かず、ユーザーに使いやすいシステムを目指して開発しました。

Tech Searchがリリースされる以前、

テックレポートはネットワーク上に雑然と保存されているだけで、添付資料などの関連ファイルも含め数千のファイル群としてファイルサーバーの奥深い階層に眠っていました。レポートは提出年月>部署>執筆者というディレクトリ構成で保存され、ファイル名は「研究課題レポート2009.doc」や「report200909.pdf」などと書かれ、探そうにもどこに何があるか不明、ファイルを開いてみるまで内容も分からないという状況でした。 知識資産を活用しようにも不可能でした。

Tech Searchのリリースにより、

ただ検索するだけでほしい情報にアクセスできるようになりました。提出時期での絞り込みはもちろん、受賞レポートに限定して一覧表示することもできます。docファイルはすべてPDFに変換済みなので、ブラウザによってはダウンロードせずにブラウザ上で閲覧することも可能です。8月いっぱいはユーザーフィードバックを聞きながら、改善や新機能追加をしていく予定です。

※受賞したレポートに関しては社内向けに製本されているので (PDF版もあり)、優秀な作品は製本されたものから探すことはできます。ただし紙媒体なので (PDF版も募集回ごとに分かれている)、ほしい情報へのアクセスは簡単ではありません。

Tech Searchのシステム構成

まず図をご覧ください。


また、仮想サーバーのスペックは以下の通りです。


CPU仮想2コア 2.2GHz
メモリ4GB
ディスク容量70GB

処理の流れとしては、ブラウザから送信されたリクエストをApacheが受け取り、検索クエリがあればアプリからSolrに問い合わせ全文検索を実行します。その結果を受けてMySQLにある各種メタデータを取得し、結果一覧を生成しブラウザへレスポンスします。結果一覧のリンクをクリックすると、ファイルシステムのPDFを返します。

ApacheとPassengerはとりあえずで選んだのですが、結果的にはよい選択だったと思います。Passengerは軽量なWebアプリケーションに向いている[*1]といわれ、今回開発したアプリケーションのRailsが担当する処理が軽く、社内のエンジニア向けのシステムということで同時接続数も少なかったため、結果的に軽快に動作するアプリケーションとなりました。Railsは関係ないですが、PDFも静的ページの画面遷移並みに高速に表示されます。

フレームワーク選定のお話

私自身の経験としては、今まで関わったプロジェクトではPHP (Codeigniter, Symfony1系) やJavaを使って開発をしてきましたので、こういったフレームワークを選ぶのが自然だったと思います。ではなぜRuby on Railsで開発することになったのかといいますと、案件の自由度の高さが大きな要因だったと思います。今回の案件では混沌としたファイル群を整理して、全文検索するシステムをつくってくれと言われただけで、フレームワークやミドルウェアの選択、設計・開発について特に指示はありませんでした。それじゃNodeかRailsだろ!ということになりました。全然理由になってないですね。

一応Javaも検討したのですが、個人的にとにかく早くプロトタイプを作って方向性の確認をしたいと考えていたので、あまり慣れていないJavaフレームワークで設定に苦しむのは避けたかったのと、少しだけ経験があったRailsへの理解をもっと深めたいということで結局Railsを採用することになりました。本当は、使ってみたいからという理由で選択するのはよくないです。

ミドルウェアはDBにMySQLを、検索エンジンにApache Solrを採用しました。MySQLという選択は自然だと思いますが、検索エンジンのSolrは薦められて使ってみました。初めての利用でしたが、それでも短期間で簡単な設定はできるようになりました。


Solrで手軽に構築

Railsの便利な機能については、rakeとかScafoldingとかmigrationとかActiveRecordとかAssetsPipelineとかキャッシュ機能とか、ググればいくらでも出てくると思うので、ここではSolrに絞って書いてみようと思います。Railsについての情報が必要な方は、今週発売のWEB+DB誌 Vol. 70で特集されているのでそちらも合わせてご参照ください。

Solrとは?

Apache Solr入門によると、

Apache Solr (アパッチ ソーラーと読みます) はYonik Seeley氏によりCNET社向けに開発された検索エンジンサーバーです。2006年1月にApacheコミュニティにソースコードが寄贈されオープンソース・ソフトウェアとなって以来、その高い機能性・拡張性・利便性および性能などが話題となり、瞬く間にユーザは世界中に広がりました。~略~Solrの特徴を挙げると、以下のようになるでしょう。
  1. 実績のある全文検索ライブラリ Apache Lucene を用いた完成された検索エンジンサーバである
  2. 膨大な検索結果の中からユーザが求めているであろうドキュメントに適切に誘導するさまざまなしくみを備える
  3. さまざまなキャッシュのしくみによりI/Oレスで高速な検索が行える
  4. インデックスのレプリケーション機構を備える
  5. 分散検索により膨大な量の検索対象ドキュメントを扱える
  6. Apache Licence 2.0 の OSS であり機能拡張のためのインタフェースを備える
以下略。
といったように、Solr単体で検索エンジンとして利用することができます。「完成された検索エンジンサーバである」という特徴により、システムにすぐに導入することができました。

Solrのバージョン

執筆時点での最新版は3.6.1で4系もbetaが出ていますが、システム構築時の3.5.0を前提にします。また、参考文献としてApache Solr入門というオレンジ色の本があります。Solr 1.4をもとに書かれているので今と仕様が異なる部分もあるのですが、基本は同じなので参考になることは間違いありません。最新情報についてはApache Solr入門の著者の一人である大谷 純氏 (@johtani) のブログも参考になります。こちらも要チェックです。

Cellでドキュメントを読み込み、インデックスを作成する

さてSolrの使い方ですが、Solrで検索をするには当然ですがデータが必要です。今回開発したTech Searchの検索に必要なデータはWordまたはPDFです。このままでは扱えないので、プレーンテキストに出力してやる必要があります。Solrへのインデックス登録はXMLで流し込めるので、出力したプレーンテキスト群を一つのXMLにまとめてやります。処理をまとめると以下の図のようになります。

インデックス作成フロー


Word or PDFからXMLへの変換には、LuceneのTikaをSolrに取り込んだCellという機能を使って行います。curlでコマンドを叩けるので、shellを書いて全Word&PDFについて一気に変換します。たまに完全に文字化けしてしまうファイルもありましたが、日本語を扱うエンジニアならそこは頑張りましょう。

続いて生成したXML群をインデックス登録用の一つのXMLにまとめる作業に入ります。プレーンテキストに変換するステップを挟む必要はないのですが、MySQLに格納するデータをスクレイピングしたりするついでに作りました。この辺はスクリプトを書いて処理しました。

あとはSolrのschemaに合わせてadd用のXMLを生成したら、post.jarを使ってインデックス登録するだけです。ここも自作スクリプトですね。

RailsからSolrにクエリを投げる

簡単に動きます。まずGemfileにsolr-rubyを追加します。
gem 'solr-ruby'

続いてcontrollerを作成します。サンプルは以下です。
class SearchController < ApplicationController

  def initialize

    @solr = Solr::Connection.new('http://localhost:8983/solr', :autocommit => :on)

  end


  def index

    if params[:q] then

      data = submit(params)
      # dataを@変数に格納したり、描画に必要な処理をする

      render 'result'

    else

      render 'index'

    end

  end


  private


  def submit( p = {} )

    query = p[:q]

    fq = p[:fq]

    field = (p[:fl] ? p[:fl] : 'id,score')

    start = (p[:start] ? p[:start] : '0')

    rows = (p[:rows] ? p[:rows] : '10' )

    highlight = true

    hl_fl = "text"

    hl_pre = ""

    hl_post = "
"

    sort = (query == '*:*' ? 'date desc' : 'score desc')


    select = Solr::Request::Select.new(nil, { 'q' => query, 'fq' => fq, 'fl' => field, 'start' => start, 'rows' => rows, 'hl' => highlight, 'hl.fl' => hl_fl, 'hl.simple.pre' => hl_pre, 'hl.simple.post' => hl_post, 'sort' => sort } )

    return @solr.send(select).data

  end
end


受け取ったパラメータをsubmitに渡し、Solr::Request::Select.newでsolrのselectクエリを生成します。それをinitializeで生成したSolrコネクションによって送信します。
結果のdataはRubyのHashで返ってくるので、あとはご自由に使ってください。

社内非標準技術 Ruby on Rails で開発してみてわかったこと

以上、こんな感じでドキュメント全文検索ができるようになりました。

今回社内非標準のフレームワークを使って開発してみて、コードレビューできる人がいないという事実の重さを改めて実感しました。自ら進んで学ばなければ成長はあり得ませんし、コードに対する責任は自分がすべて負わなければなりません。


開発を終えて

今回このシステムの開発を任せてもらい、開発日数50日で、自ら開発スケジュール・工程を決め、システム設計からWeb Appフレームワークの選定、サーバーの構築・設定、DBの設計・構築、実装・コーディング、テスト、UI/UXの設計・実装、運用、ログの解析、改善・機能追加まで一つのシステムの中で一貫して体験できたのが大きな収穫でした。検索エンジンSolrも勉強して導入してみて、技術的にも大きな学びを得ることができました。

今回のシステム開発は自分一人だけで行いましたが、やはり組織に入るからにはチームでの開発をするのが楽しみです。
技術者として内定が決まっている同期とアプリ企画バトルというコンテストも行われるのですが、私の所属するチームでは企画に留まらずモックまでつくるつもりでいるので、まずはそこでチーム開発の腕試しです。がんばります!

それから、今後は自分の専門性をどこに定めるかについてさらに掘り下げて考えていきたいです。
PMやプロデューサとしてのサービス企画・開発にも興味がありますが、まずは技術者としての地盤を固めていこうと思います。その上で技術者としての専門性を身につけながら、社内の企画コンテストなどを通してチャンスを掴んでいきます。

相談に乗ってくださる方、募集中です!

参考資料

*1 WEB+DB PRESS Vol. 70
*2 Apache Solr 入門 - オープンソース全文検索エンジン


PR: 966戸の間取りから、空住戸を検索!

DEFCON 20 のレポート

$
0
0

こんにちは。セキュリティチームの伊藤と、基盤システムエンジニアのうい(@k_ui)です。


今回の記事は、7月26-29日に開催された DEFCON20 と、その DEFCON20 のイベントの一つ CTF についてです。弊社では、この CTF に参戦する sutegoma2プロジェクトページ) のみなさんのサポートをしています。開催当日も私たち二人で邪魔にならない程度に当日の様子を見学してきましたので、その様子についても扱います。


DEFCON ってなに?


DEFCON とは、米国で開催されるセキュリティ会議の一つで、その参加者は毎年1万~2万人ほどにもなります。20回目の開催となる今年のDEFCONは、ラスベガスの ホテル Rio で開催されました。年々規模が大きくなっており、今年の DEFCON 20 も過去最大の規模だそうです。


セキュリティ会議、というのは少し堅い言い方で実際のところ「ハッカーのお祭り」と言ったほうが正しいかもしれません。その理由は会場の雰囲気などを伝える中で理解していただけると思います。


DEFCON 20 の中で催される様々なイベント・ブースがあります。セキュリティ技術者やそれに関わる方々の講演や、ハッキング技術の実演、それに関わるツールやグッツの販売、CTFなどのコンテストやイベントなどです。


CTF (Capture The Flag) ってなに?


CTFはコンピュータとネットワークを利用して行われる競技で、その競技形式には様々なものがあります。その多くは知識や技術力を競うものになっています。今回の DEFCON CTF では、クイズ形式と攻防戦形式の2つが採用されました。


このクイズ形式は、DEFCON CTF 本戦に先立って6月2日から6月4日にかけて行われた予選に採用された形式です。この予選で行われたクイズ形式は、主催者が用意したWEBサイトから情報を抜き出して答えを探したり、バイナリファイルを解析して答えを探したりする形式のものでした。今回は、「grab bag」、「/urandom」、「binary l33tness」、「pwnables」、「forensics」の5カテゴリ、それぞれのカテゴリに100点、200点、300点、400点、500点の得点が得られる問題が用意されていました。この予選で、sutegoma2 は4400点で4位となり、本戦への出場をはたしました。


攻防戦形式では、主催者から渡されるサーバを、ローカルネットワーク越しから来る他チームの攻撃から守ったり、逆に他チームのサーバを攻撃したりすることで競う形式です。こちらについては、DEFCON CTF 本戦の様子を伝える中でもう少し詳しく書きます。


DEFCON CTF


DEFCON CTF は DEFCON 20 の日程のうち、7月27-29日の3日間を通して、チームのスコアを競う競技になっています。


競技のために用意されたローカルネットワーク内で、他チームサーバが持つ鍵を奪取したり上書いたり、逆に他チームから攻撃をされたりすることで、スコアが増減します。


スコアの算出にはサーバの稼働率も含まれているため、攻撃をされないようにサーバをネットワークから遮断したり、ダウンさせておいたりても、スコアが伸びないようになっています。


競技に参加できる人数は、基本8人なのです。しかしこの人数は、会場に来られる人数で、実際にネットワーク越しに先述の8人以上の参加者がいても問題ないようです。実際、優勝したチームの侍は会場外に80人いるとの話もありました。


参加チームは20チームで、運営団体である DDTEK の公式サイト にて、参加チーム名を一覧することができます。


DEFCON CTF 前日


DEFCON CTF の主催者により用意されたホテルの一室で、CTF の準備をしました。


主な準備の目的は、自チームのネットワークをいち早く競技会場に構築できるようにするためです。そのため、配線やマシンの設定などを前日にしていました。


$サイバーエージェント 公式エンジニアブログ
画像: 前日の準備の様子


$サイバーエージェント 公式エンジニアブログ
画像: 予め配線などのセットアップの様子


DEFCON CTF 開始


競技は、9時から始まりました。開始直後、主催者から3種類のモノがわたされました。


 ◯ 競技用のローカルネットワークに通じている2本のイーサネットケーブル
   ・ チームサーバにつながっているはずですがIPアドレスは不明
 ◯ バイナリファイル2つ(USB フラッシュメモリに入っていた)
   ・ファイル名に何の意味の無い(ファイル本体をSHA1ハッシュしたものをファイル名にしている)
   ・拡張子もない
 ◯ プリンタ1台
   ・特に主催者側から用途などの説明はありません


この、あまり情報のない状態で、sutegoma2 のメンバーは、それぞれ役割分担しながら解析を進めていきます。


sutegoma2 で用意したネットワーク内に存在するチャットや、wiki を用いて、メンバーの連携や情報共有をしています。


$サイバーエージェント 公式エンジニアブログ
画像: 会場は暗く他チームのやり取りがわからないようになっていた。写真手前は sutegoma2 の皆さん


最初に動きらしい動きがあったのはプリンタの解析をしていたチームです。競技開始から4時間になっても、どの CTF 参加チームにも動きが見られず、痺れを切らせた運営チームからヒントをいただくことで先に進みました。このプリンタの中にある RFID タグを読み取るとパスワードらしき文字列が手に入りました。


運営から配られたファイル2つは、先頭数バイトを見ることで、暗号化されたファイルであることがわかりました。復号のためのパスフレーズは、先程プリンタから取得した文字列です。


一方のファイルの中身は、チームサーバのIPアドレス、SSH接続するための秘密鍵が圧縮されたファイル。もう一方のファイルの中身は、チームサーバのルートディレクトリ以下全ファイルが圧縮されたファイルでした。これにより、自チームサーバに接続が可能となり、本格的に競技が始まりました。


DEFCON CTF 攻防


チームサーバでは、TCP(UDP)ポート一つを握ったサービスが17個動いており、他チームサーバのそれらのサービスにアクセスをすることで鍵を取得 or 上書きをしスコアを稼ぎます。


サービスは telnet などで接続すると様々な挙動を示します。例えば、あるサービスは telnet で接続すると 3D 迷路ゲームになっていて、f, l, r のキー入力で移動や方向転換ができるようになっています。ゴールにたどり着くと鍵が手に入る仕組みになっているようです。またあるサービスは、その実行バイナリ内に含まれる文字列から WebDAV サーバのようなものであったようです。


これら17個のサービスの攻撃難易度は様々で、如何に簡単な問題を探し当てるか、難しい問題であるかを判断するかなども競技では大切になります。


これらのことから、チームのやるべきことは簡単に分けて2つになります。


 ◯攻撃: 他チームのサービスから鍵を奪取したり上書きする。
 ◯守り: 攻撃されても鍵を取られないようにサービスにパッチを当てる、鍵が入っていそうなパケットをフィルタリングする。


また、競技ネットワーク内を流れるパケットをキャプチャし、他チームの攻撃の様子などを解析するチームも編成されていました。


このキャプチャしたパケットの解析チームも苦戦していて、どうやら解析に使う Wireshark (パケット解析ソフトの一種)の当時未知の脆弱性を突くようなパケットを流し、妨害をするチームがいたようです。個人的には DEFCON を象徴するようなできごとだなとも感じました。


 ◯ Wireshark exploit from Defcon 20 CTF - 0xDEADBEEF
   ・上記の脆弱性について説明してるページ


競技の様子などは、sutegoma2 による参戦レポートが現在発売中の ハッカージャパン 11月号 に掲載されていますので、参考にしてみてください。


競技の結果は現時点でも発表されていませんが、会場スクリーンに流れるスコアの速報などから察するに1位は侍で、sutegoma2 は19位です。


DEFCON CTF 以外のイベント・ブース


今回、DEFCON CTF の見学が主目的だったため、DEFCON の他のイベントなどは一部しか見ることができませんでしたが、幾つか紹介します。


参加バッジと暗号解読コンテスト


DEFCON 参加者は、特殊な仕掛けが施された参加バッジが貰えます。このバッジは参加者の種類ごとに複数用意されていて、一般参加者は古代エジプトの神様を模した白いバッジ、スタッフは赤いスカラベのバッジになっている。他にも、記者向け、アーティスト向け、登壇者向けなどがあった。バッジ種類は バッジ作成者が投稿 しているので一覧することができます。


サイバーエージェント 公式エンジニアブログ
画像: 一般参加バッジ、青色LEDが点滅している


バッジには、赤外線通信モジュール、Mini USB 端子、青色 LED などがついていて、他のバッジと赤外線通信したり,LED 点滅パターンによる状態表現が可能になっていたりするようです。


このバッジにはある謎が仕掛けられていて、会場のあちこちに点在する謎の文字列などと合わせて仕組まれた暗号を解くコンテストも、DEFCONでは開催されていました。


サイバーエージェント 公式エンジニアブログ
画像: 会場に設置されている看板。近づくと・・・


サイバーエージェント 公式エンジニアブログ
画像: 線にみえる部分が、長い文字列になっている。これもコンテストの一部だとか。


物販ブース


DEFCON や、セキュリティに関わる商品を扱っているブースです。確認できた商品は:


 ◯ DEFCON Tシャツ、ステッカー
 ◯ ピッキングツール、ピッキングツールが通用しない錠
 ◯ pwnie plug
   ・一見すると電源アダプタ
   ・WiFi, 3G/GSM 通信が可能な Linux マシン
   ・用途は・・・
 ◯ WiFi 用途の外部アンテナ
 ◯ セキュリティ関係を中心とした書籍


物販では無いですが、ブースの一角では、モヒカンカットをしてくれるお店もありました。


$サイバーエージェント 公式エンジニアブログ
画像: 最終日にモヒカンカットした、とある sutegoma2 メンバー


WALL OF SHEEP


DEFCON のブースの一つに、写真のような WiFi が自由に使えるブースがありました。しかし、そのブースの奥には、この WiFi 上に流れるパケットから ID、パスワード、MAC アドレスなどを抽出し、リアルタイムに晒しているスクリーンがありました。恐ろしさと同時に、DEFCON の自由(むしろカオス)具合が垣間見られるような場でした。


$サイバーエージェント 公式エンジニアブログ
画像: WiFi が使えるブースの奥に進むと・・・




$サイバーエージェント 公式エンジニアブログ
画像: その WiFi 上で通信されているID・パスワードを晒しているスクリーンが!

まとめ


7月26-29日に開催された DEFCON20 に行って来ました。DEFCON CTF に参戦する sutegoma2 の皆さんについていき、CTF の会場や、DEFCON 全体の様子を見学してきました。


物販ブースや WALL OF SHEEP などに象徴されるように、とても自由な雰囲気で、先述した通り「会議」と言うより「お祭り」と表現するのが適切な雰囲気でした。


DEFCON CTF では、謎のバイナリファイルをどのように、如何に少ない情報から解析を進めるのかと言った技術の一端を垣間見ることができ感動を覚えました。


QCon SF参加レポート(前編)〜Twitter/Facebook/Google〜

$
0
0

こんにちは。アメーバでアプリケーションエンジニアをしている寺本と申します。
2012年11月7日~9日まで、QCon San Francisco 2012に参加してきましたのでレポートさせていただきます。QConは、ソフトウェア開発者向けの世界的なカンファレンスで、年4~5回、世界各地で開催されています。

今回はサンフランシスコのハイアットリージェンシーホテルが会場で、参加者は複数のテーマに沿って同時並行で行われるセッションの中から興味のあるものを選択して聴講していきます。3日間のカンファレンス期間を通じて、延べ18セッション程度を聞いた形になります。

全てを紹介することはできませんが、今回は興味深かったセッションについて、前編、後編に分けていくつか紹介させていただきます。前編は、私、寺本がお送りします。

なお、当日の発表資料は、こちらからダウンロードできます(2012年11月末時点)ので、興味の有る方は是非どうぞ。

それでは、早速セッションの紹介に移りたいと思います。私は、Twitter、Facebook、Googleの中の人のセッションを紹介します。長文ではありますが、とても興味深い内容だと思いますので、是非最後までご覧ください。

Timelines at scale
~Twitter 1日4億件のツイートの裏側~

Raffi Krikorian, Senior Director of the Platform Services group, Twitter

Twitterは、世界で最大級のタイムライン配信システムを運用しています。通常状態において、ツイート、ソーシャルグラフの変更、ダイレクトメッセージなど、秒間数千ものイベントを受け取っていて、これらは、Disk、インメモリのタイムライン、email、モバイルデバイスに配信される必要が有ります。これらを捌くためのインフラを構築、管理、デバッグするのは、Twitterエンジニアの大きな挑戦です。このセッションでは、Twitterのアーキテクチャを理解するため、ユーザーのツイートの裏で行われる処理とアーキテクチャの説明がありました。

①ツイートをユーザーのタイムラインに配信する
現在のTwitterは、1.5億人以上のアクティブユーザーがいます。生半可なタイムラインアーキテクチャでは簡単に破綻するため、如何に効率よく、スケールするアーキテクチャを構築できるかが、彼らの技術的チャレンジとなります。


ユーザーのツイートにより、Write APIが呼び出されると、Fanoutと呼ばれる処理が行われます。Fanout処理では、ユーザーのフォロー情報を元にして、適切なユーザーのタイムラインにツイートを配信していきます。タイムラインは、メモリ上のみに存在しているとのことで、実際にはツイートID、ユーザーIDなどから構成されるID文字列をRedisに格納しているとのことでした。



個人的に業務でタイムライン型のアプリケーションを扱っていたこともあり、Twitterのアーキテクチャについてはこれまでにも資料を見たことがありましたが、KVSはMemcachedを使っているという認識でした。現在はRedisを使っているということで、どこかで移行した模様です。また、Redisは、格納するデータの型に様々な種類があるのが特徴ですが、TwitterではList型を使っているようです。 



なお、現在のツイートの量は約4億ツイート/日で、平均すると5,000~7,000ツイート/秒、大きなイベントがあると、1万2,000ツイート/秒を超えてくるそうです。これに対し、これらのツイートにより発生するタイムラインへの配信件数は300億配信/日、30万配信/秒です。

つまり、秒間5,000~12,000程度のツイートの裏で、Fanout処理により秒間30万のRedisへの書き込みが発生しているということになります。30万/秒の書き込みですから、相当なものです。

一般的にフォロー関係の存在するタイムライン形式のアプリケーションでは、多数の人間にフォローされている人間が投稿すると、全てのフォロワーのタイムラインに書き込みが発生するため、処理に時間を要します。Twitterでも、オバマ大統領、Lady GaGaといった多数のフォロワーを抱えるセレブリティのツイートに関しては、Fanout処理に時間がかかるとのことで、彼等にTwitter上で頻繁に会話されるととんでもないことになると冗談まじりに話していたのが印象的でした。


②ツイートをリアルタイム検索できるようにする
ツイートをリアルタイムで検索できるようにするための仕組みとして、Earlybird、Blenderが紹介されていました。

Earlybird、Blenderについては、Twitter社のエンジニアブログで記事になっていますので、興味のある方は是非ご覧ください。


また、Krikorian氏は、片手にリモコン(?)を持ち、必要最小限の文字で構成された資料に対して、終始滑らかな語りでプレゼンを展開していくというカッコいいものでした。同僚の佐野氏も、プレゼン無双だと絶賛しておりました 笑





Building for a Billion Users from Silicon Valley
~Facebook エンジニアの生産性向上に向けた取り組み~

David Mortenson, Engineering Manager, Facebook


サービスの成功に伴ってエンジニアが急増していく状況のFacebookにおいて、エンジニア1人当たりの生産性を維持・もしくは向上させるための試みについてのお話です。エンジニアリングマネージャーのMortenson氏が大きく3つのチャレンジについて話してくれました。

チャレンジ①新入社員を最速で戦力化させる
Facebook社では、サービスの成長とともに急激にエンジニアが入社していました。2008年頃には、100人前後だったエンジニアリングチームは、2012年には1,000人を超えています。毎月入社してくるエンジニアが一人前のパフォーマンスをするようになるでは、一定の時間がかかり各チームはこれらのエンジニアを成長させることにたくさんの時間を使っていました。


これに対するソリューションとして、新入社員に対して6週間程度のブートキャンプを実施するようにしたとのことです。

ブートキャンプのゴールは以下です。
・カルチャー面、技術面で、彼らが早期に軌道に乗るようにキャッチアッップさせる
・コードベースのたくさんの異なるエリアを開示し、触れさせる
・彼らの情熱と能力が最も活かせるチームを見つける
・新入社員のエンジニアに、出来るだけ速く有益な仕事をしてもらう

Mortenson氏によると、実際の内容は以下のようなものだそうです。
1日目
・ブートキャンプメンバーとの顔合わせ
・開発サーバーのセットアップ
・Facebookのコードベースのコアコンセプトを学習する
・最初のタスクをこなす

1週目
・Facebookで仕事のやり方についてのトレーニングセッションに取り組む
・自分の開発環境をカスタマイズする
・ブートキャンプの仲間と一緒に過ごす
・最初のタスクを完了させ、Commitする

2~4週目
・自分の最初にした仕事がリリースされ、十億人に届く
・バックエンドService、モバイル、ネットワーク、データセンターデザインなどに関するセッション
・Facebookのスタックを横断するブートキャンプタスクの実施

4~6週目:チームの選択
・エンジニアを必要としているたくさんのチームについて学ぶ
・自分が最も興味を持っているチームのエンジニアと合う
・トップチームのための、ブートキャンプタスク
・自分の能力と情熱が最大限マッチするチームを選ぶ

Mortenson氏は、ブートキャンプの成果について以下の様にまとめました。
・約1,000人のエンジニアが卒業
・参加者からのフィードバックは一貫して素晴らしい
・これまでより速く戦力化するようになった
・エンジニアを成長させるためのコストが著しく下がった
・新エンジニアが周囲に認知され、友達を作るまでが早くなった
・Facebookのカルチャーを理解する大きな助けになった

弊社サイバーエージェントもこの数年目覚ましい速度でエンジニアが増えており、Facebookでの取り組みは非常に参考になるものでした。

チャレンジ②開発速度を速く維持する
以下の理由に基づき、開発のあらゆる作業における待ち時間を、最大限短縮するための努力を行っているとのことでした。

・集中とフロー状態は、高い生産性のために極めて重要
・開発作業において待ち時間が5秒以上の作業は軽度のコンテキストスイッチを発生させる
・開発作業において待ち時間が2分以上の作業は重度のコンテキストスイッチを発生させる
・これらは生産性を著しく悪化させるもので、如何なる代価を払っても避けるべきものである

1つの例として、開発環境のページロード時間の短縮の取り組みについて話をしてくれました。また、その他の重要なエリアとして、以下のようなものを挙げてくれました。
・ソース管理
・テスト
・静的分析
・タスク/バグトラッキングシステム
・コードレビューツール
・リリース

エンジニアとして開発をしていると、待ち時間が如何に開発の集中力を削ぐものであるかは実感を持って理解できます。特に開発で繰り返し実行する上記のような作業については、少しでも待ち時間が短くなる努力をすべきだなと感じました。

チャレンジ③自動テストによる品質向上
2008年頃までは、Facebookのコードは比較的シンプルで理解しやすいものだったようです。変更が引き起こすバグの可能性についてもある程度予測できたため、テストは開発者が個人のサンドボックス環境で行っていたとのことです。

しかし、2009年頃には、以下のような理由で、他のエンジニアの作業を阻害したり、本番環境にリリースされるバグが増え始めたようです。

・開発者がますます増加。300名程度に達した
・Gitの導入によって、並行作業がますます増えた
・コードの複雑性が一人の頭に入る限界に達した

そこで、以下のようにして自動テストが導入されたとのことです。

・テストを書きやすくするためのフレームワークの作成
・エンジニアの作業フローに単体テストを導入
・当初は、テストを書くのを一つの重要な領域に絞った
・キーとなるチームの中に、エキスパートを育てて行った
・障害の発生を、テストを書くよう奨励する機会として活用した
・ブートキャンプ参加者への教育

これによって最初の3年で3000程度のテストが書かれ、テストがカバーしている領域における不具合や、ユーザーに影響を与える欠陥は減少しました。しかし、その後テストの増加に伴い、失敗するテスト数も増加していきました。最も悪い時期で、5,000程度のテストに対して、100程度のテストが失敗しています。彼らは失敗するテスト数の0に近づけるために、以下のような努力をしています。

・価値が低く、いつも失敗している数百のテストを削除した
・1週間以上失敗し続けているテストを無効化した
・断続的に失敗するテストを無効化した
・失敗しているテスト用の分析ツールを構築
・信頼できないテストを書くチームと一緒に働き改善した

これにより、一回のテスト実行で失敗するテストの数を40~50程度に減少させることに成功したようですが、さらに減少させるためにPhabricatorという開発者向けのコミュニケーションツールを使っています。Phabricatorは、Facebookが開発したオープンソースのツールで、コードレビューツールから、バグトラッキングシステムまで様々な機能が搭載されています。

これらの複合的な努力と工夫の結果、現在では9,000以上のテストに対して、失敗するテストの数を20程度に抑えることに成功しています。



テストを書くのは大事なことで、自分のチームでも単体テストを書きますが、Facebookでの事例と同様に、気を抜くとたまに失敗するテストが出てきます。しかしながら、サービスが成長し、コードの規模が大きくなっても彼らのように全てのテスト成功することに執着する姿勢は忘れないようにしたいものです。

最後に、これらの取り組みは当初の目的であるエンジニアの生産性向上に照らし合わせて、結局のところうまくいったのかについて、Mortenson氏はコードベースへのコミット数を使って説明してくれました。エンジニアの増加と共に、コミット数も順調に伸びていて、当初の生産性を維持・もしくは向上させていることが分かります。






The Mobile Web Developer's Tool Belt
~Google スマートフォンディベロッパー向けのツール群紹介~

Pete LePage, Developer Advocate, Google


スマホディベロッパー向けの有用なツール群や、Tipsをたくさん紹介してくれました。
こちらのプレゼンについては、下記のページでも公開されていますので、是非ご覧ください。
http://goo.gl/kIfUe

ここではいくつか気になったものをご紹介します。

Sublime Text 2
最近話題のSublime Text 2ですが、LePage氏も一押ししていました。とにかくベタ褒めしていた印象です。Webディベロッパーの方は是非試してみてはいかがでしょうか。


www.mobile-patterns.com
モバイル向けのUIについてインスピレーションを得るためのサイトとして紹介されていました。様々なUIパターンが登録されていて、UIカタログの様に使えそうです。


pttrns.com    

こちらは、iOS向けアプリのUIカタログのようです。


JSConsole
スマホ実機でデバッグができるようになるサービスです。

HammerJS
タップ、ダブルタップ、スワイプなどのマルチタッチジェスチャーを用意に使えるようにしてくれるライブラリです。

Lawn Chair
インデックスDB、WebSQL、ローカルストレージなどに対して、それぞれのサービスの実装を抽象化して、シンプルなAPIを提供してくれるライブラリです。

他にも本当にたくさんのツールやTipsが紹介されており、とにかく実践的な内容のセッションでした。是非、オリジナルの資料を確認してみてください。きっと何かしら有用な情報があると思います。



QCon 全般について
個人的には、エンジニアとしていつか本場に行って、一流のエンジニアリングの世界を肌で感じてみたいという漠然とした夢がありました。プレゼンをしているエンジニアは世界でも一流の方々ばかりで、話している内容も素晴らしかったですし、プレゼンも極めて上手な方が多かったです。

英語のリスニング力が不足しているせいで、細部の情報を相当聞き漏らしているため、かなりもったいないことをしたと悔しい想いで一杯ではありますが、本当に良い刺激をもらい、少しでも彼らに近づきたいとモチベーションが向上しました。日々の業務に意識高く取り組むことで成長し、いつかまたこのような場に参加したいと思います。

さて、次回は後編として、QConに一緒に参加したインフラエンジニアの佐野さんからレポートをお届けします。お楽しみに!


(おまけ)
カンファレンスの後、週末を使ってシリコンバレーまで足を伸ばしてみました。
佐野氏と一緒に、Apple、Google、Facebookの本社を見て回ることができました。


こちらはクパチーノにあるApple本社。本当はここのAppleストア限定のAppleロゴ入りグッズが色々と買えるはずだったのですが、週末ということで閉まっていました。無念orz



こちらはマウンテンビューにあるGoogle本社。とんでもなく広大な敷地に、無数の建物が有りました。マウンテンビューは一つの街なのですが、半分がGoogleらしいです。




パロアルトにあるFacebook本社。本社前にはこんな看板が有ります。観光客が何人かいて、この前でいいね!のポーズをしてました。僕らももちろんやりましたが 笑


QCon SF参加レポート(後編)

$
0
0

こんばんは。Amebaで雑用をしている佐野と申します。
前編を執筆した寺本に引き続き、QCon San Francisco 2012の参加レポート後編を執筆させていただきます。

3日間で20セッション近く聞いたのですが、特に印象的だったものについて概要をレポートさせていただきます。

1. Architectural patterns for high availability
 → Netflixのアーキテクチャについて。
   NetflixはWebでDVDのレンタルを提供するサービスを展開していて、
   DVDはストリーミングでも視聴可能。
   そのトラフィックは北米でトップ(モバイルのトラフィックは除く)。
    下りトラフィックは、北米の下りトラフィックの33%を占める(ちなみにyoutubeは14.8%)。
   そのシステムの中核はAWSとCassandraでした。
2. Scaling Pinterest
 → Pinterestのアーキテクチャについて。Pinterestは写真共有のSNSで、
   サービス開始から2年でトラフィックが爆発的に伸びました。
   スタートアップからのアーキテクチャの変遷についての話が聞けました。
3. 全体的な感想
 → 全体を通しての感想や、他の参加者との交流などについて。

1. Architectural patterns for high availability

Adrian Cockcroft, Director of architecture for the Cloud Systems team at Netflix


Netflixのアーキテクチャの話。ぶっちゃけNetflixのエンジニアブログの内容が多かったような気もするwあと、昨年度のQConでも似たような内容を発表していますw需要があって今年も登壇したのかな?

僕個人としては仕事でCassandraを触っている関係もあり、Cassandraを大規模に扱っているNetflix社のセッションはカンファレンス前から目星をつけていました。Cassandra on AWSの大規模運用の事例として面白かったです。実際の図やアーキは公開されているスライドを見ていただくとして、ここでは印象に残ったトピックについて書きます。

netflix


① AWSとCassandra

上でも述べた通り、Netflixのアーキテクチャの肝はCassandraとAWSという印象です。想像以上に大規模な構成でした。

US-west, US-east, EU, (+おそらくアジア圏にも)、世界各地のAWSリージョンにインスタンスを展開。Cassandraクラスタは1リージョン内に3つのゾーンを跨いでLB(ELB)で負荷分散しており、規模は次の通り。

・500ノード以上のCassandraノード
・50のCassandraクラスタ
・もっとも大きいクラスタは72ノード
・1クラスタあたり250 K write/secを捌いている

数あるデータストアの中からCassandraを採択した理由は、高可用性であることに加え、会社としてJavaが得意だからとのことです。
高可用性を謳っているデータストアは他にもありますが、Javaで書かれているミドルウェアならいつでもハックできるから、ってことなんでしょうね。

② 自社製OSSで運用

これだけの規模のものをご丁寧に手運用しているわけではないですね。やはり。
自社製のOSSで運用管理を行っている模様です。

・Priam
 https://github.com/Netflix/Priam

詳細はしっかり見てないのですが、PriamはCassandraのトークンの管理、障害ノードのオートリプレイス、S3へのバックアップ・・・and moreを行うツールのようです。
また、Netflixのgithubには他にも様々なツールやライブラリが公開されています。セッションではPriamの他に自社製のCassandraのJavaクライアント、Astyanaxも紹介していました。

③ SSD

SSDな環境(hi1.4xlargeインスタンス)にCassandraを移行しつつあるようです。SSDの効果は「Awesomeだ!」と言ってました。
実は俺も最近試しにSSDな環境(AWSではなくオンプレ)にCassandraを乗せてみたんですが、俺んトコはあんま効果なかった・・・。チューニングパラメータやHW構成が最適じゃないんだと思う。SSDの効果があるという事例は心強いので、もうちょい深堀してみたいです。

2. Scaling Pinterest

Yashwanth Nelapati, Cloud Balrog @ Pinterest& Marty Weiner, Cloud Ninja @ Pinterest


Pinterestのアーキテクチャの変遷について、二人のエンジニアYashwanth NelapatiとMarty Weinerが登壇。自らの肩書きを「クラウド忍者」とか言っちゃってるトコが小粋ですね。俺もクラウド虚無僧とか名乗ろうかなwww

スモールスタート→種々のミドルウェアが導入されて複雑化→最終的にシンプルなWeb+DB+cacheなアーキにした。という内容。
なぜ最終的にシンプルにしたかをちゃんと理由付けしながら話してくれたのが良かったです。
先程紹介したNetflixがオートシャードなCassandraクラスタをプラットフォームの肝としているのに対して、Pinterestは古典的なMySQLのシャーディングを用いているのが対比として面白い。
ちなみにエンジニアを募集しているようです。腕に覚えのある方は応募してみてはいかがでしょうか。サーバサイドはPython(Django)の模様。

pinterest


①アーキの変遷

以下、スライドより引用+メモ。スモールスタート→複雑化→最終的にはシンプルな構成を成しています。

2010年
・ rackspace
・1 small web engine
・1 MySQL db
・1 Engineer

→ いわゆるWeb+DB構成のスモールスタート。

2011年
· Amazon EC2 + S3 + CloudFront
· 1 NGinX, 4 Web Engines
· 1 MySQL DB + 1 Read Slave
· 1 Task Queue + 2 Task Processors
· 1 MongoDB
· 2 Engineers

→ AWSへの移行。nginxやMongoDBなど使用しているプロダクトが増える。

· Amazon EC2 + S3 + CloudFront
· 2 NGinX, 16 Web Engines + 2 API Engines
· 5 Functionally Sharded MySQL DB + 9 read slaves
· 4 Cassandra Nodes
· 15 Membase Nodes (3 separate clusters)
· 8 Memcache Nodes
· 10 Redis Nodes
· 3 Task Routers + 4 Task Processors
· 4 Elastic Search Nodes
· 3 Mongo Clusters
· 3 Engineers

→ ノード数の増加につれてミドルウェアの種類も増える。

2012年1月
· Amazon EC2 + S3 + Akamai, ELB
· 90 Web Engines + 50 API Engines
· 66 MySQL DBs (m1.xlarge) + 1 slave each
· 59 Redis Instances
· 51 Memcache Instances
· 1 Redis Task Manager + 25 Task Processors
· Sharded Solr
· 6 Engineers

→ ここでMongoDB、Membase、Cassandra、Elastic searchなどが消える。nginxも消えてる。
  この頃からELBを導入しているので、おそらくはnginxはL7プロキシとして使っていたのかな?

2012年10月
· Amazon EC2 + S3 + Edge Cast, Akamai, Level 3
· 180 Web Engines + 240 API Engines
· 80 MySQL DBs (cc2.8xlarge) + 1 slave each
· 110 Redis Instances
· 200 Memcache Instances
· 4 Redis Task Managers + 80 Task Processors
· Sharded Solr
· 40 Engineers

→ そして現在。Web+DB+cacheといったよくありがちな構成に落ち着く。


② なぜこの構成を選んだか

詳細はスライドを見ていただくとして、主に↓の理由のようです。

・AWS:数秒でインスタンスが作れる。ELBやroute53のような便利なマネージド・プロダクト。
・MySQL:枯れている。致命的なデータロストは発生しない。Perconaのツールが良い。
・Memcached:枯れている。落ちない。早い。
・redis:便利なデータ構造。ほとんど不具合はない。

プロダクトの採択に確実性と安定性を重視しているのが見て取れます。
MySQLについて「致命的なデータロストは発生しない」ってことについては、ソレあったらデータストアとして失格だろ!wって思いましたがw

③ なぜクラスタリングよりもシャーディングを選んだか

Cassandraのようなデータストアの良さ(高可用性、スケールする、自動分散etc)を認めつつも、
pinterestはMySQLのシャーディングでデータを管理しています。
その主な理由としては、

・(クラスタリングは)複雑である点(アーキテクチャが?)
・(クラスタリングは)アップグレード時が怖い
・(クラスタリングは)実用化できるエンジニアがまだ少ない

などを挙げています。

3. 全体的な感想

全体を通しての感想です。

① とにかく刺激になった

世界最大規模のトラフィックを捌いているWebサービス企業の中の人や、著名なハッカーの話を生で聴けたこともあって、とにかく刺激になった。
かの有名な「ブリュワーのCAP定理」の提唱者であるブリュワー氏本人(GoogleのVP、カリフォルニア大学バークレー校教授)が来てCAPとBASEの話をしてくれたり、SPDYの開発者がSPDYとHTTP2.0の話をしてくれたりね。
僕らはGoogleマップで場所を調べて、iPhoneで写真を撮り、TwitterやFacebookに投稿する、、、といった行動を当たり前のようにしています。少なくとも俺はそう。まさにカンファレンスで登壇した人とその仲間達が世界を作っているんだな、と思いました。
技術的な収穫も多かったです。プライベートの時間も使って日々技術情報をキャッチアップしているハズだったんだけど、やはり知らないことは多く、もっとウマく情報を集めて糧にしていかないとなー・・・って思った。
例えば↓のringmark。こんなのあるんだね。知らなかった。(ツール類については前編で寺本も挙げています。)

・ringmark
 http://rng.io/

Facebookが公開しているHTML5の動作チェックツールです。アクセスするだけで、そのブラウザがHTML5にどこまで対応しているか調べることができる。
OSS(https://github.com/facebook/rng.io)なので自分で機能の拡張もできます。
※ 機能のテストはしません。
  あくまでもブラウザのHTML5への対応状況をチェックするだけです。

② 懇親会

初日の夜に懇親会がありました(といっても毎晩オープンスペースやホテルのレストランでお酒が振る舞われる懇親会っぽいものがありましたが)。
英語力が不安だったのですが、なんとか会話することができて良かったです。場所柄アジア系が珍しくないということもあり、他の参加者も「どんな会社で働いてるんだ?ところでちょっとトイレ行ってくるから俺の酒持っといてくんない?」といった具合でフランクに話しかけてきてくれました。海外の技術者と会話する良い機会だったので、本当はもっとガッツリ技術の話をしてみたかったのですが、英語力ががが・・・。英語ができなくて本当にもったいなかった。

③ メシ

カンファレンス中の3日間は朝から晩までほとんどをホテルで過ごし、朝昼晩メシ、お菓子、コーヒー、夜の酒代などをすべて無料で楽しめました(参加費に含まれている)。
しかしながら一日中カンヅメなのは息が詰まるので、夜はフィッシャーマンズワーフやらユニオンスクエアに繰り出して、いろいろ飲み食いしました。アメリカンサイズのハンバーガー、フィッシャーマンズワーフでカニ、クラブチャウダー(クラムチャウダー)、アメリカンイタリアン(?)やらいろいろ楽しめました。

カニ!↓


アメリカ料理ってあまり美味しい印象なかったんですけど、美味しいものは美味しいですwクラムチャウダーとカニは本当にウマかったです!あとワインも!
でもまぁメシは総合的に見てやっぱ日本のメシが一番ウマいっす。メシウマ。


年始の挨拶+CROSSの紹介(お年玉抽選つき)(追記あり)

$
0
0

あけましておめでとうございます。

除夜の鐘ならぬ除夜のアラートで新年を迎えたエンジニアの方もいらっしゃるかもしれませんが、新年ということで心機一転システム改善頑張って行きましょう。

今年もサイバーエージェント公式エンジニアブログは、技術情報や、弊社のエンジニア環境、イベントレポートなどをお伝えして参ります。

さて、早速ですが「エンジニアサポートCROSS 2013」というイベントの紹介をさせていただきます。

このイベントは、"Webテクノロジーに関わる人たちが集まり、Web技術について横断的に、過去・現在・未来について縦断的に語り合うイベント"となっています。普段なかなか会えない様々な「技術」「年代」「個人・企業」のエンジニアが参加されますので、興味を広げるいい機会になるのではないでしょうか。公式サイトは http://www.cross-party.com/ になります。

弊社からも以下の4名のエンジニアがスピーカーとして参加します。

大原 一輝
株式会社サイバーエージェント アメーバ事業本部 Ameba Technology Laboratory データマイニングエンジニア
登場セッション:
 「データ理解を助けるビジュアライゼーション」 http://www.cross-party.com/programs/?p=134

桑野 章弘(@kuwa_tw)
株式会社サイバーエージェント アメーバ事業本部 ピグディヴィジョン コアシスG社内システム運用、ホームページ作成から、ML、ブログサービスなどのサーバ構築運用を経て2007年にサイバーエージェント入社後は、アメーバビジョン、アメーバブログ、ピグ、ピグライフなどのサービスの構築運用を担当している。
登場セッション:
「継続的システム運用のゲンバのハナシ」http://www.cross-party.com/programs/?p=140

成田 俊(@oranie)
株式会社サイバーエージェント他業界を経て2006年頃からエンジニアとして働き、現在はスマートフォン・プラットフォームサービスのインフラチームで勤務。主にサービス運用、改善でというものであればなんでもやる。
登場セッション:
「継続的サービス改善のゲンバのハナシ」 http://www.cross-party.com/programs/?p=141

安田 征弘
株式会社サイバーエージェント アメーバ事業本部 Ameba Technology Laboratory2008年サイバーエージェント入社。現在はアメーバサービス内の検索、レコメンデーション、スパムフィルターなどの開発運用を担当。
登場セッション:
「検索CROSS」http://www.cross-party.com/programs/?p=366

今回は、いつも弊社エンジニアブログを読んでくださっている読者の皆様へのお年玉として抽選で3名様に上記イベントのチケットをプレゼントさせていただきます。

(追記)こちらのチケットはCROSS実行委員会様より提供していただきました。CROSS実行委員会様ありがとうございます!


応募方法(締切: 1/13 24時)
1. 本ブログの公式twitterアカウント(@principia_ca)のフォローをお願いします
2. 本ブログの公式twitterアカウント(@principia_ca)宛に 「CROSSいきたい」 とリプライをお願いします

当選の発表は当選者へのtwitterのDMによる連絡(1/15)をもって代えさせていただきます。
ご応募お待ちしております。

WebSocketで監視もリアルタイムに

$
0
0

こんばんは。社内ニートの佐野と申します。所属はいちおAmebaのインフラチームです。Twitterもやっていますがフォローする価値はないです。つぶやいているのはメシと酒の話と下ネタだけです。
最近、組織改編とかもろもろありましてこのたびは雑用からニートになりました:(;゙゚'ω゚'): あまり目立たないように生きてたんですが、何気にこのブログへの登場は3回目になります...。前回は2012年12月に「QCon San Francisco 2012の参加レポ」を書かせていただきました。その前は2012年5月に「Virident FlashMAXの検証」として名前だけ登場しました。なんか、ニートだけど会社に貢献してる気がしてきた(^ρ^)

そんなわけで以前WebSocketを使った監視ツールもどきを作ったので、それについての簡単な説明と、各種技術要素(Python, Jolokia)のTipsを紹介させていただきます。
WebSocketというと特にフロントエンドを生業とするエンジニアは早い段階から触れているかと思います。なので、エンドユーザ同士のチャットや通知機能の実装に使われるものという印象を持たれる方も多いんじゃあないかと思いますが、これを監視に応用します。
自分のブログに書いたエントリの焼き増し記事になってしまうのですが、WebSocketを監視ツールに使うのアリだな...ってことが伝わればうれしいです。


作ったもの

こんなの↓


Cassandraの全ノードのPendingTask値(※)をリアルタイムでチェックすることができます。値が一定以上を超えると色が変わります。

※ CassandraのPendingTask値は処理の滞留数を表します。PendingTask値の高いノードは処理が詰まっているということになります。Cassandraのアーキテクチャや挙動については弊社のCassandra芸人達がきっと解説してくれるハズ(チラッチラッ)。


なんで作ったのか

Cassandraの全ノードのPendingTask値の一覧を見たいよね って話から始まりました。
もちろんnagiosなりで監視してはいるのですが、調査に入ったときには既に値が落ち着いてしまっていたり、Cactiやmuninなどのツールではグラフ描画されるまでに少し時間がかかってしまいます。そこで

・今まさに何が起きているかがリアルタイムに見たい
・Cassandra90ノード分を1ビューで見たい
・グラフ描画よりは数値表示が良い(ノード数が多すぎるのでグラフだと見づらい。また、スパイクがあるとグラフが潰れてしまう。)
・数値が高くなったら色を変わると良い。

という要件を満たすものを作ってみよっか、という感じで作りました。実は最初はAjaxのポーリングだったのですが、「ツールにアクセスするとMacBook Proのファンがッー!ブラウザがッー!」とクレームを受けたのでやめました。90ノードを数秒間隔でポーリングにしたらそらそうなるよね...wこれもWebSocketにした理由でもあります。


ツールの構成

こんな感じ↓


ツールの動作なのですが、ブラウザでServerにアクセスしてWebSocketを張ります。
別プロセスで動くCollectorがnode(※)を巡回してPendingTask値を収集し、データをHTTPでServerに送ります。
Serverはデータを受信すると値をブラウザにプッシュします。

※ nodeはCassandraノードのことです。PendingTask値収集のためにJolokiaというライブラリ(後述)を仕込んでいます。

ここまでは自分のブログの焼き増し...(;-公-)


Tornado

ここからは主にTipsになります。サーバの実装にはTornadoを使いました。
TornadoはFriendFeedが開発したWebフレームワークで、シングルスレッド/ノンブロッキングIOで動作するのが特徴です。現在はFriendfeedを買収したFacebookがオープンソースとして公開しています。
なぜTornadoを採択したかというと...僕がTornadoの使い方をある程度知っていたという理由を筆頭に、WebSocketハンドラが標準で付いていること、ツール用のサーバが低スペックな仮想マシンのため省リソースであること、が挙げられます。あと、最近はPythonを書くときは最新の3.3系を使うようにしているのですが、Tornadoはちゃんと対応してます^^
ソースコードは次のとおり、シンプルにWebアプリケーションが書けます。

------------------------------------------------------------
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
import tornado
from tornado import websocket, web, ioloop

ws_client = []

class IndexHandler(tornado.web.RequestHandler):

    def get(self):
        self.render('index.tpl')

class SocketHandler(tornado.websocket.WebSocketHandler):

    def open(self):
        if self not in ws_client:
            ws_client.append(self)

    def on_close(self):
        if self in ws_client:
            ws_client.remove(self)

class ApiHandler(tornado.web.RequestHandler):

    @tornado.web.asynchronous
    def get(self, *args):
        self.finish()
        id = self.get_argument('id')
        value = self.get_argument('value')
        data = {"id": id, "value": value}
        data = json.dumps(data)
        for cl in ws_client:
            cl.write_message(data)

app = tornado.web.Application([
    (r'/', IndexHandler),
    (r'/ws', SocketHandler),
    (r'/api', ApiHandler),
])

if __name__ == '__main__':
    app.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
------------------------------------------------------------

簡単にソースコードを説明します。
ブラウザがhttp://xxx.xxx.xxx.xxx:8888/にアクセスするとindex.tpl(※)を返します(IndexHandler)。
SocketHandlerはWebSocketコネクションを管理します。
ApiHandlerは/api?id=xxx&value=xxxを受け取ると、接続しているWebSocketクライアントにメッセージを配信します。

※ Tornadoにはテンプレートエンジンも備わっています。拡張子が.tplなのは適当で特に理由はないです。index.tplには90ノード分のIPやら何やらをtableタグに記述するのですが、

------------------------------------------------------------
<tr id="cas1">
<td> 1 </td><td> xxx.xxx.xxx.1 </td><td id="ptask1"> 0 </td>
</tr>

・・・

<tr id="cas10">
<td> 10 </td><td> xxx.xxx.xxx.10 </td><td id="ptask10"> 0 </td>
</tr>
------------------------------------------------------------

などと律儀に書いているわけもなく、
 
------------------------------------------------------------
{%for n in range(1,11)%}
<tr id="cas{{n}}">
<td>{{n}} </td><td> xxx.xxx.xxx.{{n}} </td><td id="ptask{{n}}"> 0 </td>
</tr>
{%end%}
------------------------------------------------------------

などとすることで、スッキリ短く記述できます。


Jolokia

CassandraからPendingTask値を抜くにはJolokiaを使っています。JolokiaはMBeanにHTTPでアクセスできるようにしてくれるJavaのライブラリです。レスポンスはJSONで返ってきます。PendingTask値はCassandra付属のnodetoolコマンドや、MBeanから取得できるのですが、やっぱRESTが楽ですよね。例えば次のようにJVM起動オプションに渡してあげます。下記の例の場合、8778ポートでMBeanにHTTPアクセスできるようになります。

JVM_OPTS="$JVM_OPTS -javaagent:/usr/local/lib/jolokia-jvm-1.0.6-agent.jar=port=8778,host=xx.xx.xx.xx"

8778ポートにHTTPリクエストを投げてやることでMBeanに格納された各種パラメータを取得したり、FullGCを発生させたりすることができるようになります。Cassandraに限らずJVMベースのミドルウェアやアプリケーションを使っている場合は有効活用できます。

・例1:JVMのメモリ使用量を取得する場合
 http://xxx.xxx.xxx.xxx:8778/jolokia/read/java.lang:type=Memory
・例2:ReadStageのPendingTask値を取得する場合
 http://xxx.xxx.xxx.xxx:8778/jolokia/read/org.apache.cassandra.request:type=ReadStage


Collector

これはOSSでもなんでもなくて、単に情報を収集するための独立したプロセスです。これがjolokia経由でCassandraのPendingTask値を抜いて、TornadoのHTTPの口(/api)にPendingTask値を送りつけます。HTTPが投げられればいいので言語はなんでも良いです。また、各CassandraノードにAgentとして仕込んでも良いし、tornadoが稼働するサーバに同居させても良いし、どっか別のサーバにあっても良い。
今回はPendingTask値を収集していますが、CPU使用率などのOSの情報を収集するようにすればそれを表示できるようになります。



以上がツールの紹介と各種技術要素のTipsになります。
また、冒頭でも述べた通り、WebSocketというとフロントエンドのエンジニアの技術と思いがちなのですが、むしろ監視やモニタリングなどシステム管理を担当しているような運用寄りのソフトウェアエンジニアも習得しとくといいんじゃないかと思います。


最後に

弊社は個人個人が自由な言語を使っています(逆に言うとまとまりがない)。そんな中、僕はPython推しなので、社内でPython勉強会を催してみたり地味に布教活動にいそしんでおります。そして、ようやく弊社にもGitHub Enterpriseが導入されました!GHE!GHE!GHE!GHE!
導入されてからはクローズドな自作ツールやソースコードの断片はGHEに載せるようにしてます。これで社内の開発力が活性化するとうれしいですね。

開発も運用もできるエッジの効いたエンジニア募集中!!!

cassandra運用監視小ネタ集

$
0
0

はじめまして。サービスインフラというチームに所属している@oranieと申します。前回の弊社 佐野からCassandra芸人による他のネタも・・・という話があったのでこれ幸いとCassandraネタでお茶を濁そうと思っています。そもそも他にもネタを持っているエンジニアがいる中で僕に執筆依頼を出す時点で、なんて節操の無い寛容な人達だとビックリしました。多分ダーツかなんかで決めたんだと思います。


入社以来、なぜか弊社でデファクトとして使われているデータストアのMySQLにもほとんど触らず、ひたすらCassandra運用とか他には仕事チャット上で一人だけ勝手に盛り上あがって麻呂のAAを貼りつけたり等の社内ピエロ雑用をやっています。おかげさまでエキサイティングな日々を毎日送る事が出来た為、酒の量が一時期増えたのと多少は小ネタを覚えたのでまだ運用していない方に少しでも運用・監視周りのお役に立てれば幸いです。

構築

まずCassandraサーバの構築ですが、弊社ではrpmパッケージ作成チームがいるのとchefでの構築がだいぶ浸透しており、datastaxさんが公開しているrpmを使うのではなく、独自rpm+chefで一発で構築です。唯一手で変更するところはcassandra.yamlに記述するtokenを状況に応じて記述しています。
そんなレベルなので、正直構築については余り特筆事項が無いんですよね・・・。チューニング周りについてはHWスペックやCassandraへのデータアクセスパターンなどと兼ね合いがあるので、よしなに色々試していますという感じです。
Cassandraを使う上でどんな環境でも共通して出てくる問題としてあえて挙げると、ノード数が増えてきた時に各ノード間のgossipがタイムアウトする自体が発生した為、phi_convict_thresholdを長め(デフォルト8- > 12)に設定しました。ここはある程度のノード数になったらログをチェックした方が良いと思います。
ヒープ領域などはdatastatx製rpm内に色々と設定、計算してくれるcassandra-env.shという起動時に実行するファイルがあり、基本はまずこれで動作をさせてチューニングをするのが一番だと思います。
あと一時期multithreaded_compactionを有効にしていたのですが、これは使用していたVerではまだ不安定な機能だったようで、必ずfalseにしています。

とにかく設定情報が多いのとCassandra特有の設定があるので、datastaxさんの公開しているドキュメントを何度も読んでは忘れるレベルです。
http://www.datastax.com/docs/1.1/configuration/node_configuration
ただこのドキュメントは構築運用時のバイブルに近いモノがあるので、Cassandra運用する方はひと通り読んでは何かあったら該当箇所のパラメータを見直す、というのをやると幸せになれると思います。

運用オペレーション


通常のオペレーションではとにかくnodetoolの使い方を覚えるのが大事ですね。
頻繁に見るものとしては
nodetool ring -> クラスタの状況確認
nodetool compactionstats -> compactionの進捗状況やpendingしているtaskの状況確認
nodetool tpstats -> 各stage毎のスレッド状況やpending状況の確認
nodetool cfstats -> 各column family毎の統計情報確認
辺りをちょこちょこ見たり
nodetool compact (特定のkey space やcolumn familyに対してcomapctionを実行)
nodetool repair (障害復旧時等にデータの修復を実行)
nodetool cleanup (tokenレンジが変わった際に不要なデータを削除する為に実行)
辺りを障害時やノードの状況に応じて実行します。他にも色々と機能があるので、Cassandra運用する場合はまずnodetoolを覚えるのが大事ですね。(大事なことなので二回言いました)

また、全台に対してなんらかのオペレーション(chefの実行とか)についてはjenkinsでジョブを作成して実行しています。

監視

監視については言うまでもなく運用上非常に重要なのですが、どうしても「喉元過ぎれば熱さを忘れる」な事が多く、障害対応が終わると(∩´∀`)∩ワーイとなってしまって、結果的にまた同じような障害を引き起こす可能性があるため、

maro


このようなAAをチャットに貼り付けて見たりしてキャッチーなタスクにする事に日々勤しんでいます。


主な監視周りについて
前回の弊社 佐野が作成したツールももちろん使っているのですが、他にもCassandra監視には以下のツールを利用しています。
・Nagios(死活、閾値監視)
・Cacti(リソース監視)
上記二つは有名ですね。なのでツール自体の詳細はすっ飛ばします。

・Opscenter
http://www.datastax.com/what-we-offer/products-services/datastax-opscenter
これはCassandra監視専用ツールで、datastax社が公開しているツールです。データエクスプローラーやクラスタの状況等も確認出来る統合GUIツールで、まずはこれを使うと良いと思います。余談ですが、クラスタ状況を見る時に、ノード間の状況をリング状に見せてくれる画面があるのですが、
http://www.datastax.com/wp-content/uploads/2013/03/opscenter3.png
Tokenレンジがちゃんと設計されていないクラスタを見るとまるで銀河系のような綺麗な画像が見れます。綺麗ですが運用しているエンジニアは死にます。昔遭遇したのですが残念ながら白目を剥いて精神が崩壊するのをなんとか踏みとどまるのが精一杯だった為、画像キャプチャを取っておらず皆様にお見せする事ができないのが一番の心残りです。あと、今のVerだと監視対象のクラスタに監視データを保存するというなかなかドM厳しい仕様でしたが、最新版だと別に保存出来るようになったようです。これで「監視はしたいが監視をすると監視対象の負荷が上がる」という鶏が先か卵が先か的な問題に終止符が打たれるので何よりですね。

・proteus-monitor
https://github.com/ameba-proteus/proteus-monitor-server
https://github.com/ameba-proteus/proteus-monitor-agent

弊社の名村が開発したツールで、その瞬間のサーバ負荷状況が非常に見やすいツールです。Cassandraはcompaction等の処理が走るとかなりサーバに負荷を与える為、レイテンシが悪化した際にどのノードが負荷が高いか等が瞬時に判断出来る様になりました。おかげさまで他の監視ツールと組み合わせる事で、日中は障害が発生してからプロセス再起動するまでのスピードが1分切るレベルになれました。おかげで再起動職人という称号を貰う事が出来たので、そろそろ特殊技能手当の支給が望まれます。

・GrowthForecast
http://kazeburo.github.io/GrowthForecast/
Cassandraの各種統計値をOpsCenterだけで見るとデータ量の問題やそもそもノードが多すぎると表示しきれない問題があるので、普段から良く見るものは個別に取得してグラフ化しています。perlだとNet::GrowthForecastというモジュールがあるので気軽にグラフ作れますね。kazeburo++  tagomoris++

基本的には上記のツールを利用して運用監視を実施しています。冒頭に述べたNagiosでは死活監視、閾値監視として主に
・Cassnadraに対して処理要求を投げて正常に処理されるか
・各stageのactive threadの状況が適切か。スレッドが全て使い切られている等は無いか。
・各stageのpending値が閾値を超えてストールしていないか
・クラスタ全体の健全性に問題が無いか(各ノード間はお互いをちゃんと生きていると判断しているか)
辺りをCassandra側にはjolokiaを仕込み監視側はperlスクリプトを書いて監視しています。もちろん上記の様な現象が発生し、ノード障害になったので取得するようになりました。人間火傷をしないと大切な事になかなか気づきませんね。

余談ですが、インフラエンジニア内ではどの言語で書いても良いのですがpythonがデファクトになりつつあり、今のチームでは僕ぐらいしかperlで書かない為「お前そろそろ今まで書いたスクリプトpythonに書き直しておけよ。明日までな。」って言われるかドキドキしながら毎日perlで書いています。もし言われたら若手に「君の勉強のために書き直しておいてくれ( ー`дー´)キリッ」と言って書いてもらおうと思います。perlでJavaアプリを監視する場合はjmx4perlとか使うとまだ手軽なのでオススメです。というかちょろっとした監視でJavaアプリ書くとかは重量過ぎてドM過ぎる気がします。もちろんJavaアプリで監視プラグインを書くと、Nagios等の監視タイミングで都度都度実行するようなタイプでは起動コストが高すぎるのも一つの理由です。

リソースグラフなど
Cactiは基本のOSリソース状況、JVMのヒープ状況等を取得しています。ここは基本ですね。

GrothForecastで書いているグラフには
・各ホストの統計値
・各column family毎の各種統計値
(mbeanで言うとorg.apache.cassandra.db辺りの値とか)
というのを出していて、その中でもまあ誰もが知りたくなる各column family毎のデータ量とかをGrowthForecastに突っ込むスクリプトを書いて一定時間毎に動作させています。ハードコーディングしている部分が多いですが、ちょっと変えてあげれば他の統計値とかも取れるので、もし良かったら修正してお使い下さい。良かったらpull reqお待ちしております。perlで書いた言っておきながら全部perlで書くのは大変なので、Linuxコマンドやcassandra付属のnodetoolを一部利用しているレベルです。お察し下さい。
https://github.com/oranie/oranie/blob/master/mon/cassandra_cf_diskspace.monitor.pl
※とりあえず自分のgithub貼っておきます。

障害時
正直ベストプラクティスは探り探りだったのですが、個人ブログに色々と書いた所直接コミッターのyukimさんからアンサーブログを頂きました。
https://gist.github.com/yukim/5086476
基本はここを読んでおくと良いと思います。もしこういう風にやっているよ!という情報があればぜひブログを書いて頂いてCassandra運用情報をどんどん盛り上げていけると良いなーと思います。というか、Cassandraへのデータ操作とかは良く情報あるんですが、運用情報ってなかなか日本語では無いんですよね・・・・。海外だとまずはNetflix社の情報がslideshareにも上がっているので一度目を通しておくと良いかなと思います。
http://www.slideshare.net/greggulrich/cassandra-operations-at-netflix
監視項目でこんな物を見ているとかクラスタの規模等も記載されているのでオススメです。

今後はログ周りの監視や解析がまだまだなのでfluentdを組み合わせたりして、より正確、迅速な監視、レポーティングを実現して安定運用・適切なキャパシティプランニングに繋げる事が出来ればと考えております。また、今後取得した各種統計値等を見るための簡単な管理画面の開発等にも着手出来ればと考えておりました。今の所「データ取れているんだからちょちょいで作れるよね?」みたいな感じで言われたのでJavascript基礎文法最速マスターとかをチラッとだけ見て誤魔化していたら、そうすると心あるエンジニアが「うちのサービス監視ツールを作ろう」という話が出てきたのでシメシメとほくそ笑んでいる感じです。

こんな感じで僕だけアレな感じですが、他のエンジニアは戦闘力で言えば僕の53万倍はしっかりしていますので一緒にCassandraやサービスを運用してみたい!というエンジニアの方は是非応募お待ちしております。





Google IO 2013 report part.1

$
0
0

I am Patrick Boos. I am a developer at CyberAgent, Inc.

Google IO Sessions
It was a great opportunity for me to go to Google IO in San Francisco in May 2013. I have been able to meet great people and learn about the newest trends and technologies. As a Android Developer I was of course interested about everything related to Android. For that reason I mainly followed the Android track and visited many great sessions. Afterwards I will share the points from those sessions that got me interested most. I learned two years ago at my last Google IO, that there is always an empty seat somewhere in the front. I know that by sharing this secret I might risk that this won’t be true anymore next year ;-).
I hope you understand, that I can not share everything said at Google IO here. There is just too much and I do not have the time to write about all of that. But I would like to share a few things that I liked most:

> New Build System for Android
The new build system which uses gradle is very interesting. It is what I have been waiting for for a long time. I have started using Maven because that helped me to accomplish my tasks better. Gradle is not finished yet, but on a very good way to make me switch to it from maven. Gradle seems to be a lot more flexible than maven, but still simpler than maven.

> Android Studio
Since I did the switch to Intellij IDEA last year already, I was very happy to see this change. I recommend everyone to try out the new Android Studio already. You will not regret switching to it. I would never go back to eclipse again.

> Google Play Services update
It is great to see that Google supports us developers by adding new APIs to Google Play Services. This way we can target even old phones without having to wait for them to be updated with a newer Android version.
Those include: Maps v2 (since December), Fused Location Provider, Geofencing, and Activity Recognition (walking, biking, …), Google+ SignIn, GCM updates and lastly APIs for games which includes Game State sync, Leaderboards, Achievements and Multiplayer.

Google IO Sandbox
Besides the sessions there was the Sandbox where many well known companies where present and where one had the chance to talk to many great developers from Google or other companies. Since I could watch the sessions from Japan as well, the Sandbox was a focus for me on the last day of Google IO. I noticed that this was a great decisions because I was able to talk to engineers that were a lot more experienced than I am. So could I learn a lot more about how other engineers approach and solve problems. I was able to talk to gradle developers and learn how I can use it for the tasks that I want to and how to extend or configure it to do the things I want it to do.

Meetups
But there was more than just Google IO. San Francisco offers a lot of great meetups that got me busy in the evenings. Anyone traveling to San Francisco I would recommend to check out meetups and go to as many as possible that are of your interest. I was able to go to 3 meetups and I have really enjoyed them. There were great presentation and especially the people that participated. I meet people that I have worked together over the internet.

Meeting People
You might have noticed already, that wherever I went I was able to meet people. And this is what I would recommend to everyone! If you go to a conference, spend all the free time meeting people! You won’t regret it. Of course you can learn from the presenters of the conference. And you should listen and learn from them. But you can learn a lot from the fellow attendees as well! Don’t miss that chance. If you go to the conference breakfast/lunch for example. Do not search for the empty table. Search for the most crowded table (which has still a seat open) and join it. Get to know the people at that table, ask questions, get to know them.

Google IO 2013 レポート パート1

$
0
0

こんにちは。
私はサイバーエージェントでディベロッパーをしています、Boos Patrickです。

Google IO Sessions
私は今月15日より開催されたGoogle IOに参加して参りました。
すばらしい技術者に会い、最新のトレンドや技術について学び、非常に有益な時間を過ごすことができました。Android Developerとして当然、Androidに関する事すべてに興味を持って多くのセッションに参加して参りました。
今回このブログでは、最も興味深かったセッションの一部をご紹介したいと思います。
Google IOでの経験をできるだけご紹介したい気持ちはやまやまですが、全ては伝えきれないことをご了承ください。

余談ですが、、、二年前に参加した際に発見したのですが、最前列ではいつも空席が見つけられるんです!でもここで話してしまったらもう来年は見つけられないかもしれませんけどね ;)

>Androidの為の新しいビルドシステム
Gradleを使った新しいビルドシステムはとても興味深く、これこそ私がずっと待ちわびていたものでした。
私は効率よくタスクを遂行させるために既にMavenを使い始めておりましたが、現在MavenからGradleに移行している途中です。
GradleはMavenよりもずっとフレキシブルですがとてもシンプルです。

> Android Studio
私は既に去年、EclipseからIntellij IDEAに乗換えておりますが、皆様にもぜひ新しい Android Studioを試してほしいと思います!
絶対に後悔しないと思います。実際私は二度とEclipseに戻りたくありません。

> Google Play Services update
私たち開発者にとってGoogle Play Servicesに新しいAPIが追加されていることは非常にありがたく、それによって私たちは新しい端末を待たずに今日から以下のような新しい機能を試せます。

追加されたAPI: Maps v2 (12月より), Fused Location Provider, Geofencing,
Activity Recognition (徒歩,自転車,,等を認識できる ), Google+ SignIn,
GCM updates
ゲーム用API: Game State sync, Leaderboards, Achievements ,Multiplayer

Google IO Sandbox
セッションの他にもサンドボックスがありました。サンドボックスでは多くの有名企業が居合わせており、Googleや他の企業から来た有能な開発者達と話をすることができました。
セッションは日本からも見ることはできますが、Google IOに来なければこのサンドボックスには参加できません。これが私の最終日の目的でした。参加したおかげで、私よりはるかに経験のあるエンジニアと話すことができ、他のエンジニア達がどのように問題に向き合い、解決しているのかを学ぶことができました。Gradle開発者にも会え、自分のやりたいタスクにどのようにGradleを活用したらよいか、Gradleの拡張の仕方や設定の仕方を学ぶことができました。

ミートアップ
今回のサンフランシスコ出張はGoogle IOだけではありませんでした。サンフランシスコではたくさん興味深いミートアップが用意されており、タイトなスケジュールでそちらにも参加して参りました。サンフランシスコを旅行する際には、事前に興味のあるミートアップをチェックして、できるだけ参加することをお勧めします!
私はなんとか3つのミートアップに参加し、素晴らしい出会いやプレゼンテーションを楽しんできました。ネット上で一緒に仕事をしたことのある方々にも会えました。

人との出会い
このように、どんな場所でも人との出会いが必ずあります。
もうお気づきかと思いますが、この出会いこそ、私が皆さんに大切にしてほしいことなのです!
カンファレンスに行かれた際には全ての空き時間を人に会うことに使ってほしいと思います!
もちろん、カンファレンスのプレゼンターからも学ぶことはたくさんありますが、同じように周りにいる出席者からも学びとれることがたくさんあります!
このチャンスを見逃さないでほしいのです。
たとえばカンファレンスでの朝食あるいは昼食時には、空いているテーブルを探さずに、一番込み合っているテーブルを探してそこに参加し、ぜひコミュニケーションをたくさん取ってほしいと思います!

Google IO 2013 レポート パート2

$
0
0

こんにちは。

Amebaにてもっぱらスマートフォン向けのサービスでフロントエンドをしている、斉藤祐也です。
Google IO 2013 レポート パート1を執筆したPatrickに引き続き、Google I/Oのレポートとなります。

2年前にGoogle I/Oに参加したPatrickとは違い、私にとっては初のGoogle I/Oであり、サンフランシスコ空港の外に出るのも初めての経験でした。

セッション自体は(おそらく)すべてGoogle I/Oのページから動画を閲覧できますし、英語ではありますが字幕も提供されていますので、ここでは細かいセッションの紹介については省略します。(私が参加したセッションを下記しますので興味があればぜひ動画をご覧ください)

昨年のGoogle I/Oでもパフォーマンスに関連するセッションはあったようですが今年はパフォーマンス関連のセッションが非常に多かったです。スケジュールが重複し惜しくも参加を断念したセッションも1つや2つではないほどでした。

Google I/Oではセッションの他にもPatrickも触れているSandboxなどのブースが数多く立ち並んでいましたが、私はセッションの合間や空き時間のたびにChromeチームのブースに足を運んでいました。
そこでもはやり話題の中心だったのがパフォーマンスについてでした。

パフォーマンス向上を啓蒙するためにブースにはColt McAnlis氏、Ilya Grigorik氏、そしてPaul Lewis氏というGoogleの中でもパフォーマンスに関するプロフェッショナルであり、私にとっては銀幕の向こうのスターのような存在である3人がブースに集まる様々な人(もちろん私も含めて)の質問に直接回答したりしていました。

Colt McAnlis氏がGoogle Glassを使って撮影したブースの様子がこちらにありますので盛況ぶりを確認できます。

Network、Compute、Render。

今年に入ってからというもの、この3つのキーワードに関連する動画やセッションをGoogleの関係者が多く発表しつづけています。
Google I/Oが終わった今でも、たとえば丁度明日から開催されるO’Reilly社主催のfluent conferenceや、こちらは当然ではありますが、同じくO’Reilly社主催のVelocity 2013でもパフォーマンス関連のセッションが多くあり、これらのカンファレンスでもこの3つのキーワードについて触れられることと思います。

これまでウェブサイトのパフォーマンスに関して興味を持っていた方はおそらくGoogleのHead Performance EngineerであるSteve Souders氏による「ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール」そして、「続・ハイパフォーマンスWebサイト ―ウェブ高速化のベストプラクティス」を読んでいると思いますが、「続・ハイパフォーマンス~」の発売から3年が過ぎ、次のステップに入っていくタイミングが今年なんだろうと感じることができる3日間でした。

$サイバーエージェント 公式エンジニアブログ
#perfmatters === Performance Matters === パフォーマンスを考慮しよう、という意味。Chromeブースでステッカーがたくさん配布されていました。

その成果もあってかGoogle社の人々が推進している「#perfmatters」というイニシアティブが浸透しはじめ、Google +はもちろんのこと、Twitterでも非常に活発に情報が共有されはじめています。

『パフォーマンスはウェブサイト、ウェブアプリにおいて特性となりえる重要な機能である。』

これはIlya Grigorik氏がセッションでの言葉ですが、私が今回のGoogle I/Oへの参加から得た共通のメッセージです。
先ほど紹介した「#perfmatters」というイニシアティブの他にも、2,461名のメンバーが登録しているGoogle +上のWeb Performanceコミュニティもパフォーマンスに関する多くの情報を得ることが出来ますのでご覧ください。

私自身も社内外でパフォーマンスに関するなんらかの活動を積極的にアッププットしていくつもりですので、本記事を読んでくださった皆さんも「#perfmatters」を日本でも盛り上げて行きましょう!

参加セッションリスト

あなたの知らない(かもしれない)パッケージ管理。

$
0
0

二回目を書いた理由。


こんにちは、二回目の登場の前田です。ブログの運営さんから後述の宣伝をしてもよいからブログ書かないか?というバーターで引き受けました。二つ返事で引き受けたものの、特にネタを考えていなかったので締め切り迫って途方にくれました。


もっとも、よくよく考えたら私が仕事で普段やっている内容も、他の人があまり人がやらないものが多い上、一般受けしそうなネタも持ってないのでした。ですので、以前使うことのあったパッケージ関連のネタについて書きたいと思います。


パッケージを扱う


パッケージといってもいろんな種類がありますが、今回は Debian で RPM を扱う方法についてです…。








ウソです。




Debian には、 rpm, rpm2cpio, yum, createrepo などの Debian パッケージが存在します。これらのパッケージをインストールすれば、 Debian 上で RPM パッケージを作ったり、 YUM のリポジトリを作成したり、といったことも普通にできます(*1)。ですが別にこの話ではありません。


ネタとして扱うのはやはり Debian パッケージと RPM を扱う方法についてです。普通は Debian パッケージなら APT や dpkg コマンドを、 RPM なら yum コマンドや rpm コマンドを使いますが、今回はそれらを python で扱う方法についてお話します。前者は libapt-pkg ライブラリのバインディングである python-apt を、後者は librpm ライブラリへのバインディングである python-rpm を使います(*2)。それぞれ開発元によってドキュメントが公開されています。(参考文献参照)


事前準備


環境としては、Debian GNU/Linux Sid(Jessie/Sid)を、 Python のバージョンは 2.7.3 を使います。 Python3 理由は単に Python3 対応の python-rpm パッケージがまだ無いためです。


さて、 python-apt を使う場合には python-apt パッケージをインストールします。 Python3 版を使いたい人は python3-apt パッケージをインストールして下さい。


$ sudo apt-get install python-apt

python-rpm を使う場合には、同様に python-rpm パッケージをインストールして下さい。


$ sudo apt-get install python-rpm

普段、職場でサーバとして使っている Ubuntu 12.04 LTS の環境や、先日リリースされた、Debian GNU/Linux Wheezy でもほぼ同じです。RHEL系の環境は知りませんので、もし使いたければご自分で調べてみて下さい。


python-apt を使う


python-apt は、次のようのことができます。


  • APT Lineの情報を変更
  • パッケージアーカイブの情報を取得
  • パッケージをインストール、アンインストール
  • ローカルのパッケージデータベースの情報を扱う
  • ローカルの .deb ファイルを扱う


今回はそのうち、ローカルのパッケージデータベース最後の二点について説明します。これらを選んだのは、前述の通り、諸事情で使ったことがあるから、というただそれだけの理由です。


APT経由でのパッケージ管理


まず、ローカルのパッケージデータベースの情報を扱う方法についてからですが、 apt モジュールの Cache クラスを使います。あるパッケージのチェックを行うには、下記のようにします。


>>> import apt
>>> cache = apt.Cache()
>>> cache['bash']
<Package: name:'bash' architecure='amd64' id:742L>

apt-cache search コマンドで見つけられるパッケージの場合には上記のような表示になります。一方、実際には存在しないパッケージ名(例えば"hoge"など)を指定した場合には KeyError exception が発生します。パッケージがインストール状態を調べるには is_install プロパティを使います。


>>> cache['bash'].is_installed
True
>>> cache['libpython2.6'].is_installed
False

root 権限があれば、パッケージのインストール、削除などもできます。


$ sudo python
>>> import apt
>>> cache = apt.Cache()
>>> cache['zsh'].is_installed
False
>>> cache['zsh'].mark_install()
>>> cache['zsh'].marked_install
True
>>> cache.commit()
Selecting previously unselected package zsh-common.
(Reading database ... 269347 files and directories currently installed.)
Unpacking zsh-common (from .../zsh-common_5.0.2-3_all.deb) ...
Selecting previously unselected package zsh.
Unpacking zsh (from .../archives/zsh_5.0.2-3_amd64.deb) ...
Processing triggers for man-db ...
Processing triggers for menu ...
Setting up zsh-common (5.0.2-3) ...
Installing new version of config file /etc/zsh/zshrc ...
Setting up zsh (5.0.2-3) ...
update-alternatives: using /bin/zsh5 to provide /bin/zsh (zsh) in auto mode
update-alternatives: using /bin/zsh5 to provide /bin/rzsh (rzsh) in auto mode
Processing triggers for menu ...
[master 3de9c60] committing changes in /etc after apt run
 Author: mkouhei >mkouhei@testnode<
 7 files changed, 111 insertions(+), 43 deletions(-)
 create mode 120000 alternatives/rzsh
 create mode 120000 alternatives/rzsh.1.gz
 create mode 120000 alternatives/zsh
 create mode 120000 alternatives/zsh-usrbin
 rewrite zsh/zshrc (88%)
True

この直後に is_installed プロパティでインストールの状態を見ると、cache オブジェクト自体は更新されていないため False が返ってきます。


>>> cache['zsh'].is_installed
False

ですので、最新状態に反映するには、 open() メソッドを使います。


>>> cache.open()
>>> cache['zsh'].is_installed
True

パッケージを削除する場合には、 mark_delete() メソッドを使います。これは apt-get remove に相当します。


>>> cache['zsh'].marked_delete
False
>>> cache['zsh'].mark_delete()
>>> cache['zsh'].marked_delete
True
>>> cache.commit()            
(Reading database ... 270508 files and directories currently installed.)
Removing zsh ...
Processing triggers for menu ...
Processing triggers for man-db ...
[master 5e8a38d] committing changes in /etc after apt run
 Author: mkouhei <mkouhei@testnode>
 9 files changed, 115 insertions(+), 125 deletions(-)
 delete mode 120000 alternatives/ksh
 delete mode 120000 alternatives/ksh.1.gz
 delete mode 120000 alternatives/rzsh
 delete mode 120000 alternatives/rzsh.1.gz
 delete mode 120000 alternatives/usr.bin.ksh
 delete mode 120000 alternatives/zsh
 delete mode 120000 alternatives/zsh-usrbin
True
>>> cache.open()
>>> cache['zsh'].is_installed
False


ローカルのパッケージファイルの操作


次にローカルのパッケージファイルからメタ情報を取得する方法について説明します。まず、 apt_inst モジュールの DebFile クラスでローカルの Debian バイナリパッケージを読み込みます。


>>> import apt_inst
zsh_deb = '/var/cache/apt/archives/zsh_5.0.2-3_amd64.deb'
>>> deb_obj = apt_inst.DebFile(zsh_deb)

メタ情報を取得するにはこの DebFile オブジェクトの control プロパティで取得したオブジェクトを extractdata() メソッドを使って文字列に変換します。


>>> control_s = deb_obj.control.extractdata('control')
>>> 'Package: zsh\nVersion: 5.0.2-3\nArchitecture: amd64\nMaintainer: Debian Zsh Maintainers <pkg-zsh-devel@lists.alioth.debian.org>\nInstalled-Size: 1836\nPre-Depends: dpkg (>= 1.15.6~)\nDepends: libc6 (>= 2.15), libcap2 (>= 2.10), libtinfo5, zsh-common (= 5.0.2-3)\nRecommends: libncursesw5 (>= 5.6+20070908), libpcre3 (>= 8.10)\nSuggests: zsh-doc\nSection: shells\nPriority: optional\nHomepage: http://www.zsh.org/\nDescription: shell with lots of features\n Zsh is a UNIX command interpreter (shell) usable as an\n interactive login shell and as a shell script command\n processor. Of the standard shells, zsh most closely resembles\n ksh but includes many enhancements. Zsh has command-line editing,\n built-in spelling correction, programmable command completion,\n shell functions (with autoloading), a history mechanism, and a\n host of other features.\n'

control ファイルの文字列を取得したら、これを apt_pkg モジュールの TagSection クラスを使ってパースします。


>>> import apt_pkg
>>> tag_section = apt_pkg.TagSection(control_s)

apt_pkg.TagSection オブジェクトは、次のメタ情報を持っています。


>>> tag_section.keys()
['Package',
 'Version',
 'Architecture',
 'Maintainer',
 'Installed-Size',
 'Pre-Depends',
 'Depends',
 'Recommends',
 'Suggests',
 'Section',
 'Priority',
 'Homepage',
 'Description']

get() メソッドで文字列としてメタ情報を取得できます。


>>> tag_section.get('Package')
'zsh'
>>> tag_section.get('Version')
'5.0.2-3'
>>> tag_section.get('Architecture')
'amd64'

python-rpm を使う


さて今度は python-rpm を見てみます。こちらについては、ローカルのパッケージファイルからメタ情報を取得するだけの紹介とします(*3)。
python-rpm では rpm.TransactionSet のインスタンスの生成が必須です。


>>> import rpm
>>> import os
>>> ts = rpm.TransactionSet()

ローカルの rpm ファイルを扱う際、GPG での署名が無いパッケージは必ずエラーになります(*4)。もし、署名無しのパッケージを扱う場合は、rpm._RPMVSF_NOSIGNATURES を引数にして setVSFlags() メソッドを実行する必要があります(*5)。


>>> ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES)
983040

次に、RPM パッケージファイルを読み込みます。これはファイルディスクリプタを ts.hdrFromFDno() メソッドに渡します。


>>> fd = os.open('git-all-1.7.1-3.el6_4.1.noarch.rpm', os.O_RDONLY)
>>> header = ts.hdrFromFDno(fd)

このときに読み込んだファイルが RPM でなければ、 TypeError exception が発生します。ヘッダ情報を読み込めたら、ファイルディスクリプタは必ず close() しておきましょう。


>>> os.close(fd)

あとは header から欲しいメタ情報を取得するだけです。が! header.keys() を実行しても、悲しいことに数値しか返ってきません。これでは欲しい情報がどれか分かりません。


>>> header.keys()
[100,
 257,
 259,
 261,
 268,
 269,
 1000,
 1001,
 1002,
 1004,
 1005,
 1006,
 1007,
 1009,
 1011,
 1014,
 1015,
 1016,
 1020,
 1021,
 1022,
(snip)
 1126,
 1132,
 5011]

例えばパッケージ名は header['name'] で取得できるのですが、どの数値が name に相当するのかは分かりません。無論、これらの数値をキーにすれば値は取得できます。しかし、返り値から欲しい情報を類推するのはナンセンスですね。しかも、一部はバイナリデータを返すので python のインタラクティブモードや ipython などでうっかり

>>> for i in header: print(header[i])

などと実行しようものなら、コンソールが文字化けしてしまいます。


実は、この数値とタグ名のマッピングは librpm ライブラリの rpmtag.h に記述されています。 Debian では librpm-dev パッケージの、 /usr/include/rpm/rpmtag.h になります。このパッケージをインストールし、中を見ると下記のようになっています。


(snip)
    RPMTAG_NAME                 = 1000, /* s */
#define RPMTAG_N        RPMTAG_NAME     /* s */
    RPMTAG_VERSION              = 1001, /* s */
#define RPMTAG_V        RPMTAG_VERSION  /* s */
    RPMTAG_RELEASE              = 1002, /* s */
#define RPMTAG_R        RPMTAG_RELEASE  /* s */
    RPMTAG_EPOCH                = 1003, /* i */
#define RPMTAG_E        RPMTAG_EPOCH    /* i */
    RPMTAG_SUMMARY              = 1004, /* s{} */
    RPMTAG_DESCRIPTION          = 1005, /* s{} */
    RPMTAG_BUILDTIME            = 1006, /* i */
    RPMTAG_BUILDHOST            = 1007, /* s */
    RPMTAG_INSTALLTIME          = 1008, /* i */
    RPMTAG_SIZE                 = 1009, /* i */
    RPMTAG_DISTRIBUTION         = 1010, /* s */
    RPMTAG_VENDOR               = 1011, /* s */
    RPMTAG_GIF                  = 1012, /* x */
    RPMTAG_XPM                  = 1013, /* x */
    RPMTAG_LICENSE              = 1014, /* s */
    RPMTAG_PACKAGER             = 1015, /* s */
    RPMTAG_GROUP                = 1016, /* s{} */
    RPMTAG_CHANGELOG            = 1017, /* s[] internal */
    RPMTAG_SOURCE               = 1018, /* s[] */
    RPMTAG_PATCH                = 1019, /* s[] */
    RPMTAG_URL                  = 1020, /* s */
    RPMTAG_OS                   = 1021, /* s legacy used int */
    RPMTAG_ARCH                 = 1022, /* s legacy used int */
(snip)

prefix である "RPMTAG_" を取り除いて小文字にしたものが rpm.hdr オブジェクトに渡すキーになります。なので、 "rpm -qip some.rpm" を実行して表示されるメタ情報を取得するには下記のようになります。


>>> header['name'], header['summary'], header['packager'], header['buildtime'], header['version'], header['release'], header['arch'], header['sourcerpm']
('git-all',
 'Meta-package to pull in all git tools',
 'CentOS BuildSystem ',
 1362435563L,
 '1.7.1',
 '3.el6_4.1',
 'noarch',
 'git-1.7.1-3.el6_4.1.src.rpm')

まとめ


以上、 python-apt と python-rpm の機能の一部を紹介しました。これらはどちらも前述の通り、公式ドキュメントが充実しているのですが、前述の rpmtag.h での rpm.hdr オブジェクトで使う key のマッピングについては載っていなかったりします。今回紹介した内容が読者の皆さんにお役に立てば幸いです。


といっても、今回の内容はそもそも使う人が限定されるので、かなり誰得な感じですね。


参考文献


python-apt
python-apt v0.8.0 documentation
python-rpm
Chapter 16. Programming RPM with Python



(バーターでもらった)宣伝コーナー



さて、(私にとっての)本題です。


既にご存知の方もいらっしゃるかと思いますが、来る6月29日(土)に大統一Debian勉強会 2013が開催されます。


2回目の今年は東京での開催です。CFP(Call for presentation)の募集は既に終わり、セッションテーブルも公開されていますが、LTは当日まで募集しています。また、アンカンファレンスも開催予定です。Debian関連ネタをお持ちの方はぜひ応募してみてください。一般参加の申し込みも5/29(水)から始まっています。 Debian 勉強会ではおなじみの事前配布資料は今回はスポンサー様からの支援もあって(*6)、年二回の"あんどきゅめんてっどでびあん"と同様の装丁の冊子として、先着で配布できることになりました。


なお、弊社からは私と、私と同じチームの某さんの二人が発表できることになりました(*7)。某さんが誰なのか&発表内容が気になる人は当日ぜひ会場へ!


ぜひぜひ、たくさんの方のご参加をお待ちしております。(以上宣伝終わり。)




脚注

  1. RPM を作ることができてもそれをそのまま使うか、と言えばそれは別ですね。
  2. これ以外にも、 Smart Package Manager というRPM, Debian パッケージ, Slackware などのリポジトリを扱うことのできるツールがあります。これにも python バインディングもあるようです。)それぞれ開発元によってドキュメントが公開されています。
  3. 単に以前使ったのがこの機能だけなためです。 rpm で Debian にパッケージをインストールしたくないですしね。
  4. 私は Debian パッケージを作成する場合、サインするのが当たり前だったのですが、以前 python-rpm を使ってツールを作った時の都合上、サイン無しの RPM パッケージを扱う必要がありました。
  5. fedora のドキュメント "Setting the verification flags" を参照

  6. 弊社もシルバースポンサーおよび、ペットボトル(ミネラルウォーター)の配布での協賛となっています。
  7. 念の為補足しておくと、スポンサーだからというわけではなく、二人ともCFPが選考されたからです。ちなみに他の実行委員も、もう一人が誰なのかは多分知らないと思います。




English Android Meetup

$
0
0

Hello, I am Patrick Boos. I am a developer at CyberAgent, Inc.

After more than a year of not having Android Meetups for the foreign community in english, a meetup has been held again. CyberAgent provided rooms in Shibuya for this meetup to take place.
A year and a half ago when the last meetup was held there were about 10 people who participated. This time there were 19 people attending. This shows, that the interest in such kind of meetup has risen and we will try to make this more regularly.

サイバーエージェント 公式エンジニアブログ-People サイバーエージェント 公式エンジニアブログ-Presentation

This meetup took place the week after Google IO and so one topic was the announcements made at Google IO. The rest of the time people presented projects they have been working on, discussing topics like testing on Android or asking and answering questions.
We hope to make this meetup a place where people can come to learn, share, support, present, meet, network and to get inspired and motivated.

Hope to see you there again next month.

Viewing all 161 articles
Browse latest View live